This commit is contained in:
2024-04-21 14:42:52 +02:00
parent 4b69674ede
commit 8a25f53c99
10700 changed files with 55767 additions and 14201 deletions

View File

@ -0,0 +1,25 @@
import { ReactNode } from 'react'
import { Circle } from '@chakra-ui/react'
import { variables } from '@/lib'
import { useAppSelector } from '@/store/hook'
import { NavType } from '@/store/ui/nav'
export type AccountMenuActiveCircleProps = {
children?: ReactNode
}
const AccountMenuActiveCircle = ({
children,
}: AccountMenuActiveCircleProps) => {
const activeNav = useAppSelector((state) => state.ui.nav.active)
return (
<Circle
size="50px"
bg={activeNav === NavType.Account ? variables.gradiant : 'transparent'}
>
{children}
</Circle>
)
}
export default AccountMenuActiveCircle

View File

@ -0,0 +1,36 @@
import { Avatar } from '@chakra-ui/react'
import { forwardRef } from '@chakra-ui/system'
import cx from 'classnames'
import { User } from '@/client/idp/user'
import { useAppSelector } from '@/store/hook'
import { NavType } from '@/store/ui/nav'
import AccountMenuActiveCircle from './account-menu-active-circle'
export type AccountMenuAvatarButtonProps = {
user: User
}
const AccountMenuAvatarButton = forwardRef<AccountMenuAvatarButtonProps, 'div'>(
({ user, ...props }, ref) => {
const activeNav = useAppSelector((state) => state.ui.nav.active)
const isActive = activeNav === NavType.Account
return (
<div ref={ref} {...props} className={cx('cursor-pointer')}>
<AccountMenuActiveCircle>
<Avatar
name={user.fullName}
src={user.picture}
size="sm"
className={cx('w-[40px]', 'h-[40px]', {
'border': isActive,
'border-gray-300': isActive,
'dark:border-gray-700': isActive,
})}
/>
</AccountMenuActiveCircle>
</div>
)
},
)
export default AccountMenuAvatarButton

View File

@ -0,0 +1,24 @@
import { Avatar } from '@chakra-ui/react'
import cx from 'classnames'
import { User } from '@/client/idp/user'
export type AccountMenuAvatarImageProps = {
user: User
}
const AccountMenuAvatarImage = ({ user }: AccountMenuAvatarImageProps) => (
<Avatar
name={user.fullName}
src={user.picture}
size="sm"
className={cx(
'w-[40px]',
'h-[40px]',
'border',
'border-gray-300',
'dark:border-gray-700',
)}
/>
)
export default AccountMenuAvatarImage

View File

@ -0,0 +1,71 @@
import { Link } from 'react-router-dom'
import {
Menu,
MenuButton,
MenuDivider,
MenuItem,
MenuList,
Portal,
SkeletonCircle,
} from '@chakra-ui/react'
import cx from 'classnames'
import UserAPI from '@/client/idp/user'
import { swrConfig } from '@/client/options'
import AccountMenuActiveCircle from './account-menu-active-circle'
import AccountMenuAvatarButton from './account-menu-avatar-button'
import AccountMenuAvatarImage from './account-menu-avatar-image'
const TopBarAccountMenu = () => {
const { data: user } = UserAPI.useGet(swrConfig())
if (user) {
return (
<Menu>
<MenuButton as={AccountMenuAvatarButton} user={user} />
<Portal>
<MenuList>
<div
className={cx(
'flex',
'flex-row',
'items-center',
'gap-0.5',
'px-1',
)}
>
<AccountMenuAvatarImage user={user} />
<div className={cx('flex', 'flex-col', 'gap-0')}>
<span
className={cx(
'font-semibold',
'grow',
'text-ellipsis',
'overflow-hidden',
'whitespace-nowrap',
)}
>
{user.fullName}
</span>
<span className={cx('text-gray-500')}>{user.email}</span>
</div>
</div>
<MenuDivider />
<MenuItem as={Link} to="/account/settings">
Account
</MenuItem>
<MenuItem as={Link} to="/sign-out" className={cx('text-red-500')}>
Sign Out
</MenuItem>
</MenuList>
</Portal>
</Menu>
)
} else {
return (
<AccountMenuActiveCircle>
<SkeletonCircle size="40px" />
</AccountMenuActiveCircle>
)
}
}
export default TopBarAccountMenu