export function spaPathFromCiUrl(url: string | null | undefined): string | null { if (url == null) return null const u = url.trim() if (u === '' || u === '#') return '/app/home' if (/^https?:\/\//i.test(u)) return null const path = u.replace(/^\/+/, '').replace(/\/+$/, '') if (!path) return '/app/home' if (path === 'app' || path.startsWith('app/')) { return `/${path}` } const querySuffix = path.includes('?') ? `?${path.slice(path.indexOf('?') + 1)}` : '' const pathOnly = path.split('?')[0] ?? path const slug = pathOnly .split('/') .map((s) => s.trim()) .filter(Boolean) .map((s) => s.toLowerCase()) .join('/') const competitionScoresDetail = /^teacher\/competition_scores\/scores\/(\d+)$/.exec(slug) if (competitionScoresDetail) { return `/app/teacher/competition-scores/${competitionScoresDetail[1]}${querySuffix}` } const teacherMessage = /^teacher\/teacher_message\/(\d+)$/.exec(slug) if (teacherMessage) { return `/app/teacher/messages/${teacherMessage[1]}${querySuffix}` } const gradingScore = /^grading\/(homework|quiz|project|test|midterm|final|comments)$/.exec(slug) if (gradingScore) { return `/app/grading/scores/${gradingScore[1]}${querySuffix}` } const placementBatchDetail = /^grading\/placement_batch\/(\d+)$/.exec(slug) if (placementBatchDetail) { return `/app/grading/placement-batch/${placementBatchDetail[1]}${querySuffix}` } const inventoryEdit = /^inventory\/edit\/(\d+)$/.exec(slug) if (inventoryEdit) { return `/app/administrator/inventory/edit/${inventoryEdit[1]}${querySuffix}` } const inventoryAudit = /^inventory\/classroom\/audit\/(\d+)$/.exec(slug) if (inventoryAudit) { return `/app/administrator/inventory/classroom/${inventoryAudit[1]}/audit${querySuffix}` } const inventoryAdjust = /^inventory\/adjust\/(\d+)$/.exec(slug) if (inventoryAdjust) { return `/app/administrator/inventory/items/${inventoryAdjust[1]}/adjust${querySuffix}` } const inventoryMovementEdit = /^inventory\/movements\/edit\/(\d+)$/.exec(slug) if (inventoryMovementEdit) { return `/app/administrator/inventory/movements/${inventoryMovementEdit[1]}/edit${querySuffix}` } const userEdit = /^user\/edit\/(\d+)$/.exec(slug) if (userEdit) { return `/app/user/edit/${userEdit[1]}${querySuffix}` } const authUserPw = /^user\/set_authorized_user_password\/(\d+)$/.exec(slug) if (authUserPw) { return `/set-authorized-user-password/${authUserPw[1]}${querySuffix}` } const shortcuts: Record = { 'landing_page/admin_dashboard': '/app/landing-page/admin-dashboard', 'landing_page/guest_dashboard': '/app/home', 'landing_page/parent_dashboard': '/app/parent/home', 'landing_page/teacher_dashboard': '/app/teacher_dashboard', 'teacher/dashboard': '/app/teacher_dashboard', 'teacher/no_classes': '/app/teacher/no-classes', 'teacher/select_semester': '/app/teacher/select-semester', 'teacher/trash': '/app/teacher/trash', 'teacher/inbox': '/app/teacher/inbox', 'teacher/sent': '/app/teacher/sent', 'teacher/competition_scores/index': '/app/teacher/competition-scores', 'teacher/absence_vacation': '/app/teacher/absence-vacation', 'teacher/add_final_exam': '/app/teacher/add-final-exam', 'teacher/add_homework': '/app/teacher/add-homework', 'teacher/add_midterm_exam': '/app/teacher/add-midterm-exam', 'teacher/add_participation': '/app/teacher/add-participation', 'teacher/add_project': '/app/teacher/add-project', 'teacher/add_quiz': '/app/teacher/add-quiz', 'teacher/add_quiz_column_form': '/app/teacher/add-quiz-column-form', 'teacher/calendar': '/app/teacher/calendar', 'teacher/class_progress_history': '/app/teacher/class-progress-history', 'teacher/class_progress_submit': '/app/teacher/class-progress-submit', 'teacher/class_progress_view': '/app/teacher/class-progress-view', 'teacher/class_view': '/app/teacher/class-view', 'teacher/drafts': '/app/teacher/drafts', 'teacher/exam_drafts': '/app/teacher/exam-drafts', 'teacher/homework_list': '/app/teacher/homework-list', 'teacher/scores': '/app/teacher/scores', 'teacher/showupdate_attendance': '/app/teacher/showupdate-attendance', 'teacher/teacher_assignment': '/app/teacher/teacher-assignment', 'teacher/teacher_contactus': '/app/teacher/teacher-contactus', 'teacher/teacher_support': '/app/teacher/teacher-support', 'teacher/teacher_message': '/app/teacher/inbox', 'flags/flags_management': '/app/administrator/flags/management', 'flags/processed_flags': '/app/administrator/flags/processed', 'flags/incident_analysis': '/app/administrator/flags/incident-analysis', 'administrator/dashboard': '/app/administrator/dashboard', 'administrator/administratordashboard': '/app/admin/dashboard', 'administrator/absence': '/app/administrator/absence', 'administrator/daily_attendance': '/app/administrator/daily_attendance', 'administrator/daily_attendance_analysis': '/app/administrator/daily_attendance_analysis', 'administrator/exam_drafts': '/app/administrator/exam-drafts', 'administrator/grading_management': '/app/administrator/grading_management', 'administrator/ip_bans': '/app/administrator/ip_bans', 'administrator/late_slip_logs': '/app/administrator/late_slip_logs', 'administrator/manage_users': '/app/administrator/manage_users', 'administrator/notifications_alerts': '/app/administrator/notifications_alerts', 'administrator/parent_profile': '/app/administrator/parent_profiles', 'administrator/paypal_transactions': '/app/administrator/paypal_transactions', 'administrator/print_notification_admins': '/app/administrator/print_notification_admins', 'administrator/removed_students': '/app/administrator/removed_students', 'administrator/search_results': '/app/administrator/search_results', 'administrator/sections_auto_distribute': '/app/administrator/sections/auto-distribute', 'administrator/sections_promotion_totals': '/app/administrator/sections/promotion-totals', 'administrator/student_class_assignment': '/app/administrator/student_class_assignment', 'administrator/student_profiles': '/app/administrator/student_profiles', 'administrator/subject_curriculum': '/app/administrator/subject-curriculum', 'administrator/teacher_class_assignment': '/app/administrator/teacher_class_assignment', 'administrator/teacher_submissions': '/app/administrator/teacher-submissions', 'administrator/events/event_list': '/app/administrator/events', 'administrator/events': '/app/administrator/events', 'admin/competition_winners': '/app/competition-winners', 'admin/competition_winners/index': '/app/competition-winners', 'admin/competition_winners/form': '/app/competition-winners/create', 'admin/competition_winners/preview': '/app/competition-winners', 'admin/competition_winners/scores': '/app/competition-winners', 'admin/competition_winners/winners': '/app/competition-winners', 'admin/class_progress_list': '/app/admin/progress', 'admin/class_progress_view': '/app/admin/progress', 'administrator/student_score_card': '/app/administrator/student-score-card', 'administrator/emergency_contact': '/app/administrator/emergency-contacts', 'administrator/emergency_contact/index': '/app/administrator/emergency-contacts', 'administrator/emergency_contact/edit': '/app/administrator/emergency-contacts', 'nav-builder': '/app/nav-builder', 'nav-builder/index': '/app/nav-builder/index', 'nav-builder/edit': '/app/nav-builder/edit', 'api/nav-builder': '/app/nav-builder', 'parent/parent_dashboard': '/app/parent/home', parent_dashboard: '/app/parent/home', 'parent/attendance-reports': '/app/parent/attendance-reports', 'parent/authorized-users': '/app/parent/authorized-users', 'parent/update-profile': '/app/parent/update-profile', 'parent/add_second_parent': '/app/parent/add-second-parent', 'parent/add-second-parent': '/app/parent/add-second-parent', 'parent/enroll_classes': '/app/parent/enroll-classes', 'parent/enroll-classes': '/app/parent/enroll-classes', 'parent/enroll_success': '/app/parent/enroll/success', 'parent/enroll_failure': '/app/parent/enroll/failure', 'parent/payment': '/app/parent/payment', 'parent/invoice_payment': '/app/parent/invoice-payment', 'parent/invoice-payment': '/app/parent/invoice-payment', 'parent/calendar': '/app/parent/calendar', 'parent/attendance': '/app/parent/attendance', 'parent/report-attendance': '/app/parent/report-attendance', 'parent/report_cards': '/app/parent/report-cards', 'parent/report-cards': '/app/parent/report-cards', 'parent/progress': '/app/parent/progress', 'parent/events': '/app/parent/events', 'parent/contact': '/app/parent/contact', 'parent/register_student': '/app/parent/register-student', 'parent/register-student': '/app/parent/register-student', 'parent/scores': '/app/parent/scores', 'parent/assignments': '/app/parent/assignments', 'parent/classes': '/app/parent/classes', 'parent/viewsecondparent': '/app/parent/add-second-parent', 'parent/child_register': '/app/parent/register-student', 'parent/edit-emergency-contact': '/app/parent/edit-emergency-contact', 'parent/emergency-contacts': '/app/parent/emergency-contacts', 'parent/edit_all_students': '/app/parent/edit-all-students', 'parent/edit-all-students': '/app/parent/edit-all-students', 'class-prep': '/app/administrator/class-prep', communications: '/app/administrator/communications', 'communications/index': '/app/administrator/communications', 'configuration/configuration_view': '/app/administrator/configuration_view', 'discounts/list': '/app/administrator/discounts', 'discount/create': '/app/administrator/discounts/create', 'discount/apply': '/app/administrator/discounts/apply', 'errors/invalid_token': '/invalid-token', 'errors/access_denied': '/access-denied', 'discounts/reverse_discount': '/app/administrator/discounts/reverse', 'expenses/index': '/app/administrator/expenses', 'expenses/create': '/app/administrator/expenses/create', family: '/app/administrator/family', 'family/index': '/app/administrator/family', 'family/compose-email': '/app/administrator/family/compose-email', 'families/import-legacy': '/app/families/import-legacy', 'administrator/expense_management': '/app/administrator/expenses', 'enroll_withdraw/new-students': '/app/admin/enrollment/new-students', 'enroll_withdraw/enrollment_withdrawal': '/app/administrator/enroll-withdraw/enrollment-withdrawal', 'emails/parent_email_extractor': '/app/administrator/parent-email-extractor', 'emails/broadcast': '/app/administrator/email-templates', '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/homework_tracking': '/app/grading/homework-tracking', 'grading/participation': '/app/grading/participation', 'grading/placement_index': '/app/grading/placement-index', 'grading/placement': '/app/grading/placement', 'grading/schedule_meeting': '/app/grading/schedule-meeting', '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', 'inventory/books/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', 'invoice_payment/invoice_management': '/app/administrator/invoice-payment', '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/under_processing': '/app/administrator/reimbursements/under-processing', 'refunds/list': '/app/refunds/list', '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', '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', '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', 'user/welcome_back': '/app/user/welcome-back', 'user/login_activity': '/app/user/login-activity', 'user/user_list': '/app/user/user-list', 'user/create': '/app/user/create', 'user/forgot_password': '/forgot-password', 'user/reset_password': '/reset-password', 'user/set_password': '/set-password', 'user/password_set_success': '/password-set-success', 'user/login': '/login', 'user/register': '/register', } const mapped = shortcuts[slug] if (mapped) return `${mapped}${querySuffix}` return `/app/${slug}${querySuffix}` } export function isExternalNavUrl(url: string | null | undefined): boolean { if (!url) return false return /^https?:\/\//i.test(url.trim()) }