194 lines
5.1 KiB
TypeScript
194 lines
5.1 KiB
TypeScript
'use client';
|
|
|
|
import { useMemo } from 'react';
|
|
|
|
import Link from 'next/link';
|
|
|
|
import { StoreCart } from '@medusajs/types';
|
|
import { Cross, LogOut, Menu, Shield, ShoppingCart } from 'lucide-react';
|
|
|
|
import { usePersonalAccountData } from '@kit/accounts/hooks/use-personal-account-data';
|
|
import { ApplicationRoleEnum } from '@kit/accounts/types/accounts';
|
|
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 { Trans } from '@kit/ui/trans';
|
|
|
|
// home imports
|
|
import type { UserWorkspace } from '../_lib/server/load-user-workspace';
|
|
|
|
export function HomeMobileNavigation(props: {
|
|
workspace: UserWorkspace;
|
|
cart: StoreCart | null;
|
|
}) {
|
|
const user = props.workspace.user;
|
|
|
|
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>
|
|
<DropdownMenuTrigger>
|
|
<Menu className={'h-9'} />
|
|
</DropdownMenuTrigger>
|
|
|
|
<DropdownMenuContent sideOffset={10} className={'w-screen rounded-none'}>
|
|
<If condition={props.cart && hasCartItems}>
|
|
<DropdownMenuGroup>
|
|
<DropdownLink
|
|
path="/home/cart"
|
|
label="common:shoppingCartCount"
|
|
Icon={<ShoppingCart className="stroke-[1.5px]" />}
|
|
labelOptions={{ count: cartQuantityTotal }}
|
|
/>
|
|
</DropdownMenuGroup>
|
|
<DropdownMenuSeparator />
|
|
</If>
|
|
|
|
<DropdownMenuGroup>{Links}</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 />
|
|
|
|
<SignOutDropdownItem onSignOut={() => signOut.mutateAsync()} />
|
|
</DropdownMenuContent>
|
|
</DropdownMenu>
|
|
);
|
|
}
|
|
|
|
function DropdownLink(
|
|
props: React.PropsWithChildren<{
|
|
path: string;
|
|
label: string;
|
|
labelOptions?: Record<string, any>;
|
|
Icon: React.ReactNode;
|
|
}>,
|
|
) {
|
|
return (
|
|
<DropdownMenuItem asChild key={props.path}>
|
|
<Link
|
|
href={props.path}
|
|
className={'flex h-12 w-full items-center space-x-4'}
|
|
>
|
|
{props.Icon}
|
|
|
|
<span>
|
|
<Trans
|
|
i18nKey={props.label}
|
|
defaults={props.label}
|
|
values={props.labelOptions}
|
|
/>
|
|
</span>
|
|
</Link>
|
|
</DropdownMenuItem>
|
|
);
|
|
}
|
|
|
|
function SignOutDropdownItem(
|
|
props: React.PropsWithChildren<{
|
|
onSignOut: () => unknown;
|
|
}>,
|
|
) {
|
|
return (
|
|
<DropdownMenuItem
|
|
className={'flex h-12 w-full items-center space-x-4'}
|
|
onClick={props.onSignOut}
|
|
>
|
|
<LogOut className={'h-6'} />
|
|
|
|
<span>
|
|
<Trans i18nKey={'common:signOut'} defaults={'Sign out'} />
|
|
</span>
|
|
</DropdownMenuItem>
|
|
);
|
|
}
|