| import { useState, memo } from 'react'; | |
| import { useRecoilState } from 'recoil'; | |
| import * as Select from '@ariakit/react/select'; | |
| import { FileText, LogOut } from 'lucide-react'; | |
| import { LinkIcon, GearIcon, DropdownMenuSeparator, Avatar } from '@librechat/client'; | |
| import { useGetStartupConfig, useGetUserBalance } from '~/data-provider'; | |
| import FilesView from '~/components/Chat/Input/Files/FilesView'; | |
| import { useAuthContext } from '~/hooks/AuthContext'; | |
| import { useLocalize } from '~/hooks'; | |
| import Settings from './Settings'; | |
| import store from '~/store'; | |
| function AccountSettings() { | |
| const localize = useLocalize(); | |
| const { user, isAuthenticated, logout } = useAuthContext(); | |
| const { data: startupConfig } = useGetStartupConfig(); | |
| const balanceQuery = useGetUserBalance({ | |
| enabled: !!isAuthenticated && startupConfig?.balance?.enabled, | |
| }); | |
| const [showSettings, setShowSettings] = useState(false); | |
| const [showFiles, setShowFiles] = useRecoilState(store.showFiles); | |
| return ( | |
| <Select.SelectProvider> | |
| <Select.Select | |
| aria-label={localize('com_nav_account_settings')} | |
| data-testid="nav-user" | |
| className="mt-text-sm flex h-auto w-full items-center gap-2 rounded-xl p-2 text-sm transition-all duration-200 ease-in-out hover:bg-surface-hover" | |
| > | |
| <div className="-ml-0.9 -mt-0.8 h-8 w-8 flex-shrink-0"> | |
| <div className="relative flex"> | |
| <Avatar user={user} size={32} /> | |
| </div> | |
| </div> | |
| <div | |
| className="mt-2 grow overflow-hidden text-ellipsis whitespace-nowrap text-left text-text-primary" | |
| style={{ marginTop: '0', marginLeft: '0' }} | |
| > | |
| {user?.name ?? user?.username ?? localize('com_nav_user')} | |
| </div> | |
| </Select.Select> | |
| <Select.SelectPopover | |
| className="popover-ui w-[235px]" | |
| style={{ | |
| transformOrigin: 'bottom', | |
| marginRight: '0px', | |
| translate: '0px', | |
| }} | |
| > | |
| <div className="text-token-text-secondary ml-3 mr-2 py-2 text-sm" role="note"> | |
| {user?.email ?? localize('com_nav_user')} | |
| </div> | |
| <DropdownMenuSeparator /> | |
| {startupConfig?.balance?.enabled === true && balanceQuery.data != null && ( | |
| <> | |
| <div className="text-token-text-secondary ml-3 mr-2 py-2 text-sm" role="note"> | |
| {localize('com_nav_balance')}:{' '} | |
| {new Intl.NumberFormat().format(Math.round(balanceQuery.data.tokenCredits))} | |
| </div> | |
| <DropdownMenuSeparator /> | |
| </> | |
| )} | |
| <Select.SelectItem | |
| value="" | |
| onClick={() => setShowFiles(true)} | |
| className="select-item text-sm" | |
| > | |
| <FileText className="icon-md" aria-hidden="true" /> | |
| {localize('com_nav_my_files')} | |
| </Select.SelectItem> | |
| {startupConfig?.helpAndFaqURL !== '/' && ( | |
| <Select.SelectItem | |
| value="" | |
| onClick={() => window.open(startupConfig?.helpAndFaqURL, '_blank')} | |
| className="select-item text-sm" | |
| > | |
| <LinkIcon aria-hidden="true" /> | |
| {localize('com_nav_help_faq')} | |
| </Select.SelectItem> | |
| )} | |
| <Select.SelectItem | |
| value="" | |
| onClick={() => setShowSettings(true)} | |
| className="select-item text-sm" | |
| > | |
| <GearIcon className="icon-md" aria-hidden="true" /> | |
| {localize('com_nav_settings')} | |
| </Select.SelectItem> | |
| <DropdownMenuSeparator /> | |
| <Select.SelectItem | |
| aria-selected={true} | |
| onClick={() => logout()} | |
| value="logout" | |
| className="select-item text-sm" | |
| > | |
| <LogOut className="icon-md" /> | |
| {localize('com_nav_log_out')} | |
| </Select.SelectItem> | |
| </Select.SelectPopover> | |
| {showFiles && <FilesView open={showFiles} onOpenChange={setShowFiles} />} | |
| {showSettings && <Settings open={showSettings} onOpenChange={setShowSettings} />} | |
| </Select.SelectProvider> | |
| ); | |
| } | |
| export default memo(AccountSettings); | |