Files
medreport_mrb2b/app/home/(user)/_components/home-mobile-navigation.tsx
2025-10-08 16:32:19 +03:00

223 lines
6.8 KiB
TypeScript

'use client';
import { useMemo } from 'react';
import Link from 'next/link';
import { StoreCart } from '@medusajs/types';
import { Cross, Menu, Shield, ShoppingCart, UserCircle } from 'lucide-react';
import { usePersonalAccountData } from '@kit/accounts/hooks/use-personal-account-data';
import { ApplicationRoleEnum } from '@kit/accounts/types/accounts';
import SignOutDropdownItem from '@kit/shared/components/sign-out-dropdown-item';
import DropdownLink from '@kit/shared/components/ui/dropdown-link';
import {
pathsConfig,
personalAccountNavigationConfig,
} from '@kit/shared/config';
import { useSignOut } from '@kit/supabase/hooks/use-sign-out';
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@kit/ui/dropdown-menu';
import { If } from '@kit/ui/if';
import { cn } from '@kit/ui/shadcn';
import { Avatar, AvatarFallback, AvatarImage } from '@kit/ui/shadcn/avatar';
import { Button } from '@kit/ui/shadcn/button';
import { Trans } from '@kit/ui/trans';
// home imports
import type { UserWorkspace } from '../_lib/server/load-user-workspace';
import { UserNotifications } from './user-notifications';
const PERSONAL_ACCOUNT_SLUG = 'personal';
export function HomeMobileNavigation(props: {
workspace: UserWorkspace;
cart: StoreCart | null;
}) {
const { user, accounts } = props.workspace;
const signOut = useSignOut();
const { data: personalAccountData } = usePersonalAccountData(user.id);
const Links = personalAccountNavigationConfig.routes.map((item, index) => {
if ('children' in item) {
return item.children.map((child) => {
return (
<DropdownLink
key={child.path}
Icon={child.Icon}
path={child.path}
label={child.label}
/>
);
});
}
if ('divider' in item) {
return <DropdownMenuSeparator key={index} />;
}
});
const hasTotpFactor = useMemo(() => {
const factors = user?.factors ?? [];
return factors.some(
(factor) => factor.factor_type === 'totp' && factor.status === 'verified',
);
}, [user?.factors]);
const isSuperAdmin = useMemo(() => {
const hasAdminRole =
personalAccountData?.application_role === ApplicationRoleEnum.SuperAdmin;
return hasAdminRole && hasTotpFactor;
}, [user, personalAccountData, hasTotpFactor]);
const isDoctor = useMemo(() => {
const hasDoctorRole =
personalAccountData?.application_role === ApplicationRoleEnum.Doctor;
return hasDoctorRole && hasTotpFactor;
}, [user, personalAccountData, hasTotpFactor]);
const cartQuantityTotal =
props.cart?.items?.reduce((acc, item) => acc + item.quantity, 0) ?? 0;
const hasCartItems = cartQuantityTotal > 0;
return (
<DropdownMenu>
<div className="flex justify-between gap-3">
<Link href={pathsConfig.app.cart}>
<Button
variant="ghost"
className="relative mr-0 h-10 cursor-pointer border-1 px-4 py-2"
>
<ShoppingCart className="stroke-[1.5px]" />
{hasCartItems && (
<>
(
<span className="text-success font-bold">
{cartQuantityTotal}
</span>
)
</>
)}
</Button>
</Link>
<UserNotifications userId={user.id} />
<DropdownMenuTrigger>
<Menu className="h-6 w-6" />
</DropdownMenuTrigger>
</div>
<DropdownMenuContent sideOffset={10} className={'w-screen rounded-none'}>
<If condition={props.cart && hasCartItems}>
<DropdownMenuGroup>
<DropdownLink
path={pathsConfig.app.cart}
label="common:shoppingCartCount"
Icon={<ShoppingCart className="stroke-[1.5px]" />}
labelOptions={{ count: cartQuantityTotal }}
/>
</DropdownMenuGroup>
<DropdownMenuSeparator />
</If>
<DropdownMenuGroup>
{Links}
<DropdownLink
Icon={<UserCircle className="w-4 stroke-[1.5px]" />}
path={pathsConfig.app.personalAccountSettings}
label="common:routes.profile"
/>
</DropdownMenuGroup>
<If condition={isSuperAdmin}>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
className={
's-full flex cursor-pointer items-center space-x-2 text-yellow-700 dark:text-yellow-500'
}
href={pathsConfig.app.admin}
>
<Shield className={'h-5'} />
<span>Super Admin</span>
</Link>
</DropdownMenuItem>
</If>
<If condition={isDoctor}>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link
className={
'flex h-full cursor-pointer items-center space-x-2 text-yellow-700 dark:text-yellow-500'
}
href={pathsConfig.app.doctor}
>
<Cross className={'h-5'} />
<span>
<Trans i18nKey="common:doctor" />
</span>
</Link>
</DropdownMenuItem>
</If>
<DropdownMenuSeparator />
<If condition={accounts.length > 0}>
<span className="text-muted-foreground px-2 text-xs">
<Trans
i18nKey={'teams:yourTeams'}
values={{ teamsCount: accounts.length }}
/>
</span>
{accounts.map((account) => (
<DropdownMenuItem key={account.value} asChild>
<Link
className={'s-full flex cursor-pointer items-center space-x-2'}
href={`${pathsConfig.app.home}/${account.value}`}
>
<div className={'flex items-center'}>
<Avatar className={'h-5 w-5 rounded-xs ' + account.image}>
<AvatarImage
{...(account.image && { src: account.image })}
/>
<AvatarFallback
className={cn('rounded-md', {
['bg-background']:
PERSONAL_ACCOUNT_SLUG === account.value,
['group-hover:bg-background']:
PERSONAL_ACCOUNT_SLUG !== account.value,
})}
>
{account.label ? account.label[0] : ''}
</AvatarFallback>
</Avatar>
<span className={'pl-3'}>{account.label}</span>
</div>
</Link>
</DropdownMenuItem>
))}
<DropdownMenuSeparator />
</If>
<SignOutDropdownItem onSignOut={() => signOut.mutateAsync()} />
</DropdownMenuContent>
</DropdownMenu>
);
}