ui phase 2
This commit is contained in:
@@ -1,33 +1,64 @@
|
||||
'use client';
|
||||
import { FunctionComponent, PropsWithChildren, useMemo } from 'react';
|
||||
import { useTranslations } from 'next-intl';
|
||||
import { Stack } from '@mui/material';
|
||||
import { NotificationBell } from '@/components/notifications';
|
||||
import { ProfileSummary } from '@/components';
|
||||
import { ROUTES } from '@/constants';
|
||||
import { LinkToPage } from '@/utils';
|
||||
import { useMe } from '@/services/auth';
|
||||
import { useNurseProfile } from '@/services/profiles';
|
||||
import { useVerificationStatus } from '@/services/verification';
|
||||
import { ownBadgeState } from '@/services/verification/types';
|
||||
import TopBarAndSideBarLayout from './TopBarAndSideBarLayout';
|
||||
import { BottomBar } from './components';
|
||||
import ActorSwitcher from './components/ActorSwitcher';
|
||||
|
||||
/** A "more" bottom-nav tab isn't a real route — this sentinel never matches a pathname. */
|
||||
const MORE_TAB_PATH = '#more';
|
||||
|
||||
/**
|
||||
* Nurse app shell — the "نمای پرستار" experience (verification, dashboard, EVV visits).
|
||||
* Uses the shared TopBar + SideBar engine: a temporary drawer on mobile, persistent on
|
||||
* desktop. Nav is role-scoped to the nurse routes.
|
||||
* Nurse app shell — the "نمای پرستار" workspace. Sectioned sidebar (امروز/حرفهٔ من/مالی/پشتیبانی)
|
||||
* with a real `ProfileSummary` identity card (name, masked phone, own `TrustBadge`), plus a 5-tab
|
||||
* mobile bottom nav whose «بیشتر» tab opens the same sidebar drawer for the remaining items.
|
||||
* @layout NurseLayout
|
||||
*/
|
||||
const NurseLayout: FunctionComponent<PropsWithChildren> = ({ children }) => {
|
||||
const t = useTranslations('nav');
|
||||
const tShell = useTranslations('shell');
|
||||
|
||||
const sidebarItems: Array<LinkToPage> = useMemo(
|
||||
() => [
|
||||
const { data: me } = useMe();
|
||||
const { data: nurseProfile } = useNurseProfile();
|
||||
const { data: verification } = useVerificationStatus();
|
||||
|
||||
const identityLoading = !me;
|
||||
const displayName = me ? [me.firstName, me.lastName].filter(Boolean).join(' ').trim() || me.phone : '';
|
||||
|
||||
const sidebarItems: Array<LinkToPage> = useMemo(() => {
|
||||
const groupToday = t('group_today');
|
||||
const groupProfession = t('group_profession');
|
||||
const groupFinance = t('group_finance');
|
||||
const groupSupport = t('group_support');
|
||||
return [
|
||||
{ title: t('dashboard'), path: ROUTES.NURSE, icon: 'dashboard', group: groupToday },
|
||||
{ title: t('requests'), path: ROUTES.NURSE_REQUESTS, icon: 'requests', group: groupToday },
|
||||
{ title: t('visits'), path: ROUTES.NURSE_VISITS, icon: 'visits', group: groupToday },
|
||||
{ title: t('profile'), path: ROUTES.NURSE_PROFILE, icon: 'profile', group: groupProfession },
|
||||
{ title: t('services'), path: ROUTES.NURSE_SERVICES, icon: 'services', group: groupProfession },
|
||||
{ title: t('coverage'), path: ROUTES.NURSE_COVERAGE, icon: 'coverage', group: groupProfession },
|
||||
{ title: t('verification'), path: ROUTES.NURSE_VERIFICATION, icon: 'verification', group: groupProfession },
|
||||
{ title: t('earnings'), path: ROUTES.NURSE_EARNINGS, icon: 'earnings', group: groupFinance },
|
||||
{ title: t('bank'), path: ROUTES.NURSE_BANK, icon: 'bank', group: groupFinance },
|
||||
{ title: t('support'), path: ROUTES.NURSE_SUPPORT_TICKETS, icon: 'support', group: groupSupport },
|
||||
];
|
||||
}, [t]);
|
||||
|
||||
const mobileTabs = useMemo(
|
||||
(): Array<LinkToPage> => [
|
||||
{ title: t('dashboard'), path: ROUTES.NURSE, icon: 'dashboard' },
|
||||
{ title: t('requests'), path: ROUTES.NURSE_REQUESTS, icon: 'requests' },
|
||||
{ title: t('profile'), path: ROUTES.NURSE_PROFILE, icon: 'profile' },
|
||||
{ title: t('services'), path: ROUTES.NURSE_SERVICES, icon: 'services' },
|
||||
{ title: t('coverage'), path: ROUTES.NURSE_COVERAGE, icon: 'coverage' },
|
||||
{ title: t('bank'), path: ROUTES.NURSE_BANK, icon: 'bank' },
|
||||
{ title: t('verification'), path: ROUTES.NURSE_VERIFICATION, icon: 'verification' },
|
||||
{ title: t('visits'), path: ROUTES.NURSE_VISITS, icon: 'visits' },
|
||||
{ title: t('earnings'), path: ROUTES.NURSE_EARNINGS, icon: 'earnings' },
|
||||
{ title: t('support'), path: ROUTES.NURSE_SUPPORT_TICKETS, icon: 'support' },
|
||||
{ title: t('more'), path: MORE_TAB_PATH, icon: 'menu' },
|
||||
],
|
||||
[t]
|
||||
);
|
||||
@@ -35,9 +66,26 @@ const NurseLayout: FunctionComponent<PropsWithChildren> = ({ children }) => {
|
||||
return (
|
||||
<TopBarAndSideBarLayout
|
||||
sidebarItems={sidebarItems}
|
||||
title={tShell('nurse_app')}
|
||||
variant="sidebarPersistentOnDesktop"
|
||||
headerActions={<NotificationBell role="nurse" />}
|
||||
sidebarIdentity={
|
||||
<Stack sx={{ gap: 1.5 }}>
|
||||
<ProfileSummary
|
||||
displayName={displayName}
|
||||
phone={me?.phone}
|
||||
avatarUrl={nurseProfile?.avatarUrl}
|
||||
trustState={ownBadgeState(verification)}
|
||||
loading={identityLoading}
|
||||
/>
|
||||
<ActorSwitcher target="customer" />
|
||||
</Stack>
|
||||
}
|
||||
mobileBottomBar={(openMobileSidebar) => (
|
||||
<BottomBar
|
||||
items={mobileTabs.map((item) =>
|
||||
item.path === MORE_TAB_PATH ? { ...item, onSelect: openMobileSidebar } : item
|
||||
)}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
</TopBarAndSideBarLayout>
|
||||
|
||||
Reference in New Issue
Block a user