import type { Organization } from '@/types/organization'; export type OrgTypeName = 'CLINIC' | 'LAB'; export type DashboardRouteConfig = { prefix: string; permission: string; orgTypes: OrgTypeName[]; }; export const DASHBOARD_ROUTES: DashboardRouteConfig[] = [ { prefix: '/today', permission: 'TAB_TODAY_READ', orgTypes: ['CLINIC', 'LAB'] }, { prefix: '/staff', permission: 'TAB_STAFF_READ', orgTypes: ['CLINIC', 'LAB'] }, { prefix: '/organizations', permission: 'TAB_ORGANIZATIONS_READ', orgTypes: ['CLINIC', 'LAB'] }, { prefix: '/patients', permission: 'TAB_PATIENTS_READ', orgTypes: ['CLINIC'] }, { prefix: '/appointments', permission: 'TAB_APPOINTMENTS_READ', orgTypes: ['CLINIC'] }, { prefix: '/treatment', permission: 'TAB_TREATMENT_READ', orgTypes: ['CLINIC'] }, { prefix: '/cases', permission: 'TAB_CASES_READ', orgTypes: ['LAB'] }, { prefix: '/tasks', permission: 'TAB_TASKS_READ', orgTypes: ['LAB'] }, { prefix: '/billing', permission: 'TAB_BILLING_READ', orgTypes: ['CLINIC', 'LAB'] }, { prefix: '/reports', permission: 'TAB_REPORTS_READ', orgTypes: ['CLINIC', 'LAB'] }, ]; export function isRouteAllowedForOrgType(pathname: string, orgType: OrgTypeName | undefined): boolean { if (!orgType) return false; const route = DASHBOARD_ROUTES.find( (r) => pathname === r.prefix || pathname.startsWith(`${r.prefix}/`), ); if (!route) return true; return route.orgTypes.includes(orgType); } export function hasPermission(org: Organization | null, permission: string): boolean { if (!org) return false; return Boolean(org.permissions?.includes(permission)); } /** True when the user is owner of the currently selected organization. */ export function canCreateOrganizationFromCurrentOrg(org: Organization | null): boolean { return Boolean(org?.isOwner); } /** Sidebar / route guard: READ access to a tab */ export function canViewTab(org: Organization | null, readPermission: string): boolean { return hasPermission(org, readPermission); } export function getRouteConfigForPath(pathname: string): DashboardRouteConfig | null { for (const route of DASHBOARD_ROUTES) { if (pathname === route.prefix || pathname.startsWith(`${route.prefix}/`)) { return route; } } return null; } export function getRequiredReadPermissionForPath(pathname: string): string | null { return getRouteConfigForPath(pathname)?.permission ?? null; } export function canAccessDashboardRoute(org: Organization | null, pathname: string): boolean { if (!org) return false; const route = getRouteConfigForPath(pathname); if (!route) return true; if (!isRouteAllowedForOrgType(pathname, org.type)) { return false; } if (route.prefix === '/appointments') { return canAccessAppointmentsSection(org); } if (route.prefix === '/cases') { return canViewCases(org); } if (route.prefix === '/tasks') { return canViewTasks(org); } return hasPermission(org, route.permission); } /** First dashboard route the user may open (ordered). Fallback: account settings. */ export function firstAccessibleDashboardPath(org: Organization | null): string { if (!org) return '/today'; for (const route of DASHBOARD_ROUTES) { if (!route.orgTypes.includes(org.type)) continue; if (route.prefix === '/appointments') { if (canAccessAppointmentsSection(org)) return route.prefix; continue; } if (route.prefix === '/cases') { if (canViewCases(org)) return route.prefix; continue; } if (route.prefix === '/tasks') { if (canViewTasks(org)) return route.prefix; continue; } if (hasPermission(org, route.permission)) return route.prefix; } return '/settings/account'; } export function canEditStaff(org: Organization | null): boolean { return hasPermission(org, 'TAB_STAFF_EDIT'); } export function canViewStaff(org: Organization | null): boolean { return ( hasPermission(org, 'TAB_STAFF_READ') || hasPermission(org, 'TAB_STAFF_EDIT') ); } /** * Create/delete/book slots: owners or staff with TAB_APPOINTMENTS_EDIT only. */ export function canEditAppointments(org: Organization | null): boolean { if (!org) { return false; } if (org.type !== 'CLINIC') { return false; } if (org.isOwner) { return true; } return hasPermission(org, 'TAB_APPOINTMENTS_EDIT'); } /** Route + sidebar: appointments tab requires TAB_APPOINTMENTS_READ or TAB_APPOINTMENTS_EDIT. */ export function canAccessAppointmentsSection(org: Organization | null): boolean { return canViewAppointmentsTab(org); } /** Treatment composer, scheduling columns, and saving clinical workflows */ export function canEditTreatment(org: Organization | null): boolean { if (!org) return false; if (org.type !== 'CLINIC') return false; if (org.isOwner) return true; return hasPermission(org, 'TAB_TREATMENT_EDIT'); } /** Staff treatment editors only — personal schedule Today gadgets (not owners). */ export function canViewMyAppointmentsWeekChart(org: Organization | null): boolean { if (!org) return false; if (org.type !== 'CLINIC') return false; if (org.isOwner) return false; return hasPermission(org, 'TAB_TREATMENT_EDIT'); } /** View treatment workspace (read-only or edit) */ export function canViewTreatment(org: Organization | null): boolean { if (!org) return false; if (org.type !== 'CLINIC') return false; if (org.isOwner) return true; return ( hasPermission(org, 'TAB_TREATMENT_READ') || hasPermission(org, 'TAB_TREATMENT_EDIT') ); } /** Lab cases inbox */ export function canViewCases(org: Organization | null): boolean { if (!org) return false; if (org.type !== 'LAB') return false; if (org.isOwner) return true; return ( hasPermission(org, 'TAB_CASES_READ') || hasPermission(org, 'TAB_CASES_EDIT') ); } export function canEditCases(org: Organization | null): boolean { if (!org) return false; if (org.type !== 'LAB') return false; if (org.isOwner) return true; return hasPermission(org, 'TAB_CASES_EDIT'); } /** Lab task inbox */ export function canViewTasks(org: Organization | null): boolean { if (!org) return false; if (org.type !== 'LAB') return false; if (org.isOwner) return true; return ( hasPermission(org, 'TAB_TASKS_READ') || hasPermission(org, 'TAB_TASKS_EDIT') ); } export function canEditTasks(org: Organization | null): boolean { if (!org) return false; if (org.type !== 'LAB') return false; if (org.isOwner) return true; return hasPermission(org, 'TAB_TASKS_EDIT'); } /** Appointments tab only (excludes treatment-only access). */ export function canViewAppointmentsTab(org: Organization | null): boolean { if (!org) return false; if (org.type !== 'CLINIC') return false; if (org.isOwner) return true; return ( hasPermission(org, 'TAB_APPOINTMENTS_READ') || hasPermission(org, 'TAB_APPOINTMENTS_EDIT') ); } export function canViewLabCasesOrTasks(org: Organization | null): boolean { return canViewCases(org) || canViewTasks(org); }