import { type ViewRouteMetaEntry, viewRouteMeta } from './viewRouteMeta.generated' import { viewRouteManual } from './viewRouteManual' /** view registry keys whose folder layout does not match the SPA route (see `App.tsx`). */ const VIEW_REGISTRY_APP_PATH_OVERRIDES: Record = { // Nested views map to flat `/app/teacher/competition-scores` (+ dynamic detail route). 'teacher/competition_scores/index': '/app/teacher/competition-scores', 'teacher/competition_scores/scores': '/app/teacher/competition-scores', 'landing_page/admin_dashboard': '/app/landing-page/admin-dashboard', /** view `landing_page/teacher_dashboard.php` → SPA (underscore segment per legacy URL). */ 'landing_page/teacher_dashboard': '/app/teacher_dashboard', 'flags/flags_management': '/app/administrator/flags/management', 'flags/processed_flags': '/app/administrator/flags/processed', 'flags/incident_analysis': '/app/administrator/flags/incident-analysis', 'grading/grading_main': '/app/grading', 'grading/all_decisions': '/app/grading/decisions', 'grading/below_sixty': '/app/grading/below-60', 'grading/below_sixty_decision_email_editor': '/app/grading/below-60/decisions/email-editor', 'grading/below_sixty_decisions': '/app/grading/below-60/decisions', 'grading/below_sixty_email_editor': '/app/grading/below-60/email-editor', 'grading/comments': '/app/grading/scores/comments', 'grading/final': '/app/grading/scores/final', 'grading/homework': '/app/grading/scores/homework', 'grading/homework_tracking': '/app/grading/homework-tracking', 'grading/midterm': '/app/grading/scores/midterm', 'grading/participation': '/app/grading/participation', 'grading/placement': '/app/grading/placement', /** Batch id is in the URL segment in view; dynamic route uses `spaPathFromCiUrl` / placement-index when no id. */ 'grading/placement_batch': '/app/grading/placement-index', 'grading/placement_index': '/app/grading/placement-index', 'grading/project': '/app/grading/scores/project', 'grading/quiz': '/app/grading/scores/quiz', 'grading/schedule_meeting': '/app/grading/schedule-meeting', 'grading/test': '/app/grading/scores/test', 'inventory/book/index': '/app/inventory/book', 'inventory/book/form': '/app/inventory/book/create', 'inventory/classroom/index': '/app/administrator/inventory/classroom', 'inventory/classroom/form': '/app/administrator/inventory/classroom/create', 'inventory/classroom/audit_form': '/app/administrator/inventory/classroom', 'inventory/kitchen/index': '/app/administrator/inventory/kitchen', 'inventory/kitchen/form': '/app/administrator/inventory/kitchen/create', 'inventory/office/index': '/app/administrator/inventory/office', 'inventory/office/form': '/app/administrator/inventory/office/create', 'inventory/movements/index': '/app/administrator/inventory/movements', 'inventory/movements/form': '/app/administrator/inventory/movements/create', 'inventory/movements/edit': '/app/administrator/inventory/movements', 'inventory/summary': '/app/administrator/inventory/summary', 'inventory/adjust_form': '/app/administrator/inventory/summary', 'inventory/teacher_distribute': '/app/teacher/inventory/book-distribute', 'attendance/teacher_attendance_month': '/app/admin/teacher-attendance/month', 'attendance/violations_pending': '/app/attendance/violations/pending', 'attendance/violations_notified': '/app/attendance/violations/notified', 'attendance/early_dismissals': '/app/attendance/early-dismissals', 'attendance/early_dismissals_add': '/app/attendance/early-dismissals/new', /** view `enroll_withdraw/new-students.php` — registered students list (JWT `registered-new-students`). */ 'enroll_withdraw/new-students': '/app/admin/enrollment/new-students', 'enroll_withdraw/new_students': '/app/admin/enrollment/new-students', 'administrator/sections_auto_distribute': '/app/administrator/sections/auto-distribute', 'administrator/sections_promotion_totals': '/app/administrator/sections/promotion-totals', /** view `administrator/events/event_list.php` — school calendar list (`GET .../school-calendar/events`). */ 'administrator/events/event_list': '/app/administrator/events', 'administrator/events': '/app/administrator/events', 'invoice_payment/invoice_management': '/app/administrator/invoice-payment', /** PDF is generated server-side; SPA preview lives under invoice-payment/pdf/:id */ 'invoice_payment/pdf_template': '/app/administrator/invoice-payment', 'notifications/list_active': '/app/notifications/active', 'notifications/list_deleted': '/app/notifications/deleted', 'payment/manual_pay': '/app/administrator/payment/manual-pay', 'payment/manual_payment': '/app/administrator/payment/manual-payment', 'payment/notification_management': '/app/administrator/payment/notification-management', 'payment/unpaid_parents': '/app/payment/unpaid-parents', 'payment/discount': '/app/administrator/payment/discount-apply-student', 'payment/extra_charges': '/app/admin/charges', 'payment/financial_report': '/app/administrator/payment/financial-report', 'payment/financial_report_summary': '/app/administrator/payment/financial-report-summary', 'payment/payment_redirect': '/app/parent/payment-redirect', 'policy/school_policy': '/school-policy', 'policy/picture_policy': '/picture-policy', 'print_requests/admin_index': '/app/admin/print-requests', 'print_requests/teacher_index': '/app/teacher/print-requests', 'printables_reports/sticker_form': '/app/printables_reports/stickers', 'printables_reports/stickers': '/app/printables_reports/stickers', 'printables_reports/badge_form': '/app/administrator/printables/badges', 'printables_reports/report_card': '/app/administrator/printables/report-cards', 'reimbursements/index': '/app/administrator/reimbursements', 'reimbursements/create': '/app/administrator/reimbursements/create', 'reimbursements/edit': '/app/administrator/reimbursements', 'reimbursements/under_processing': '/app/administrator/reimbursements/under-processing', 'report/combined': '/app/report/combined', 'rfid/rfid_coming_soon': '/app/rfid_coming_soon', 'rolepermission/list_roles': '/app/rolepermission/roles', 'rolepermission/permissionList': '/app/rolepermission/list_permissions', 'rolepermission/list_permissions': '/app/rolepermission/list_permissions', 'rolepermission/add_permission': '/app/rolepermission/permissions/create', 'rolepermission/add_role': '/app/rolepermission/roles/create', 'rolepermission/assign_role': '/app/rolepermission/assign', 'rolepermission/edit_permission': '/app/rolepermission/list_permissions', 'rolepermission/edit_role': '/app/rolepermission/roles', 'rolepermission/edit_role_permissions': '/app/rolepermission/roles', 'score_analysis/score_prediction': '/app/administrator/score-analysis/score-prediction', 'slips/preview_list': '/app/slips/preview', 'slips/slip_pdf': '/app/slips/print', 'staff/index': '/app/staff', 'staff/create': '/app/staff/create', 'student/score_card_list': '/app/student/score-card/list', /** Detail view is reached with an id segment in the URL; map the view key to the list entry route. */ 'student/score_card': '/app/student/score-card/list', 'whatsapp/manage_links': '/app/whatsapp/manage-links', 'whatsapp/parent_contacts': '/app/whatsapp/parent-contacts', 'whatsapp/parent_contacts_by_class': '/app/whatsapp/parent-contacts-by-class', 'winners/competitions/index': '/app/winners/competitions', } /** Match view `app/Views/...` keys: lowercase, hyphens in URL map to underscores. */ export function getViewRouteMeta(splat: string): ViewRouteMetaEntry | null { const raw = splat .trim() .replace(/^\/+|\/+$/g, '') .toLowerCase() if (!raw) return null const withUnderscores = raw.replace(/-/g, '_') return ( viewRouteManual[withUnderscores] ?? viewRouteMeta[withUnderscores] ?? null ) } /** Build canonical SPA path from a registry key (snake segments) using kebab-case segments. */ export function registryKeyToAppPath(routeKey: string): string { const normalized = routeKey.trim().toLowerCase() const override = VIEW_REGISTRY_APP_PATH_OVERRIDES[normalized] if (override) return override const parts = routeKey.split('/').map((seg) => seg.replace(/_/g, '-')) return `/app/${parts.join('/')}` }