feature: phase1 - org-type navigation, Cases permissions, staff filtering, and route guards.
This commit is contained in:
@@ -11,51 +11,73 @@ import {
|
||||
FlaskConical,
|
||||
FileText,
|
||||
CreditCard,
|
||||
Package,
|
||||
} from 'lucide-react';
|
||||
import type { OrgTypeName } from '@/components/shared/permissions';
|
||||
import { useAuth } from '@/lib/hooks/useAuth';
|
||||
import { usePendingConnectionsCount } from '@/lib/hooks/usePendingConnectionsCount';
|
||||
import { canAccessAppointmentsSection, canViewTab } from '@/components/shared/permissions';
|
||||
import {
|
||||
canAccessAppointmentsSection,
|
||||
canViewCases,
|
||||
canViewTab,
|
||||
} from '@/components/shared/permissions';
|
||||
import {
|
||||
counterpartOrganizationType,
|
||||
organizationTypeIcon,
|
||||
} from '@/components/shared/organizationTypeIcon';
|
||||
|
||||
type MenuItem = {
|
||||
name: string;
|
||||
path: string;
|
||||
icon: typeof LayoutDashboard;
|
||||
read: string;
|
||||
orgTypes: OrgTypeName[];
|
||||
};
|
||||
|
||||
function Sidebar() {
|
||||
const t = useTranslations('nav');
|
||||
const tCommon = useTranslations('common');
|
||||
const pathname = usePathname();
|
||||
const { currentOrganization } = useAuth();
|
||||
const pendingConnectionsCount = usePendingConnectionsCount();
|
||||
const orgType = currentOrganization?.type;
|
||||
|
||||
|
||||
const menu = useMemo(
|
||||
() => [
|
||||
{ name: t('dashboard'), path: '/today', icon: LayoutDashboard, read: 'TAB_TODAY_READ' as const },
|
||||
{ name: t('staff'), path: '/staff', icon: UserCog, read: 'TAB_STAFF_READ' as const },
|
||||
const menu = useMemo((): MenuItem[] => {
|
||||
const items: MenuItem[] = [
|
||||
{ name: t('dashboard'), path: '/today', icon: LayoutDashboard, read: 'TAB_TODAY_READ', orgTypes: ['CLINIC', 'LAB'] },
|
||||
{ name: t('staff'), path: '/staff', icon: UserCog, read: 'TAB_STAFF_READ', orgTypes: ['CLINIC', 'LAB'] },
|
||||
{
|
||||
name: currentOrganization?.type === 'LAB' ? t('clinics') : t('labs'),
|
||||
name: orgType === 'LAB' ? t('clinics') : t('labs'),
|
||||
path: '/organizations',
|
||||
icon: organizationTypeIcon(counterpartOrganizationType(currentOrganization?.type)),
|
||||
read: 'TAB_ORGANIZATIONS_READ' as const,
|
||||
icon: organizationTypeIcon(counterpartOrganizationType(orgType)),
|
||||
read: 'TAB_ORGANIZATIONS_READ',
|
||||
orgTypes: ['CLINIC', 'LAB'],
|
||||
},
|
||||
{ name: t('patients'), path: '/patients', icon: Users, read: 'TAB_PATIENTS_READ' as const },
|
||||
{ name: t('appointment'), path: '/appointments', icon: Calendar, read: 'TAB_APPOINTMENTS_READ' as const },
|
||||
{ name: t('treatment'), path: '/treatment', icon: FlaskConical, read: 'TAB_TREATMENT_READ' as const },
|
||||
{ name: t('billing'), path: '/billing', icon: CreditCard, read: 'TAB_BILLING_READ' as const },
|
||||
{ name: t('reports'), path: '/reports', icon: FileText, read: 'TAB_REPORTS_READ' as const },
|
||||
],
|
||||
[currentOrganization?.type, t],
|
||||
);
|
||||
{ name: t('patients'), path: '/patients', icon: Users, read: 'TAB_PATIENTS_READ', orgTypes: ['CLINIC'] },
|
||||
{ name: t('cases'), path: '/cases', icon: Package, read: 'TAB_CASES_READ', orgTypes: ['LAB'] },
|
||||
{ name: t('appointment'), path: '/appointments', icon: Calendar, read: 'TAB_APPOINTMENTS_READ', orgTypes: ['CLINIC'] },
|
||||
{ name: t('treatment'), path: '/treatment', icon: FlaskConical, read: 'TAB_TREATMENT_READ', orgTypes: ['CLINIC'] },
|
||||
{ name: t('billing'), path: '/billing', icon: CreditCard, read: 'TAB_BILLING_READ', orgTypes: ['CLINIC', 'LAB'] },
|
||||
{ name: t('reports'), path: '/reports', icon: FileText, read: 'TAB_REPORTS_READ', orgTypes: ['CLINIC', 'LAB'] },
|
||||
];
|
||||
return items;
|
||||
}, [orgType, t]);
|
||||
|
||||
const visibleMenu = useMemo(
|
||||
() =>
|
||||
menu.filter((item) => {
|
||||
if (!orgType || !item.orgTypes.includes(orgType)) {
|
||||
return false;
|
||||
}
|
||||
if (item.path === '/appointments') {
|
||||
return canAccessAppointmentsSection(currentOrganization);
|
||||
}
|
||||
if (item.path === '/cases') {
|
||||
return canViewCases(currentOrganization);
|
||||
}
|
||||
return canViewTab(currentOrganization, item.read);
|
||||
}),
|
||||
[currentOrganization, menu],
|
||||
[currentOrganization, menu, orgType],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user