import { hasModuleAccess, hasPermission, type AppSession } from '$lib/session'; export type WorkspaceRole = 'admin' | 'operations' | 'full' | 'client' | 'unknown'; type RouteAccessRule = { path: string; roles: WorkspaceRole[]; matches: (pathname: string) => boolean; }; function hasPathPrefix(pathname: string, prefix: string) { return pathname === prefix || pathname.startsWith(`${prefix}/`); } function canAccessWorkspaceArea( session: AppSession | null | undefined, moduleKey: string, permissionKeys: string[], minimumLevel: 'view' | 'edit' | 'manage' = 'view' ) { if (!session) { return false; } if (session.role === 'internal') { return permissionKeys.some((permissionKey) => hasPermission(session, permissionKey)); } return hasModuleAccess(session, moduleKey, minimumLevel); } function isLeanAdminRole(session: AppSession | null | undefined) { return session?.role === 'admin' || (session?.role === 'internal' && ['admin', 'lean'].includes(session.role_name?.toLowerCase() ?? '')); } export function getWorkspaceRole(session: AppSession | null | undefined): WorkspaceRole { if (!session) { return 'unknown'; } if (session.role === 'admin') { return 'admin'; } if (session.role !== 'internal') { return 'client'; } if (isLeanAdminRole(session)) { return 'admin'; } if (session.role_name === 'Operations') { return 'operations'; } if (session.role_name === 'Full Access') { return 'full'; } return 'unknown'; } export function canOpenDashboard(session: AppSession | null | undefined) { return canAccessWorkspaceArea(session, 'dashboard', ['view_dashboard']); } export function canOpenRawMaterials(session: AppSession | null | undefined) { return canAccessWorkspaceArea(session, 'raw_materials', ['view_raw_materials', 'edit_raw_materials']); } export function canOpenMixMaster(session: AppSession | null | undefined) { return canAccessWorkspaceArea(session, 'mix_master', ['view_mixes', 'edit_mixes']); } export function canCreateMixWorksheet(session: AppSession | null | undefined) { return canAccessWorkspaceArea(session, 'mix_master', ['edit_mixes'], 'edit'); } export function canOpenMixCalculator(session: AppSession | null | undefined) { return canAccessWorkspaceArea(session, 'mix_calculator', ['view_mix_calculator', 'use_mix_calculator']); } export function canCreateMixSession(session: AppSession | null | undefined) { return canAccessWorkspaceArea(session, 'mix_calculator', ['use_mix_calculator', 'save_mix_calculator_session'], 'edit'); } export function canOpenProducts(session: AppSession | null | undefined) { return canAccessWorkspaceArea(session, 'products', ['view_products', 'edit_products']); } export function canOpenEditor(session: AppSession | null | undefined) { if (!session) { return false; } return isLeanAdminRole(session); } export function canOpenScenarios(session: AppSession | null | undefined) { return !!session && hasModuleAccess(session, 'scenarios'); } export function canOpenThroughput(session: AppSession | null | undefined) { return canAccessWorkspaceArea(session, 'operations_throughput', ['view_throughput', 'edit_throughput']); } export function canEditThroughput(session: AppSession | null | undefined) { return canAccessWorkspaceArea(session, 'operations_throughput', ['edit_throughput'], 'edit'); } export function canOpenReporting(session: AppSession | null | undefined) { return canOpenProducts(session); } export function canOpenSettings(session: AppSession | null | undefined) { if (!session) { return false; } return session.role === 'internal' ? hasPermission(session, 'view_settings') || hasPermission(session, 'edit_settings') : true; } export function canOpenClientAccess(session: AppSession | null | undefined) { return !!session && hasModuleAccess(session, 'client_access', 'manage'); } export const routeAccessRules: RouteAccessRule[] = [ { path: '/', roles: ['admin', 'full', 'client'], matches: (pathname) => pathname === '/' }, { path: '/mix-calculator', roles: ['admin', 'operations', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/mix-calculator') }, { path: '/raw-materials', roles: ['admin', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/raw-materials') }, { path: '/mixes', roles: ['admin', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/mixes') }, { path: '/products', roles: ['admin', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/products') }, { path: '/editor', roles: ['admin'], matches: (pathname) => hasPathPrefix(pathname, '/editor') }, { path: '/reporting', roles: ['admin', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/reporting') }, { path: '/scenarios', roles: ['admin', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/scenarios') }, { path: '/settings', roles: ['admin', 'full', 'operations', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/settings') }, { path: '/client-access', roles: ['admin', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/client-access') }, { path: '/throughput', roles: ['admin', 'operations', 'full', 'client'], matches: (pathname) => hasPathPrefix(pathname, '/throughput') } ]; export function getDefaultRouteForRole(session: AppSession | null | undefined) { const role = getWorkspaceRole(session); if (role === 'operations') { return '/mix-calculator'; } if (role === 'admin' || role === 'full' || role === 'client') { if (canOpenDashboard(session)) return '/'; if (canOpenMixCalculator(session)) return '/mix-calculator'; if (canOpenRawMaterials(session)) return '/raw-materials'; if (canOpenMixMaster(session)) return '/mixes'; if (canOpenProducts(session)) return '/products'; if (canOpenScenarios(session)) return '/scenarios'; if (canOpenSettings(session)) return '/settings'; } return '/'; } export function canAccessRoute(session: AppSession | null | undefined, pathname: string) { const rule = routeAccessRules.find((candidate) => candidate.matches(pathname)); if (!rule) { return true; } const role = getWorkspaceRole(session); if (!rule.roles.includes(role)) { return false; } if (pathname === '/') return canOpenDashboard(session); if (pathname.startsWith('/mix-calculator')) return canOpenMixCalculator(session); if (pathname.startsWith('/raw-materials')) return canOpenRawMaterials(session); if (pathname.startsWith('/mixes')) return canOpenMixMaster(session); if (pathname.startsWith('/products')) return canOpenProducts(session); if (pathname.startsWith('/editor')) return canOpenEditor(session); if (pathname.startsWith('/scenarios')) return canOpenScenarios(session); if (pathname.startsWith('/reporting')) return canOpenReporting(session); if (pathname.startsWith('/settings')) return canOpenSettings(session); if (pathname.startsWith('/client-access')) return canOpenClientAccess(session); if (pathname.startsWith('/throughput')) return canOpenThroughput(session); return true; } export function canUseWorkspaceSearch(session: AppSession | null | undefined) { return ( canOpenDashboard(session) || canOpenRawMaterials(session) || canOpenMixMaster(session) || canOpenEditor(session) || canOpenMixCalculator(session) || canOpenProducts(session) || canOpenScenarios(session) ); } export const getWorkspaceHomeHref = getDefaultRouteForRole; export const isWorkspaceRouteAllowed = canAccessRoute;