@jmruthers/pace-core 0.6.8 → 0.6.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/audit-tool/audits/02-project-structure.cjs +97 -32
- package/audit-tool/audits/03-architecture.cjs +145 -19
- package/audit-tool/audits/04-code-quality.cjs +86 -1
- package/audit-tool/audits/06-security-rbac.cjs +109 -11
- package/cursor-rules/02-project-structure.mdc +2 -26
- package/cursor-rules/05-styling.mdc +84 -6
- package/cursor-rules/06-security-rbac.mdc +124 -1
- package/dist/{DataTable-6RMSCQJ6.js → DataTable-SAXFG4XI.js} +11 -13
- package/dist/{AuthService-DmfO5rGS.d.ts → InactivityServiceProvider-DHryoh6K.d.ts} +24 -249
- package/dist/UnifiedAuthProvider-BBD2PS3Q.js +7 -0
- package/dist/{UnifiedAuthProvider-CKvHP1MK.d.ts → UnifiedAuthProvider-CiBAl9-s.d.ts} +34 -22
- package/dist/{api-7P7DI652.js → api-F47QJ7FX.js} +3 -3
- package/dist/assets/app-icons/admin_favicon.svg +462 -0
- package/dist/assets/app-icons/base_favicon.svg +85 -0
- package/dist/assets/app-icons/cake_favicon.svg +68 -0
- package/dist/assets/app-icons/core_favicon.svg +256 -0
- package/dist/assets/app-icons/gear_favicon.svg +91 -0
- package/dist/assets/app-icons/medi_favicon.svg +92 -0
- package/dist/assets/app-icons/mint_favicon.svg +83 -0
- package/dist/assets/app-icons/pace_favicon.svg +49 -0
- package/dist/assets/app-icons/pump_favicon.svg +68 -0
- package/dist/assets/app-icons/seed_favicon.svg +91 -0
- package/dist/assets/app-icons/team_favicon.svg +67 -0
- package/dist/assets/app-icons/trac_favicon.svg +112 -0
- package/dist/assets/app-icons/trip_favicon.svg +102 -0
- package/dist/audit-Z6ZZBWLU.js +3 -0
- package/dist/chunk-3GWSPISD.js +61 -0
- package/dist/{chunk-4DDCYDQ3.js → chunk-66R6RLUZ.js} +12 -27
- package/dist/{chunk-FYHN4DD5.js → chunk-7YDC7LMU.js} +80 -8
- package/dist/{chunk-S7DKJPLT.js → chunk-BCTXBU6U.js} +22 -17
- package/dist/{chunk-TTRFSOKR.js → chunk-BTHN5MKC.js} +4 -4
- package/dist/{chunk-A3W6LW53.js → chunk-DDMPHZ3D.js} +6 -18
- package/dist/{chunk-MPBLMWVR.js → chunk-FBZ7U3ID.js} +140 -92
- package/dist/chunk-FN52B75D.js +246 -0
- package/dist/{chunk-5W2A3DRC.js → chunk-JJEYZ3DX.js} +5 -4
- package/dist/chunk-KPYQWGFQ.js +183 -0
- package/dist/{chunk-IUBRCBSY.js → chunk-KSNLMI7N.js} +14 -8
- package/dist/chunk-KYURMOQM.js +977 -0
- package/dist/{chunk-LX6U42O3.js → chunk-LNHFAF4X.js} +160 -58
- package/dist/{chunk-NKHKXPI4.js → chunk-MPY44PWB.js} +683 -627
- package/dist/{chunk-AHU7G2R5.js → chunk-NIU6DPQV.js} +10 -6
- package/dist/{chunk-HF6O3O37.js → chunk-RMLY6KB5.js} +1 -1
- package/dist/{chunk-6GLLNA6U.js → chunk-SACF5YSM.js} +1 -1
- package/dist/{chunk-EURB7QFZ.js → chunk-TFIPNIPE.js} +867 -534
- package/dist/{chunk-OJ4SKRSV.js → chunk-UZNAFKGW.js} +25 -5
- package/dist/chunk-W46INAVW.js +1216 -0
- package/dist/chunk-X5EAU5G7.js +793 -0
- package/dist/{chunk-T5CVK4R3.js → chunk-Y4PF6HIM.js} +110 -64
- package/dist/components.d.ts +8 -86
- package/dist/components.js +21 -55
- package/dist/{database.generated-CcnC_DRc.d.ts → database.generated-DT8JTZiP.d.ts} +12 -12
- package/dist/eslint-rules/rules/05-styling.cjs +507 -0
- package/dist/eslint-rules/rules/06-security-rbac.cjs +10 -0
- package/dist/{event-CW5YB_2p.d.ts → event-WTAQuGcq.d.ts} +1 -1
- package/dist/{functions-lBy5L2ry.d.ts → functions-DH45k8ec.d.ts} +1 -1
- package/dist/hooks.d.ts +12 -11
- package/dist/hooks.js +69 -44
- package/dist/index.d.ts +380 -32
- package/dist/index.js +46 -32
- package/dist/papaparseLoader-WG2UXQ22.js +7 -0
- package/dist/providers.d.ts +28 -14
- package/dist/providers.js +5 -5
- package/dist/rbac/eslint-rules.js +2 -2
- package/dist/rbac/index.d.ts +58 -214
- package/dist/rbac/index.js +11 -11
- package/dist/theming/runtime.d.ts +9 -3
- package/dist/theming/runtime.js +2 -2
- package/dist/{timezone-BZe_eUxx.d.ts → timezone-K-ptz3HO.d.ts} +22 -23
- package/dist/{types-t9H8qKRw.d.ts → types-BE2sEHKd.d.ts} +1 -1
- package/dist/{types-BeoeWV5I.d.ts → types-CvOPXWWZ.d.ts} +6 -5
- package/dist/{types-DXstZpNI.d.ts → types-D05dCGma.d.ts} +56 -149
- package/dist/types-Dr8sNhER.d.ts +50 -0
- package/dist/types.d.ts +5 -5
- package/dist/{PublicPageProvider-CIGSujI2.d.ts → usePublicPageContext-vxBlEHO9.d.ts} +294 -151
- package/dist/{usePublicRouteParams-MamNgwqe.d.ts → usePublicRouteParams-G3Ks53mk.d.ts} +8 -7
- package/dist/utils.d.ts +301 -137
- package/dist/utils.js +42 -41
- package/dist/{validation-643vUDZW.d.ts → validation-g5n0hDkh.d.ts} +2 -2
- package/docs/api/modules.md +542 -549
- package/docs/api-reference/components.md +5 -5
- package/docs/api-reference/rpc-functions.md +3 -3
- package/docs/implementation-guides/data-tables.md +256 -8
- package/docs/rbac/RBAC_CONTRACT.md +0 -12
- package/docs/standards/2-project-structure-standards.md +12 -74
- package/docs/standards/6-security-rbac-standards.md +222 -7
- package/docs/standards/7-api-tech-stack-standards.md +91 -3
- package/docs/testing/README.md +10 -0
- package/docs/testing/test-setup-for-consumers.md +914 -0
- package/eslint-config-pace-core.cjs +4 -0
- package/package.json +1 -1
- package/scripts/eslint-audit.cjs +110 -11
- package/src/__mocks__/lucide-react.ts +0 -2
- package/src/__tests__/helpers/__tests__/test-utils.test.tsx +0 -2
- package/src/__tests__/index.test.ts +532 -0
- package/src/__tests__/integration/UserProfile.test.tsx +1 -1
- package/src/__tests__/rbac/PagePermissionGuard.test.tsx +10 -8
- package/src/__tests__/rls-policies.test.ts +3 -2
- package/src/assets/app-icons/admin_favicon.svg +462 -0
- package/src/assets/app-icons/base_favicon.svg +85 -0
- package/src/assets/app-icons/cake_favicon.svg +68 -0
- package/src/assets/app-icons/core_favicon.svg +256 -0
- package/src/assets/app-icons/gear_favicon.svg +91 -0
- package/src/assets/app-icons/index.ts +83 -0
- package/src/assets/app-icons/medi_favicon.svg +92 -0
- package/src/assets/app-icons/mint_favicon.svg +83 -0
- package/src/assets/app-icons/pace_favicon.svg +49 -0
- package/src/assets/app-icons/pump_favicon.svg +68 -0
- package/src/assets/app-icons/seed_favicon.svg +91 -0
- package/src/assets/app-icons/team_favicon.svg +67 -0
- package/src/assets/app-icons/trac_favicon.svg +112 -0
- package/src/assets/app-icons/trip_favicon.svg +102 -0
- package/src/components/AddressField/AddressField.test.tsx +378 -3
- package/src/components/AddressField/AddressField.tsx +2 -2
- package/src/components/AddressField/types.ts +2 -2
- package/src/components/Alert/Alert.test.tsx +35 -25
- package/src/components/Alert/Alert.tsx +8 -8
- package/src/components/AppSwitcher/AppSwitcher.test.tsx +1250 -0
- package/src/components/AppSwitcher/AppSwitcher.tsx +315 -0
- package/src/components/Avatar/Avatar.test.tsx +11 -1
- package/src/components/Avatar/Avatar.tsx +3 -2
- package/src/components/Badge/Badge.test.tsx +11 -1
- package/src/components/Button/Button.test.tsx +13 -3
- package/src/components/Calendar/Calendar.test.tsx +523 -131
- package/src/components/Calendar/Calendar.tsx +107 -488
- package/src/components/Card/Card.test.tsx +220 -249
- package/src/components/Checkbox/Checkbox.test.tsx +58 -174
- package/src/components/ContextSelector/ContextSelector.tsx +3 -3
- package/src/components/ContextSelector/__tests__/ContextSelector.test.tsx +360 -0
- package/src/components/DataTable/DataTable.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTable.comprehensive.test.tsx +1 -1
- package/src/components/DataTable/__tests__/DataTable.export.test.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTable.grouping-aggregation.test.tsx +1 -1
- package/src/components/DataTable/__tests__/DataTable.select-label-display.test.tsx +485 -0
- package/src/components/DataTable/__tests__/DataTable.test.tsx +2 -2
- package/src/components/DataTable/__tests__/DataTableCore.test-setup.ts +1 -1
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +76 -580
- package/src/components/DataTable/__tests__/README.md +1 -1
- package/src/components/DataTable/__tests__/a11y.basic.test.tsx +1 -1
- package/src/components/DataTable/__tests__/keyboard.test.tsx +1 -1
- package/src/components/DataTable/__tests__/pagination.modes.test.tsx +1 -3
- package/src/components/DataTable/__tests__/ssr.strict-mode.test.tsx +0 -6
- package/src/components/DataTable/__tests__/test-utils/sharedTestUtils.tsx +14 -6
- package/src/components/DataTable/components/ActionButtons.tsx +9 -4
- package/src/components/DataTable/components/BulkOperationsDropdown.tsx +3 -3
- package/src/components/DataTable/components/ColumnFilter.tsx +2 -7
- package/src/components/DataTable/components/DataTableCore.tsx +44 -52
- package/src/components/DataTable/components/DataTableLayout.tsx +37 -26
- package/src/components/DataTable/components/DataTableModals.tsx +118 -30
- package/src/components/DataTable/components/DataTableToolbar.tsx +2 -2
- package/src/components/DataTable/components/EditFields.tsx +6 -47
- package/src/components/DataTable/components/EditableRow.tsx +8 -8
- package/src/components/DataTable/components/EmptyState.tsx +6 -3
- package/src/components/DataTable/components/FilterRow.tsx +18 -11
- package/src/components/DataTable/components/GroupingDropdown.tsx +0 -1
- package/src/components/DataTable/components/ImportModal.tsx +305 -133
- package/src/components/DataTable/components/LoadingState.tsx +2 -2
- package/src/components/DataTable/components/PaginationControls.tsx +0 -4
- package/src/components/DataTable/components/RowComponent.tsx +42 -22
- package/src/components/DataTable/components/UnifiedTableBody.tsx +52 -12
- package/src/components/DataTable/components/__tests__/AccessDeniedPage.test.tsx +51 -463
- package/src/components/DataTable/components/__tests__/ActionButtons.test.tsx +122 -116
- package/src/components/DataTable/components/__tests__/BulkOperationsDropdown.test.tsx +40 -68
- package/src/components/DataTable/components/__tests__/ColumnFilter.test.tsx +9 -137
- package/src/components/DataTable/components/__tests__/ColumnVisibilityDropdown.test.tsx +57 -17
- package/src/components/DataTable/components/__tests__/DataTableCore.test.tsx +792 -0
- package/src/components/DataTable/components/__tests__/DataTableErrorBoundary.test.tsx +24 -65
- package/src/components/DataTable/components/__tests__/DataTableLayout.test.tsx +467 -0
- package/src/components/DataTable/components/__tests__/DataTableModals.test.tsx +8 -125
- package/src/components/DataTable/components/__tests__/DataTableToolbar.test.tsx +528 -56
- package/src/components/DataTable/components/__tests__/EditFields.test.tsx +526 -0
- package/src/components/DataTable/components/__tests__/EditableRow.test.tsx +1 -68
- package/src/components/DataTable/components/__tests__/EmptyState.test.tsx +8 -25
- package/src/components/DataTable/components/__tests__/FilterRow.test.tsx +3 -62
- package/src/components/DataTable/components/__tests__/GroupingDropdown.test.tsx +9 -14
- package/src/components/DataTable/components/__tests__/ImportModal.test.tsx +50 -186
- package/src/components/DataTable/components/__tests__/LoadingState.test.tsx +39 -97
- package/src/components/DataTable/components/__tests__/PaginationControls.test.tsx +13 -103
- package/src/components/DataTable/components/__tests__/RowComponent.test.tsx +629 -0
- package/src/components/DataTable/components/__tests__/SortIndicator.test.tsx +135 -0
- package/src/components/DataTable/components/__tests__/UnifiedTableBody.test.tsx +31 -171
- package/src/components/DataTable/components/__tests__/cellValueUtils.test.ts +453 -0
- package/src/components/DataTable/components/hooks/useImportModalFocus.test.ts +184 -0
- package/src/components/DataTable/components/hooks/usePermissionTracking.test.ts +381 -0
- package/src/components/DataTable/context/DataTableContext.tsx +9 -10
- package/src/components/DataTable/context/__tests__/DataTableContext.test.tsx +12 -26
- package/src/components/DataTable/core/ColumnFactory.ts +3 -3
- package/src/components/DataTable/core/ColumnManager.ts +0 -1
- package/src/components/DataTable/core/DataManager.ts +4 -2
- package/src/components/DataTable/core/LocalDataAdapter.ts +1 -1
- package/src/components/DataTable/core/PluginRegistry.ts +2 -2
- package/src/components/DataTable/core/__tests__/ActionManager.test.ts +114 -2
- package/src/components/DataTable/core/__tests__/ColumnFactory.test.ts +103 -5
- package/src/components/DataTable/core/__tests__/ColumnManager.test.ts +57 -0
- package/src/components/DataTable/core/__tests__/DataManager.test.ts +63 -0
- package/src/components/DataTable/core/__tests__/LocalDataAdapter.test.ts +42 -9
- package/src/components/DataTable/core/__tests__/PluginRegistry.test.ts +29 -7
- package/src/components/DataTable/core/__tests__/StateManager.test.ts +58 -4
- package/src/components/DataTable/hooks/__tests__/useColumnOrderPersistence.test.ts +16 -21
- package/src/components/DataTable/hooks/__tests__/useColumnVisibilityPersistence.test.ts +93 -4
- package/src/components/DataTable/hooks/__tests__/useDataTableConfiguration.test.ts +227 -54
- package/src/components/DataTable/hooks/__tests__/useDataTableDataPipeline.test.ts +215 -62
- package/src/components/DataTable/hooks/__tests__/useDataTablePermissions.test.ts +217 -39
- package/src/components/DataTable/hooks/__tests__/useDataTableState.test.ts +101 -6
- package/src/components/DataTable/hooks/__tests__/useEffectiveColumnOrder.test.ts +157 -27
- package/src/components/DataTable/hooks/__tests__/useHierarchicalState.test.ts +80 -0
- package/src/components/DataTable/hooks/__tests__/useKeyboardNavigation.test.ts +787 -0
- package/src/components/DataTable/hooks/__tests__/useServerSideDataEffect.test.ts +258 -0
- package/src/components/DataTable/hooks/__tests__/useTableColumns.test.ts +298 -23
- package/src/components/DataTable/hooks/__tests__/useTableHandlers.test.ts +440 -0
- package/src/components/DataTable/hooks/useColumnOrderPersistence.ts +12 -9
- package/src/components/DataTable/hooks/useColumnVisibilityPersistence.ts +12 -9
- package/src/components/DataTable/hooks/useDataTableConfiguration.ts +1 -1
- package/src/components/DataTable/hooks/useDataTablePermissions.ts +11 -22
- package/src/components/DataTable/hooks/useDataTableState.ts +20 -24
- package/src/components/DataTable/hooks/useKeyboardNavigation.ts +5 -5
- package/src/components/DataTable/hooks/useServerSideDataEffect.ts +13 -1
- package/src/components/DataTable/hooks/useTableColumns.ts +36 -38
- package/src/components/DataTable/hooks/useTableHandlers.ts +8 -20
- package/src/components/DataTable/index.ts +24 -2
- package/src/components/DataTable/types.ts +6 -3
- package/src/components/DataTable/utils/__tests__/a11yUtils.test.ts +3 -67
- package/src/components/DataTable/utils/__tests__/aggregationUtils.test.ts +288 -0
- package/src/components/DataTable/utils/__tests__/errorHandling.test.ts +3 -60
- package/src/components/DataTable/utils/__tests__/flexibleImport.test.ts +1 -1
- package/src/components/DataTable/utils/__tests__/hierarchicalSorting.test.ts +9 -21
- package/src/components/DataTable/utils/__tests__/hierarchicalUtils.test.ts +102 -86
- package/src/components/DataTable/utils/__tests__/paginationUtils.test.ts +593 -0
- package/src/components/DataTable/utils/__tests__/rowUtils.test.ts +33 -49
- package/src/components/DataTable/utils/__tests__/selectFieldUtils.test.ts +208 -0
- package/src/components/DataTable/utils/a11yUtils.ts +1 -1
- package/src/components/DataTable/utils/aggregationUtils.ts +5 -5
- package/src/components/DataTable/utils/errorHandling.ts +3 -1
- package/src/components/DataTable/utils/exportUtils.ts +1 -1
- package/src/components/DataTable/utils/flexibleImport.ts +2 -2
- package/src/components/DataTable/utils/hierarchicalSorting.ts +3 -3
- package/src/components/DataTable/utils/paginationUtils.ts +1 -1
- package/src/components/DataTable/utils/performanceUtils.ts +1 -1
- package/src/components/DataTable/utils/selectFieldUtils.ts +127 -0
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +17 -24
- package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +1 -1
- package/src/components/DateTimeField/DateTimeField.test.tsx +2 -15
- package/src/components/DateTimeField/DateTimeField.tsx +1 -1
- package/src/components/Dialog/Dialog.test.tsx +2007 -407
- package/src/components/Dialog/Dialog.tsx +97 -192
- package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +2 -62
- package/src/components/ErrorBoundary/ErrorBoundaryContext.context.ts +17 -0
- package/src/components/ErrorBoundary/ErrorBoundaryContext.tsx +2 -45
- package/src/components/ErrorBoundary/ErrorBoundaryContext.types.ts +41 -0
- package/src/components/ErrorBoundary/index.ts +3 -4
- package/src/components/ErrorBoundary/useErrorBoundaryContext.ts +20 -0
- package/src/components/FileDisplay/FileDisplay.test.tsx +454 -222
- package/src/components/FileDisplay/FileDisplay.tsx +14 -12
- package/src/components/FileDisplay/index.tsx +1 -1
- package/src/components/FileUpload/FileUpload.test.tsx +54 -18
- package/src/components/FileUpload/FileUpload.tsx +10 -7
- package/src/components/FileUpload/index.tsx +1 -1
- package/src/components/Footer/Footer.test.tsx +33 -114
- package/src/components/Form/Form.test.tsx +388 -68
- package/src/components/Form/Form.tsx +57 -42
- package/src/components/Header/Header.test.tsx +645 -154
- package/src/components/Header/Header.tsx +52 -43
- package/src/components/InactivityWarningModal/InactivityWarningModal.test.tsx +35 -76
- package/src/components/Input/Input.test.tsx +34 -120
- package/src/components/Label/Label.test.tsx +47 -46
- package/src/components/LoadingSpinner/LoadingSpinner.test.tsx +9 -12
- package/src/components/LoginForm/LoginForm.test.tsx +0 -1
- package/src/components/NavigationMenu/NavigationMenu.test.tsx +1399 -82
- package/src/components/NavigationMenu/NavigationMenu.tsx +2 -2
- package/src/components/NavigationMenu/__tests__/useNavigationFiltering.test.ts +1934 -0
- package/src/components/NavigationMenu/useNavigationFiltering.ts +5 -15
- package/src/components/PaceAppLayout/PaceAppLayout.edge-cases.test.tsx +1307 -0
- package/src/components/PaceAppLayout/PaceAppLayout.integration.test.tsx +47 -46
- package/src/components/PaceAppLayout/PaceAppLayout.performance.test.tsx +81 -38
- package/src/components/PaceAppLayout/PaceAppLayout.security.test.tsx +87 -66
- package/src/components/PaceAppLayout/PaceAppLayout.test.tsx +245 -39
- package/src/components/PaceAppLayout/PaceAppLayout.tsx +14 -20
- package/src/components/PaceAppLayout/README.md +0 -9
- package/src/components/PaceAppLayout/test-setup.tsx +15 -9
- package/src/components/PaceLoginPage/PaceLoginPage.test.tsx +759 -3
- package/src/components/PaceLoginPage/PaceLoginPage.tsx +2 -3
- package/src/components/PasswordChange/PasswordChangeForm.test.tsx +1 -1
- package/src/components/Progress/Progress.test.tsx +127 -1
- package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +1196 -4
- package/src/components/ProtectedRoute/ProtectedRoute.tsx +24 -6
- package/src/components/PublicLayout/PublicLayout.test.tsx +1435 -14
- package/src/components/PublicLayout/PublicPageContext.ts +28 -0
- package/src/components/PublicLayout/PublicPageLayout.tsx +6 -6
- package/src/components/PublicLayout/PublicPageProvider.tsx +2 -41
- package/src/components/PublicLayout/usePublicPageContext.ts +36 -0
- package/src/components/Select/Select.test.tsx +46 -9
- package/src/components/Select/Select.tsx +31 -24
- package/src/components/Select/__tests__/context.test.tsx +56 -0
- package/src/components/Select/hooks/__tests__/useSelectEvents.test.ts +279 -0
- package/src/components/Select/hooks/__tests__/useSelectSearch.test.tsx +295 -0
- package/src/components/Select/hooks/__tests__/useSelectState.test.ts +254 -0
- package/src/components/Select/hooks/useSelectState.ts +16 -16
- package/src/components/Select/types.ts +3 -0
- package/src/components/Select/utils/__tests__/text.test.tsx +104 -0
- package/src/components/SessionRestorationLoader/SessionRestorationLoader.test.tsx +28 -112
- package/src/components/Switch/Switch.test.tsx +57 -153
- package/src/components/Table/Table.test.tsx +47 -317
- package/src/components/Tabs/Tabs.tsx +3 -3
- package/src/components/Textarea/Textarea.test.tsx +11 -38
- package/src/components/Toast/Toast.test.tsx +78 -569
- package/src/components/Tooltip/Tooltip.test.tsx +4 -21
- package/src/components/UserMenu/UserMenu.test.tsx +1 -21
- package/src/components/UserMenu/UserMenu.tsx +3 -6
- package/src/components/__tests__/index.test.ts +346 -0
- package/src/components/index.ts +12 -1
- package/src/constants/__tests__/performance.test.ts +91 -0
- package/src/hooks/__tests__/ServiceHooks.test.tsx +239 -129
- package/src/hooks/__tests__/hooks.integration.test.tsx +4 -3
- package/src/hooks/__tests__/useApiFetch.unit.test.ts +1 -1
- package/src/hooks/__tests__/useAppConfig.unit.test.ts +88 -29
- package/src/hooks/__tests__/useComponentPerformance.unit.test.tsx +282 -98
- package/src/hooks/__tests__/useDataTablePerformance.unit.test.ts +53 -109
- package/src/hooks/__tests__/useDataTableState.test.ts +143 -49
- package/src/hooks/__tests__/useDebounce.unit.test.ts +94 -19
- package/src/hooks/__tests__/useEvents.unit.test.ts +100 -125
- package/src/hooks/__tests__/useFileDisplay.test.ts +540 -0
- package/src/hooks/__tests__/useFileDisplay.unit.test.ts +1 -4
- package/src/hooks/__tests__/useFileUrl.unit.test.ts +27 -247
- package/src/hooks/__tests__/useFileUrlCache.test.ts +246 -56
- package/src/hooks/__tests__/useFocusManagement.unit.test.ts +442 -68
- package/src/hooks/__tests__/useFocusTrap.unit.test.tsx +345 -560
- package/src/hooks/__tests__/useFormDialog.test.ts +51 -222
- package/src/hooks/__tests__/useInactivityTracker.unit.test.ts +1 -1
- package/src/hooks/__tests__/useKeyboardShortcuts.unit.test.ts +1 -4
- package/src/hooks/__tests__/useOrganisationPermissions.unit.test.tsx +0 -1
- package/src/hooks/__tests__/usePerformanceMonitor.unit.test.ts +1 -1
- package/src/hooks/__tests__/usePermissionCache.test.ts +506 -0
- package/src/hooks/__tests__/usePreventTabReload.test.ts +255 -36
- package/src/hooks/__tests__/usePublicEvent.simple.test.ts +17 -8
- package/src/hooks/__tests__/usePublicEvent.test.ts +16 -24
- package/src/hooks/__tests__/usePublicEvent.unit.test.ts +12 -4
- package/src/hooks/__tests__/usePublicFileDisplay.test.ts +3 -6
- package/src/hooks/__tests__/usePublicRouteParams.unit.test.ts +1 -2
- package/src/hooks/__tests__/useQueryCache.test.ts +313 -66
- package/src/hooks/__tests__/useSessionDraft.test.ts +496 -103
- package/src/hooks/__tests__/useSessionRestoration.unit.test.tsx +2 -2
- package/src/hooks/__tests__/useStorage.unit.test.ts +72 -102
- package/src/hooks/__tests__/useToast.test.ts +413 -0
- package/src/hooks/__tests__/useToast.unit.test.tsx +1 -1
- package/src/hooks/__tests__/useZodForm.unit.test.tsx +175 -21
- package/src/hooks/index.ts +13 -1
- package/src/hooks/public/usePublicEvent.test.ts +304 -0
- package/src/hooks/public/usePublicEvent.ts +11 -11
- package/src/hooks/public/usePublicEventLogo.test.ts +655 -120
- package/src/hooks/public/usePublicEventLogo.ts +2 -2
- package/src/hooks/public/usePublicFileDisplay.test.ts +723 -0
- package/src/hooks/public/usePublicFileDisplay.ts +79 -49
- package/src/hooks/public/usePublicRouteParams.test.ts +595 -0
- package/src/hooks/public/usePublicRouteParams.ts +2 -2
- package/src/hooks/services/useAuthService.ts +1 -1
- package/src/hooks/services/useEventService.ts +1 -1
- package/src/hooks/useAccessibleApps.test.ts +400 -0
- package/src/hooks/useAccessibleApps.ts +264 -0
- package/src/hooks/useAddressAutocomplete.test.ts +165 -42
- package/src/hooks/useAddressAutocomplete.ts +41 -28
- package/src/hooks/useAppConfig.ts +13 -3
- package/src/hooks/useDataTablePerformance.ts +13 -12
- package/src/hooks/useDataTableState.ts +5 -5
- package/src/hooks/useEventTheme.test.ts +66 -17
- package/src/hooks/useEventTheme.ts +1 -1
- package/src/hooks/useEvents.ts +8 -1
- package/src/hooks/useFileDisplay.ts +66 -33
- package/src/hooks/useFileReference.test.ts +365 -87
- package/src/hooks/useFileReference.ts +2 -6
- package/src/hooks/useFileUrlCache.ts +4 -1
- package/src/hooks/useFormDialog.ts +2 -2
- package/src/hooks/useInactivityTracker.ts +3 -3
- package/src/hooks/useOrganisationPermissions.test.ts +1 -2
- package/src/hooks/useOrganisationPermissions.ts +1 -4
- package/src/hooks/useOrganisationSecurity.test.ts +1 -30
- package/src/hooks/useOrganisationSecurity.ts +3 -3
- package/src/hooks/useOrganisations.ts +1 -1
- package/src/hooks/usePerformanceMonitor.ts +1 -1
- package/src/hooks/usePermissionCache.ts +2 -6
- package/src/hooks/useQueryCache.ts +7 -7
- package/src/hooks/useSessionDraft.ts +14 -11
- package/src/hooks/useSessionRestoration.ts +1 -1
- package/src/hooks/useStorage.ts +75 -40
- package/src/hooks/useToast.ts +2 -2
- package/src/hooks/useZodForm.ts +3 -3
- package/src/icons/__tests__/index.test.ts +133 -0
- package/src/icons/index.ts +1 -1
- package/src/index.ts +43 -4
- package/src/providers/OrganisationProvider.test.tsx +40 -0
- package/src/providers/OrganisationProvider.tsx +5 -5
- package/src/providers/UnifiedAuthProvider.smoke.test.tsx +7 -12
- package/src/providers/__tests__/AuthProvider.test.tsx +22 -91
- package/src/providers/__tests__/EventProvider.test.tsx +16 -80
- package/src/providers/__tests__/InactivityProvider.test.tsx +29 -173
- package/src/providers/__tests__/OrganisationProvider.test.tsx +4 -5
- package/src/providers/__tests__/OrganisationProvider.wrapper.test.tsx +591 -0
- package/src/providers/__tests__/ProviderLifecycle.test.tsx +80 -196
- package/src/providers/__tests__/UnifiedAuthProvider.test.tsx +40 -133
- package/src/providers/__tests__/index.test.ts +138 -0
- package/src/providers/services/AuthServiceContext.ts +27 -0
- package/src/providers/services/AuthServiceProvider.tsx +81 -20
- package/src/providers/services/EventServiceContext.ts +25 -0
- package/src/providers/services/EventServiceProvider.tsx +11 -20
- package/src/providers/services/InactivityServiceContext.ts +25 -0
- package/src/providers/services/InactivityServiceProvider.tsx +7 -17
- package/src/providers/services/OrganisationServiceContext.ts +25 -0
- package/src/providers/services/OrganisationServiceProvider.tsx +7 -17
- package/src/providers/services/UnifiedAuthContext.ts +99 -0
- package/src/providers/services/UnifiedAuthProvider.test.tsx +212 -0
- package/src/providers/services/UnifiedAuthProvider.tsx +38 -143
- package/src/providers/services/__tests__/AuthServiceProvider.integration.test.tsx +61 -95
- package/src/providers/services/__tests__/AuthServiceProvider.test.tsx +638 -0
- package/src/providers/services/__tests__/EventServiceProvider.test.tsx +839 -0
- package/src/providers/services/__tests__/InactivityServiceProvider.test.tsx +662 -0
- package/src/providers/services/__tests__/OrganisationServiceProvider.test.tsx +440 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.advanced.test.tsx +435 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.appId.test.tsx +408 -0
- package/src/providers/services/__tests__/UnifiedAuthProvider.integration.test.tsx +55 -48
- package/src/providers/services/__tests__/contexts.test.tsx +281 -0
- package/src/providers/services/__tests__/useUnifiedAuth.test.tsx +251 -0
- package/src/providers/services/useUnifiedAuth.ts +29 -0
- package/src/rbac/README.md +5 -5
- package/src/rbac/__tests__/adapters.comprehensive.test.tsx +9 -14
- package/src/rbac/__tests__/audit-batched.test.ts +550 -0
- package/src/rbac/__tests__/auth-rbac-security.integration.test.tsx +1 -14
- package/src/rbac/__tests__/auth-rbac.e2e.test.tsx +43 -12
- package/src/rbac/__tests__/cache-invalidation.test.ts +8 -14
- package/src/rbac/__tests__/engine.comprehensive.test.ts +2 -7
- package/src/rbac/__tests__/index.test.ts +107 -0
- package/src/rbac/__tests__/performance.test.ts +451 -0
- package/src/rbac/__tests__/rbac-core.test.tsx +2 -2
- package/src/rbac/__tests__/rbac-engine-core-logic.test.ts +0 -5
- package/src/rbac/__tests__/rbac-engine-simplified.test.ts +1 -7
- package/src/rbac/__tests__/rbac-functions.test.ts +0 -1
- package/src/rbac/__tests__/rbac-integration.test.ts +0 -1
- package/src/rbac/__tests__/scenarios.user-role.test.tsx +21 -32
- package/src/rbac/adapters.test.tsx +654 -0
- package/src/rbac/adapters.tsx +24 -9
- package/src/rbac/api.test.ts +13 -217
- package/src/rbac/api.ts +85 -16
- package/src/rbac/audit-batched.ts +5 -4
- package/src/rbac/audit.test.ts +225 -28
- package/src/rbac/audit.ts +22 -17
- package/src/rbac/cache-invalidation.ts +18 -15
- package/src/rbac/cache.test.ts +123 -63
- package/src/rbac/cache.ts +3 -4
- package/src/rbac/components/AccessDenied.tsx +20 -18
- package/src/rbac/components/NavigationGuard.tsx +10 -8
- package/src/rbac/components/PagePermissionGuard.tsx +27 -25
- package/src/rbac/components/__tests__/AccessDenied.test.tsx +324 -0
- package/src/rbac/components/__tests__/NavigationGuard.test.tsx +242 -71
- package/src/rbac/components/__tests__/PagePermissionGuard.performance.test.tsx +20 -37
- package/src/rbac/components/__tests__/PagePermissionGuard.race-condition.test.tsx +18 -17
- package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +452 -129
- package/src/rbac/components/__tests__/PagePermissionGuard.verification.test.tsx +14 -13
- package/src/rbac/config.test.ts +131 -48
- package/src/rbac/config.ts +11 -8
- package/src/rbac/docs/event-based-apps.md +26 -13
- package/src/rbac/engine.test.ts +496 -146
- package/src/rbac/engine.ts +53 -13
- package/src/rbac/errors.test.ts +99 -87
- package/src/rbac/eslint-rules.js +2 -2
- package/src/rbac/hooks/__tests__/usePermissions.integration.test.ts +0 -5
- package/src/rbac/hooks/__tests__/useSecureSupabase.test.ts +601 -1
- package/src/rbac/hooks/permissions/__tests__/useAccessLevel.test.ts +622 -0
- package/src/rbac/hooks/permissions/__tests__/useCan.test.ts +798 -0
- package/src/rbac/hooks/permissions/__tests__/useMultiplePermissions.test.ts +843 -0
- package/src/rbac/hooks/permissions/__tests__/usePermissions.test.ts +545 -0
- package/src/rbac/hooks/permissions/useAccessLevel.ts +7 -8
- package/src/rbac/hooks/permissions/useCan.ts +12 -10
- package/src/rbac/hooks/permissions/useMultiplePermissions.ts +57 -8
- package/src/rbac/hooks/permissions/usePermissions.ts +15 -14
- package/src/rbac/hooks/useCan.test.ts +319 -3
- package/src/rbac/hooks/usePermissions.test.ts +426 -0
- package/src/rbac/hooks/usePermissions.ts +5 -7
- package/src/rbac/hooks/useRBAC.test.ts +1669 -2
- package/src/rbac/hooks/useRBAC.ts +7 -11
- package/src/rbac/hooks/useResolvedScope.test.ts +442 -5
- package/src/rbac/hooks/useResolvedScope.ts +4 -1
- package/src/rbac/hooks/useResourcePermissions.test.ts +538 -1
- package/src/rbac/hooks/useResourcePermissions.ts +9 -7
- package/src/rbac/hooks/useRoleManagement.test.ts +659 -1
- package/src/rbac/hooks/useRoleManagement.ts +16 -12
- package/src/rbac/hooks/useSecureSupabase.ts +11 -12
- package/src/rbac/index.ts +32 -32
- package/src/rbac/permissions.test.ts +149 -68
- package/src/rbac/permissions.ts +0 -3
- package/src/rbac/request-deduplication.test.ts +347 -0
- package/src/rbac/secureClient.test.ts +112 -159
- package/src/rbac/secureClient.ts +46 -26
- package/src/rbac/security.test.ts +125 -44
- package/src/rbac/security.ts +7 -6
- package/src/rbac/types.test.ts +236 -0
- package/src/rbac/types.ts +7 -5
- package/src/rbac/utils/__tests__/clientSecurity.test.ts +192 -0
- package/src/rbac/utils/__tests__/contextValidator.test.ts +1 -3
- package/src/rbac/utils/__tests__/deep-equal.test.ts +23 -0
- package/src/rbac/utils/__tests__/eventContext.test.ts +10 -57
- package/src/rbac/utils/clientSecurity.ts +6 -4
- package/src/rbac/utils/contextValidator.ts +1 -2
- package/src/rbac/utils/eventContext.ts +2 -2
- package/src/services/AuthService.ts +13 -11
- package/src/services/EventService.ts +4 -5
- package/src/services/OrganisationService.ts +13 -30
- package/src/services/__tests__/AuthService.edge-cases.test.ts +746 -0
- package/src/services/__tests__/AuthService.restoreSession.test.ts +23 -3
- package/src/services/__tests__/AuthService.test.ts +4 -8
- package/src/services/__tests__/BaseService.edge-cases.test.ts +506 -0
- package/src/services/__tests__/BaseService.test.ts +49 -0
- package/src/services/__tests__/EventService.edge-cases.test.ts +633 -0
- package/src/services/__tests__/EventService.eventColours.test.ts +0 -12
- package/src/services/__tests__/EventService.test.ts +0 -7
- package/src/services/__tests__/InactivityService.edge-cases.test.ts +492 -0
- package/src/services/__tests__/InactivityService.lifecycle.test.ts +0 -5
- package/src/services/__tests__/OrganisationService.edge-cases.test.ts +633 -0
- package/src/services/base/BaseService.test.ts +214 -0
- package/src/services/interfaces/IOrganisationService.ts +0 -1
- package/src/services/interfaces/__tests__/IAuthService.test.ts +190 -0
- package/src/services/interfaces/__tests__/IEventService.test.ts +176 -0
- package/src/services/interfaces/__tests__/IInactivityService.test.ts +183 -0
- package/src/services/interfaces/__tests__/IOrganisationService.test.ts +207 -0
- package/src/styles/core.css +1 -0
- package/src/theming/__tests__/runtime.test.ts +29 -94
- package/src/theming/parseEventColours.ts +18 -9
- package/src/theming/runtime.ts +1 -5
- package/src/types/__tests__/core.test.ts +397 -0
- package/src/types/__tests__/database-generated.test.ts +78 -0
- package/src/types/__tests__/file-reference.test.ts +270 -366
- package/src/types/__tests__/guards.test.ts +26 -26
- package/src/types/__tests__/index.test.ts +265 -0
- package/src/types/__tests__/type-validation.test.ts +3 -3
- package/src/types/__tests__/validation.test.ts +0 -2
- package/src/types/auth.ts +0 -1
- package/src/types/database.generated.ts +9 -9
- package/src/types/event.ts +1 -1
- package/src/types/rpc-responses.ts +33 -0
- package/src/types/supabase.ts +1 -2
- package/src/types/vitest-globals.d.ts +1 -1
- package/src/utils/__tests__/bundleAnalysis.unit.test.ts +64 -77
- package/src/utils/__tests__/dynamicUtils.unit.test.ts +13 -0
- package/src/utils/__tests__/formatDate.unit.test.ts +1 -1
- package/src/utils/__tests__/lazyLoad.unit.test.tsx +0 -1
- package/src/utils/__tests__/logger.unit.test.ts +1 -1
- package/src/utils/__tests__/performanceBenchmark.test.ts +1 -2
- package/src/utils/__tests__/performanceBudgets.unit.test.ts +48 -13
- package/src/utils/__tests__/request-deduplication.test.ts +349 -0
- package/src/utils/__tests__/secureDataAccess.unit.test.ts +0 -1
- package/src/utils/__tests__/timezone.test.ts +1 -1
- package/src/utils/__tests__/validation.unit.test.ts +1 -2
- package/src/utils/__tests__/validationUtils.unit.test.ts +1 -1
- package/src/utils/app/appConfig.test.ts +235 -0
- package/src/utils/app/appIdResolver.test.ts +188 -20
- package/src/utils/app/appNameResolver.test.ts +18 -10
- package/src/utils/app/appNameResolver.ts +11 -9
- package/src/utils/app/appPortMap.test.ts +125 -0
- package/src/utils/app/appPortMap.ts +51 -0
- package/src/utils/app/buildAppUrl.test.ts +273 -0
- package/src/utils/app/buildAppUrl.ts +114 -0
- package/src/utils/audit/audit.test.ts +354 -39
- package/src/utils/context/organisationContext.test.ts +10 -4
- package/src/utils/context/organisationContext.ts +5 -5
- package/src/utils/context/sessionTracking.test.ts +354 -0
- package/src/utils/core/__tests__/cn.test.ts +66 -0
- package/src/utils/core/__tests__/debugLogger.test.ts +113 -0
- package/src/utils/core/__tests__/logger.test.ts +217 -0
- package/src/utils/core/debugLogger.ts +15 -8
- package/src/utils/core/logger.ts +20 -16
- package/src/utils/device/deviceFingerprint.test.ts +8 -5
- package/src/utils/device/deviceFingerprint.ts +3 -3
- package/src/utils/dynamic/__tests__/dynamicUtils.test.ts +185 -0
- package/src/utils/dynamic/__tests__/lazyLoad.test.tsx +156 -0
- package/src/utils/dynamic/createLazyComponent.tsx +38 -0
- package/src/utils/dynamic/dynamicUtils.ts +6 -6
- package/src/utils/dynamic/lazyLoad.tsx +8 -36
- package/src/utils/dynamic/papaparseLoader.ts +7 -0
- package/src/utils/file-reference/__tests__/file-reference.test.ts +583 -145
- package/src/utils/file-reference/index.ts +0 -1
- package/src/utils/formatting/formatDate.test.ts +22 -148
- package/src/utils/formatting/formatDateTime.test.ts +41 -119
- package/src/utils/formatting/formatDateTimeTimezone.test.ts +40 -84
- package/src/utils/formatting/formatNumber.test.ts +259 -0
- package/src/utils/formatting/formatTime.test.ts +36 -128
- package/src/utils/formatting/formatting.ts +1 -1
- package/src/utils/google-places/googlePlacesUtils.test.ts +72 -3
- package/src/utils/google-places/googlePlacesUtils.ts +15 -2
- package/src/utils/google-places/loadGoogleMapsScript.test.ts +58 -1
- package/src/utils/google-places/loadGoogleMapsScript.ts +2 -1
- package/src/utils/index.ts +52 -11
- package/src/utils/location/location.test.ts +18 -115
- package/src/utils/performance/__tests__/bundleAnalysis.test.ts +148 -0
- package/src/utils/performance/__tests__/performanceBenchmark.test.ts +251 -0
- package/src/utils/performance/__tests__/performanceBudgets.test.ts +241 -0
- package/src/utils/performance/bundleAnalysis.ts +16 -22
- package/src/utils/performance/performanceBenchmark.ts +12 -4
- package/src/utils/performance/performanceBudgets.ts +9 -6
- package/src/utils/permissions/__tests__/permissionTypes.test.ts +149 -0
- package/src/utils/permissions/permissionUtils.test.ts +20 -42
- package/src/utils/persistence/__tests__/keyDerivation.test.ts +180 -9
- package/src/utils/persistence/__tests__/sensitiveFieldDetection.test.ts +164 -16
- package/src/utils/persistence/sensitiveFieldDetection.ts +2 -2
- package/src/utils/request-deduplication.ts +6 -4
- package/src/utils/security/auth-utils.ts +7 -7
- package/src/utils/security/secureDataAccess.test.ts +22 -191
- package/src/utils/security/secureErrors.test.ts +163 -0
- package/src/utils/security/secureStorage.test.ts +156 -0
- package/src/utils/security/secureStorage.ts +1 -1
- package/src/utils/security/security.test.ts +204 -0
- package/src/utils/security/securityMonitor.test.ts +90 -0
- package/src/utils/security/securityMonitor.ts +1 -1
- package/src/utils/storage/__tests__/config.unit.test.ts +239 -0
- package/src/utils/storage/__tests__/index.unit.test.ts +64 -12
- package/src/utils/storage/helpers.test.ts +757 -430
- package/src/utils/storage/helpers.ts +1 -2
- package/src/utils/storage/{index.ts → storageUtils.ts} +1 -36
- package/src/utils/storage/types.ts +2 -2
- package/src/utils/supabase/createBaseClient.test.ts +201 -0
- package/src/utils/supabase/createBaseClient.ts +27 -8
- package/src/utils/timezone/timezone.test.ts +25 -43
- package/src/utils/validation/__tests__/common.test.ts +115 -0
- package/src/utils/validation/__tests__/csrf.test.ts +65 -0
- package/src/utils/validation/__tests__/htmlSanitization.unit.test.ts +27 -7
- package/src/utils/validation/__tests__/passwordSchema.test.ts +164 -0
- package/src/utils/validation/__tests__/schema.test.ts +127 -0
- package/src/utils/validation/__tests__/sqlInjectionProtection.test.ts +76 -3
- package/src/utils/validation/__tests__/user.test.ts +173 -0
- package/src/utils/validation/__tests__/validation.test.ts +197 -0
- package/src/utils/validation/__tests__/validationUtils.test.ts +265 -43
- package/src/utils/validation/htmlSanitization.ts +27 -31
- package/src/utils/validation/schema.ts +6 -3
- package/src/utils/validation/sqlInjectionProtection.ts +2 -2
- package/src/vite-env.d.ts +6 -0
- package/dist/DataTable-DRUIgtUH.d.ts +0 -166
- package/dist/UnifiedAuthProvider-7SNDOWYD.js +0 -7
- package/dist/audit-MYQXYZFU.js +0 -3
- package/dist/chunk-7ILTDCL2.js +0 -80
- package/dist/chunk-EF2UGZWY.js +0 -611
- package/dist/chunk-FEJLJNWA.js +0 -181
- package/dist/chunk-GS5672WG.js +0 -2003
- package/dist/chunk-S6ZQKDY6.js +0 -62
- package/dist/chunk-Z2FNRKF3.js +0 -994
- package/dist/useToast-AyaT-x7p.d.ts +0 -68
- package/src/components/DataTable/components/index.ts +0 -16
- package/src/components/DataTable/core/index.ts +0 -1
- package/src/components/DataTable/hooks/index.ts +0 -13
- package/src/components/DataTable/utils/index.ts +0 -9
- package/src/components/PublicLayout/index.ts +0 -32
- package/src/hooks/__tests__/usePermissionCache.simple.test.ts +0 -192
- package/src/hooks/__tests__/usePermissionCache.unit.test.ts +0 -741
- package/src/hooks/public/index.ts +0 -36
- package/src/hooks/usePermissionCache.test.ts +0 -536
- package/src/rbac/__tests__/isSuperAdmin.real.test.ts +0 -82
- package/src/rbac/audit-enhanced.ts +0 -384
- package/src/rbac/compliance/database-validator.ts +0 -165
- package/src/rbac/compliance/index.ts +0 -48
- package/src/rbac/compliance/pattern-detector.ts +0 -553
- package/src/rbac/compliance/quick-fix-suggestions.ts +0 -209
- package/src/rbac/compliance/runtime-compliance.ts +0 -99
- package/src/rbac/compliance/setup-validator.ts +0 -131
- package/src/rbac/components/index.ts +0 -26
- package/src/rbac/hooks/index.ts +0 -34
- package/src/rbac/hooks/permissions/index.ts +0 -4
- package/src/rbac/hooks/useRBAC.simple.test.ts +0 -95
- package/src/rbac/utils/__tests__/eventContext.unit.test.ts +0 -490
- package/src/utils/app/appNameResolver.simple.test.ts +0 -212
- package/src/utils/google-places/index.ts +0 -26
- package/src/utils/location/index.ts +0 -16
- package/src/utils/storage/__tests__/helpers.unit.test.ts +0 -332
- package/src/utils/timezone/index.ts +0 -17
- package/src/utils/validation/index.ts +0 -73
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
import { AccessDenied } from './chunk-
|
|
2
|
-
import { Input, Dialog, DialogContent, DialogHeader, DialogBody, DialogFooter, Select, SelectTrigger,
|
|
3
|
-
import { Button,
|
|
4
|
-
import { useAddressAutocomplete, createFileReferenceService, uploadFileWithReference, usePublicFileDisplay, useFileDisplay, getPublicUrl, getSignedUrl, generateFileUrlsBatch, useEventTheme, usePreventTabReload } from './chunk-
|
|
5
|
-
import { clearPalette } from './chunk-
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
1
|
+
import { useRBAC, useSecureSupabase, useEvents, AccessDenied } from './chunk-X5EAU5G7.js';
|
|
2
|
+
import { Input, Dialog, DialogContent, DialogHeader, DialogBody, DialogFooter, Label, Select, SelectTrigger, SelectContent, SelectLabel, SelectSeparator, SelectItem, DialogTitle, SelectValue, deriveFormKey, useSessionDraft, filterSensitiveFields, isSensitiveField, SelectGroup, Progress } from './chunk-MPY44PWB.js';
|
|
3
|
+
import { Button, Card, CardHeader, CardTitle, CardDescription, CardContent, Alert, AlertDescription, CardFooter, useResolvedScope, usePermissions, useCan, AlertTitle } from './chunk-KYURMOQM.js';
|
|
4
|
+
import { useAddressAutocomplete, createFileReferenceService, uploadFileWithReference, usePublicFileDisplay, useFileDisplay, getPublicUrl, getSignedUrl, generateFileUrlsBatch, useEventTheme, usePreventTabReload } from './chunk-FBZ7U3ID.js';
|
|
5
|
+
import { clearPalette } from './chunk-JJEYZ3DX.js';
|
|
6
|
+
import { useOrganisationSecurity } from './chunk-KPYQWGFQ.js';
|
|
7
|
+
import { useToast } from './chunk-BCTXBU6U.js';
|
|
8
|
+
import { useIsPublicPage, PublicPageContext, useAppConfig } from './chunk-3GWSPISD.js';
|
|
9
|
+
import { useUnifiedAuth, useOrganisations, UnifiedAuthContext, EventServiceContext, useSessionRestoration } from './chunk-Y4PF6HIM.js';
|
|
10
|
+
import { EventContextRequiredError, OrganisationContextRequiredError, isSuperAdmin } from './chunk-LNHFAF4X.js';
|
|
10
11
|
import { assertAppId } from './chunk-4SXLQIZO.js';
|
|
11
|
-
import { getAppId } from './chunk-
|
|
12
|
-
import { LoadingSpinner } from './chunk-
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import
|
|
16
|
-
import
|
|
17
|
-
import React6__default, { useState, useRef, useMemo, useCallback, useEffect, useContext } from 'react';
|
|
12
|
+
import { getUserTimeZone, getAppIcon, getAppId } from './chunk-FN52B75D.js';
|
|
13
|
+
import { cn, LoadingSpinner, getCurrentAppName } from './chunk-UZNAFKGW.js';
|
|
14
|
+
import { performanceBudgetMonitor } from './chunk-7YDC7LMU.js';
|
|
15
|
+
import { createLogger, logger } from './chunk-BTHN5MKC.js';
|
|
16
|
+
import * as React from 'react';
|
|
17
|
+
import React__default, { useState, useRef, useMemo, useCallback, useEffect, createContext, useContext, Component } from 'react';
|
|
18
18
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
19
|
-
import { FileText, ExternalLink, X, ChevronDown, KeyRound, LogOut, Calendar as Calendar$1, Building2, AlertCircle, RefreshCw, File, Check } from 'lucide-react';
|
|
19
|
+
import { FileText, ExternalLink, X, ChevronDown, KeyRound, LogOut, Clock, Calendar as Calendar$1, Building2, AlertCircle, RefreshCw, File, Check } from 'lucide-react';
|
|
20
20
|
import * as SwitchPrimitive from '@radix-ui/react-switch';
|
|
21
21
|
import * as TabsPrimitive from '@radix-ui/react-tabs';
|
|
22
|
-
import {
|
|
22
|
+
import { DayPicker } from 'react-day-picker';
|
|
23
23
|
import { enAU } from 'date-fns/locale';
|
|
24
|
-
import { format } from 'date-fns';
|
|
25
24
|
import * as ToastPrimitives from '@radix-ui/react-toast';
|
|
26
25
|
import { useForm, useWatch, FormProvider, useFormContext, Controller } from 'react-hook-form';
|
|
27
26
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
28
27
|
import { useLocation, Link, useNavigate, Outlet, Navigate } from 'react-router-dom';
|
|
28
|
+
import { createClient } from '@supabase/supabase-js';
|
|
29
29
|
|
|
30
|
-
var AddressField =
|
|
30
|
+
var AddressField = React.forwardRef(
|
|
31
31
|
({
|
|
32
32
|
apiKey,
|
|
33
33
|
value: controlledValue,
|
|
@@ -46,14 +46,14 @@ var AddressField = React6.forwardRef(
|
|
|
46
46
|
cacheTTL,
|
|
47
47
|
...props
|
|
48
48
|
}, ref) => {
|
|
49
|
-
const [internalValue, setInternalValue] =
|
|
50
|
-
const [isOpen, setIsOpen] =
|
|
51
|
-
const [selectedIndex, setSelectedIndex] =
|
|
52
|
-
const [inputFocused, setInputFocused] =
|
|
53
|
-
const inputRef =
|
|
54
|
-
const suggestionsRef =
|
|
55
|
-
const containerRef =
|
|
56
|
-
const blurTimeoutRef =
|
|
49
|
+
const [internalValue, setInternalValue] = React.useState(defaultValue);
|
|
50
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
51
|
+
const [selectedIndex, setSelectedIndex] = React.useState(-1);
|
|
52
|
+
const [inputFocused, setInputFocused] = React.useState(false);
|
|
53
|
+
const inputRef = React.useRef(null);
|
|
54
|
+
const suggestionsRef = React.useRef(null);
|
|
55
|
+
const containerRef = React.useRef(null);
|
|
56
|
+
const blurTimeoutRef = React.useRef(null);
|
|
57
57
|
const value = controlledValue !== void 0 ? controlledValue : internalValue;
|
|
58
58
|
const { suggestions, isLoading, error: autocompleteError, selectAddress, clearSuggestions } = useAddressAutocomplete(apiKey, value, {
|
|
59
59
|
autocompleteOptions,
|
|
@@ -61,14 +61,14 @@ var AddressField = React6.forwardRef(
|
|
|
61
61
|
cacheEnabled,
|
|
62
62
|
cacheTTL
|
|
63
63
|
});
|
|
64
|
-
|
|
64
|
+
React.useEffect(() => {
|
|
65
65
|
if (suggestions.length > 0 && inputFocused && value.trim()) {
|
|
66
66
|
setIsOpen(true);
|
|
67
67
|
} else if (suggestions.length === 0 || !value.trim()) {
|
|
68
68
|
setIsOpen(false);
|
|
69
69
|
}
|
|
70
70
|
}, [suggestions, inputFocused, value]);
|
|
71
|
-
const handleInputChange =
|
|
71
|
+
const handleInputChange = React.useCallback(
|
|
72
72
|
(e) => {
|
|
73
73
|
const newValue = e.target.value;
|
|
74
74
|
if (controlledValue === void 0) {
|
|
@@ -83,7 +83,7 @@ var AddressField = React6.forwardRef(
|
|
|
83
83
|
},
|
|
84
84
|
[controlledValue, onInputChange, onChange, clearSuggestions]
|
|
85
85
|
);
|
|
86
|
-
const handleSelectAddress =
|
|
86
|
+
const handleSelectAddress = React.useCallback(
|
|
87
87
|
async (placeId) => {
|
|
88
88
|
setIsOpen(false);
|
|
89
89
|
setSelectedIndex(-1);
|
|
@@ -100,7 +100,7 @@ var AddressField = React6.forwardRef(
|
|
|
100
100
|
},
|
|
101
101
|
[selectAddress, onChange, onInputChange, controlledValue]
|
|
102
102
|
);
|
|
103
|
-
const handleKeyDown =
|
|
103
|
+
const handleKeyDown = React.useCallback(
|
|
104
104
|
(e) => {
|
|
105
105
|
if (!isOpen || suggestions.length === 0) {
|
|
106
106
|
if (e.key === "Escape") {
|
|
@@ -138,14 +138,14 @@ var AddressField = React6.forwardRef(
|
|
|
138
138
|
},
|
|
139
139
|
[isOpen, suggestions, selectedIndex, handleSelectAddress]
|
|
140
140
|
);
|
|
141
|
-
const handleFocus =
|
|
141
|
+
const handleFocus = React.useCallback(() => {
|
|
142
142
|
setInputFocused(true);
|
|
143
143
|
if (suggestions.length > 0 && value.trim()) {
|
|
144
144
|
setIsOpen(true);
|
|
145
145
|
}
|
|
146
146
|
}, [suggestions, value]);
|
|
147
|
-
const handleBlur =
|
|
148
|
-
(
|
|
147
|
+
const handleBlur = React.useCallback(
|
|
148
|
+
(_e) => {
|
|
149
149
|
if (blurTimeoutRef.current) {
|
|
150
150
|
clearTimeout(blurTimeoutRef.current);
|
|
151
151
|
blurTimeoutRef.current = null;
|
|
@@ -165,7 +165,7 @@ var AddressField = React6.forwardRef(
|
|
|
165
165
|
},
|
|
166
166
|
[]
|
|
167
167
|
);
|
|
168
|
-
|
|
168
|
+
React.useEffect(() => {
|
|
169
169
|
return () => {
|
|
170
170
|
if (blurTimeoutRef.current) {
|
|
171
171
|
clearTimeout(blurTimeoutRef.current);
|
|
@@ -173,7 +173,7 @@ var AddressField = React6.forwardRef(
|
|
|
173
173
|
}
|
|
174
174
|
};
|
|
175
175
|
}, []);
|
|
176
|
-
|
|
176
|
+
React.useEffect(() => {
|
|
177
177
|
const handleClickOutside = (event) => {
|
|
178
178
|
if (containerRef.current && !containerRef.current.contains(event.target)) {
|
|
179
179
|
setIsOpen(false);
|
|
@@ -187,8 +187,8 @@ var AddressField = React6.forwardRef(
|
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
189
|
}, [isOpen]);
|
|
190
|
-
const suggestionsId =
|
|
191
|
-
|
|
190
|
+
const suggestionsId = React.useId();
|
|
191
|
+
React.useEffect(() => {
|
|
192
192
|
if (selectedIndex >= 0) {
|
|
193
193
|
const selectedItem = document.getElementById(
|
|
194
194
|
`${suggestionsId}-item-${selectedIndex}`
|
|
@@ -198,7 +198,7 @@ var AddressField = React6.forwardRef(
|
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
200
|
}, [selectedIndex, suggestionsId]);
|
|
201
|
-
|
|
201
|
+
React.useImperativeHandle(ref, () => inputRef.current);
|
|
202
202
|
const hasError = error || !!autocompleteError;
|
|
203
203
|
return /* @__PURE__ */ jsxs("form", { ref: containerRef, className: cn("relative w-full", className), children: [
|
|
204
204
|
/* @__PURE__ */ jsx(
|
|
@@ -238,7 +238,7 @@ var AddressField = React6.forwardRef(
|
|
|
238
238
|
"list-none p-0 m-0"
|
|
239
239
|
),
|
|
240
240
|
"data-testid": "address-suggestions",
|
|
241
|
-
children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxs(
|
|
241
|
+
children: suggestions.map((suggestion, index) => /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
242
242
|
/* @__PURE__ */ jsx(
|
|
243
243
|
"dt",
|
|
244
244
|
{
|
|
@@ -420,7 +420,7 @@ function defaultGenerateFallbackText(fileName) {
|
|
|
420
420
|
if (words.length === 0) return "FL";
|
|
421
421
|
return words.map((word) => word.charAt(0).toUpperCase()).join("").substring(0, 3);
|
|
422
422
|
}
|
|
423
|
-
var FileDisplayContent =
|
|
423
|
+
var FileDisplayContent = React__default.memo(function FileDisplayContent2({
|
|
424
424
|
isLoading,
|
|
425
425
|
error,
|
|
426
426
|
fileUrl,
|
|
@@ -436,7 +436,7 @@ var FileDisplayContent = React6__default.memo(function FileDisplayContent2({
|
|
|
436
436
|
children,
|
|
437
437
|
onDelete,
|
|
438
438
|
clearError,
|
|
439
|
-
organisation_id,
|
|
439
|
+
organisation_id: _organisation_id,
|
|
440
440
|
loadingComponent: LoadingComponent,
|
|
441
441
|
errorComponent: ErrorComponent,
|
|
442
442
|
showFallback = false,
|
|
@@ -495,7 +495,7 @@ var FileDisplayContent = React6__default.memo(function FileDisplayContent2({
|
|
|
495
495
|
await onDelete();
|
|
496
496
|
}
|
|
497
497
|
setImageError(false);
|
|
498
|
-
} catch (
|
|
498
|
+
} catch (_error) {
|
|
499
499
|
setImageError(false);
|
|
500
500
|
}
|
|
501
501
|
};
|
|
@@ -564,7 +564,7 @@ var FileDisplayContent = React6__default.memo(function FileDisplayContent2({
|
|
|
564
564
|
if (LoadingComponent) {
|
|
565
565
|
return /* @__PURE__ */ jsx(LoadingComponent, {});
|
|
566
566
|
}
|
|
567
|
-
return /* @__PURE__ */ jsx("figure", { className, title: "Loading", children: /* @__PURE__ */ jsx("
|
|
567
|
+
return /* @__PURE__ */ jsx("figure", { className, title: "Loading", children: /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center p-4", children: /* @__PURE__ */ jsx(LoadingSpinner, {}) }) });
|
|
568
568
|
}
|
|
569
569
|
if ((category || displayOnly) && fileReference) {
|
|
570
570
|
const isImage = fileReference.file_metadata.fileType?.startsWith("image/");
|
|
@@ -680,7 +680,7 @@ var FileDisplayContent = React6__default.memo(function FileDisplayContent2({
|
|
|
680
680
|
] })
|
|
681
681
|
] })
|
|
682
682
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
683
|
-
/* @__PURE__ */ jsxs("
|
|
683
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
|
|
684
684
|
/* @__PURE__ */ jsx("span", { className: "text-2xl", children: getFileIcon(fileReference.file_metadata.fileType || "") }),
|
|
685
685
|
showDelete && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
686
686
|
/* @__PURE__ */ jsx(
|
|
@@ -743,7 +743,7 @@ var FileDisplayContent = React6__default.memo(function FileDisplayContent2({
|
|
|
743
743
|
fileRef.file_metadata.category
|
|
744
744
|
] })
|
|
745
745
|
] }),
|
|
746
|
-
/* @__PURE__ */ jsxs("
|
|
746
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2", children: [
|
|
747
747
|
canDownload && /* @__PURE__ */ jsx(
|
|
748
748
|
"a",
|
|
749
749
|
{
|
|
@@ -800,8 +800,7 @@ function FileDisplayPublic({
|
|
|
800
800
|
fileUrls,
|
|
801
801
|
fileCount,
|
|
802
802
|
isLoading,
|
|
803
|
-
error
|
|
804
|
-
refetch
|
|
803
|
+
error
|
|
805
804
|
} = usePublicFileDisplay(
|
|
806
805
|
table_name,
|
|
807
806
|
record_id,
|
|
@@ -1081,7 +1080,6 @@ function FileDisplay({
|
|
|
1081
1080
|
}
|
|
1082
1081
|
);
|
|
1083
1082
|
}
|
|
1084
|
-
createLogger("useFileReference");
|
|
1085
1083
|
var urlRefreshManager = {
|
|
1086
1084
|
subscriptions: /* @__PURE__ */ new Map(),
|
|
1087
1085
|
subscribe(key, callback) {
|
|
@@ -1156,7 +1154,7 @@ function useFileReference(supabase) {
|
|
|
1156
1154
|
setIsLoading(false);
|
|
1157
1155
|
}
|
|
1158
1156
|
}, [service]);
|
|
1159
|
-
const
|
|
1157
|
+
const getSignedUrl2 = useCallback(async (table_name, record_id, organisation_id, expires_in) => {
|
|
1160
1158
|
setIsLoading(true);
|
|
1161
1159
|
setError(null);
|
|
1162
1160
|
try {
|
|
@@ -1257,7 +1255,7 @@ function useFileReference(supabase) {
|
|
|
1257
1255
|
getFileReference,
|
|
1258
1256
|
getFileReferenceById,
|
|
1259
1257
|
getFileUrl,
|
|
1260
|
-
getSignedUrl:
|
|
1258
|
+
getSignedUrl: getSignedUrl2,
|
|
1261
1259
|
updateFileReference,
|
|
1262
1260
|
deleteFileReference,
|
|
1263
1261
|
listFileReferences,
|
|
@@ -1383,7 +1381,7 @@ function useFileReferenceById(supabase, fileReferenceId, organisationId) {
|
|
|
1383
1381
|
organisationId
|
|
1384
1382
|
);
|
|
1385
1383
|
setFileUrl(url);
|
|
1386
|
-
} catch (
|
|
1384
|
+
} catch (_error) {
|
|
1387
1385
|
setFileUrl(null);
|
|
1388
1386
|
}
|
|
1389
1387
|
};
|
|
@@ -1443,7 +1441,7 @@ var sizeClasses = {
|
|
|
1443
1441
|
xl: "size-16 text-xl",
|
|
1444
1442
|
"2xl": "size-20 text-2xl"
|
|
1445
1443
|
};
|
|
1446
|
-
var Avatar =
|
|
1444
|
+
var Avatar = React.forwardRef(
|
|
1447
1445
|
({
|
|
1448
1446
|
table_name,
|
|
1449
1447
|
record_id,
|
|
@@ -1457,10 +1455,10 @@ var Avatar = React6.forwardRef(
|
|
|
1457
1455
|
size = "md",
|
|
1458
1456
|
...props
|
|
1459
1457
|
}, ref) => {
|
|
1460
|
-
const [imageError, setImageError] =
|
|
1458
|
+
const [imageError, setImageError] = React.useState(false);
|
|
1461
1459
|
const { supabase } = useUnifiedAuth();
|
|
1462
1460
|
const canFetchFileId = Boolean(fileId && organisation_id && supabase);
|
|
1463
|
-
const {
|
|
1461
|
+
const { fileUrl: fileIdUrl, isLoading: fileIdLoading } = useFileReferenceById(
|
|
1464
1462
|
supabase || {},
|
|
1465
1463
|
// Hook requires SupabaseClient, but we check canFetchFileId before using result
|
|
1466
1464
|
canFetchFileId ? fileId : null,
|
|
@@ -1474,10 +1472,10 @@ var Avatar = React6.forwardRef(
|
|
|
1474
1472
|
const fallbackClasses = "size-full grid place-items-center text-center text-sec-50 bg-sec-500";
|
|
1475
1473
|
const imageClasses = "object-cover size-full";
|
|
1476
1474
|
const containerClasses = cn(baseClasses, className);
|
|
1477
|
-
const handleImageError =
|
|
1475
|
+
const handleImageError = React.useCallback(() => {
|
|
1478
1476
|
setImageError(true);
|
|
1479
1477
|
}, []);
|
|
1480
|
-
|
|
1478
|
+
React.useEffect(() => {
|
|
1481
1479
|
if (src) {
|
|
1482
1480
|
setImageError(false);
|
|
1483
1481
|
}
|
|
@@ -1626,7 +1624,7 @@ function Badge({ className, variant = "solid-main-normal", ref, ...props }) {
|
|
|
1626
1624
|
);
|
|
1627
1625
|
}
|
|
1628
1626
|
Badge.displayName = "Badge";
|
|
1629
|
-
var Switch =
|
|
1627
|
+
var Switch = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
1630
1628
|
SwitchPrimitive.Root,
|
|
1631
1629
|
{
|
|
1632
1630
|
className: cn(
|
|
@@ -1667,9 +1665,9 @@ var Switch = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
|
|
|
1667
1665
|
}
|
|
1668
1666
|
));
|
|
1669
1667
|
Switch.displayName = SwitchPrimitive.Root.displayName;
|
|
1670
|
-
var Tabs =
|
|
1668
|
+
var Tabs = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(TabsPrimitive.Root, { asChild: true, ...props, children: /* @__PURE__ */ jsx("section", { ref, className, children }) }));
|
|
1671
1669
|
Tabs.displayName = TabsPrimitive.Root.displayName || "Tabs";
|
|
1672
|
-
var TabsList =
|
|
1670
|
+
var TabsList = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(TabsPrimitive.List, { asChild: true, ...props, children: /* @__PURE__ */ jsx(
|
|
1673
1671
|
"nav",
|
|
1674
1672
|
{
|
|
1675
1673
|
ref,
|
|
@@ -1681,7 +1679,7 @@ var TabsList = React6.forwardRef(({ className, children, ...props }, ref) => /*
|
|
|
1681
1679
|
}
|
|
1682
1680
|
) }));
|
|
1683
1681
|
TabsList.displayName = TabsPrimitive.List.displayName || "TabsList";
|
|
1684
|
-
var TabsTrigger =
|
|
1682
|
+
var TabsTrigger = React.forwardRef(({ className, variant, size = "lg", children, ...props }, ref) => {
|
|
1685
1683
|
return /* @__PURE__ */ jsx(TabsPrimitive.Trigger, { asChild: true, ...props, children: /* @__PURE__ */ jsx(
|
|
1686
1684
|
Button,
|
|
1687
1685
|
{
|
|
@@ -1689,9 +1687,9 @@ var TabsTrigger = React6.forwardRef(({ className, variant, size, children, ...pr
|
|
|
1689
1687
|
variant,
|
|
1690
1688
|
size,
|
|
1691
1689
|
className: cn(
|
|
1692
|
-
"rounded-b-none",
|
|
1690
|
+
"rounded-b-none text-lg px-4",
|
|
1693
1691
|
"data-[state=active]:bg-main-50 data-[state=active]:text-main-950 data-[state=active]:border-t-1 data-[state=active]:border-x-1 data-[state=active]:shadow-md",
|
|
1694
|
-
"data-[state=inactive]:bg-main-300 data-[state=inactive]:text-main-800 ",
|
|
1692
|
+
"data-[state=inactive]:bg-main-300 data-[state=inactive]:text-main-800 data-[state=inactive]:border-t-1 data-[state=inactive]:border-x-1",
|
|
1695
1693
|
"data-[state=inactive]:hover:bg-acc-400",
|
|
1696
1694
|
className
|
|
1697
1695
|
),
|
|
@@ -1700,7 +1698,7 @@ var TabsTrigger = React6.forwardRef(({ className, variant, size, children, ...pr
|
|
|
1700
1698
|
) });
|
|
1701
1699
|
});
|
|
1702
1700
|
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName || "TabsTrigger";
|
|
1703
|
-
var TabsContent =
|
|
1701
|
+
var TabsContent = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsx(TabsPrimitive.Content, { asChild: true, ...props, children: /* @__PURE__ */ jsx(
|
|
1704
1702
|
"aside",
|
|
1705
1703
|
{
|
|
1706
1704
|
ref,
|
|
@@ -1712,41 +1710,58 @@ var TabsContent = React6.forwardRef(({ className, children, ...props }, ref) =>
|
|
|
1712
1710
|
}
|
|
1713
1711
|
) }));
|
|
1714
1712
|
TabsContent.displayName = TabsPrimitive.Content.displayName || "TabsContent";
|
|
1715
|
-
var
|
|
1716
|
-
if (!ref) {
|
|
1717
|
-
return;
|
|
1718
|
-
}
|
|
1719
|
-
if (typeof ref === "function") {
|
|
1720
|
-
ref(value);
|
|
1721
|
-
return;
|
|
1722
|
-
}
|
|
1723
|
-
ref.current = value;
|
|
1724
|
-
};
|
|
1725
|
-
var Calendar = React6.forwardRef(
|
|
1713
|
+
var Calendar = React.forwardRef(
|
|
1726
1714
|
({ className, classNames, mode, components, locale, month: controlledMonth, onMonthChange: controlledOnMonthChange, onSelect, captionLayout, startMonth, endMonth, ...props }, ref) => {
|
|
1727
|
-
const
|
|
1728
|
-
|
|
1729
|
-
(
|
|
1730
|
-
|
|
1731
|
-
if (
|
|
1732
|
-
|
|
1715
|
+
const dayPickerRef = React.useRef(null);
|
|
1716
|
+
React.useEffect(() => {
|
|
1717
|
+
if (ref && dayPickerRef.current) {
|
|
1718
|
+
const tableElement = dayPickerRef.current.querySelector("table");
|
|
1719
|
+
if (tableElement && typeof ref === "function") {
|
|
1720
|
+
ref(tableElement);
|
|
1721
|
+
} else if (tableElement && ref && "current" in ref) {
|
|
1722
|
+
ref.current = tableElement;
|
|
1733
1723
|
}
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
} else {
|
|
1737
|
-
ref.current = node;
|
|
1738
|
-
}
|
|
1739
|
-
},
|
|
1740
|
-
[ref]
|
|
1741
|
-
);
|
|
1742
|
-
const rootPropsRef = React6.useRef(null);
|
|
1724
|
+
}
|
|
1725
|
+
}, [ref]);
|
|
1743
1726
|
const selected = props.selected;
|
|
1744
1727
|
const isMonthControlled = controlledMonth !== void 0;
|
|
1745
|
-
const [internalMonth, setInternalMonth] =
|
|
1728
|
+
const [internalMonth, setInternalMonth] = React.useState(() => {
|
|
1729
|
+
if (selected) {
|
|
1730
|
+
if (selected instanceof Date) {
|
|
1731
|
+
return new Date(selected.getFullYear(), selected.getMonth(), 1);
|
|
1732
|
+
}
|
|
1733
|
+
if (typeof selected === "object" && "from" in selected && selected.from) {
|
|
1734
|
+
return new Date(selected.from.getFullYear(), selected.from.getMonth(), 1);
|
|
1735
|
+
}
|
|
1736
|
+
if (Array.isArray(selected) && selected.length > 0 && selected[0] instanceof Date) {
|
|
1737
|
+
return new Date(selected[0].getFullYear(), selected[0].getMonth(), 1);
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1746
1740
|
const now = /* @__PURE__ */ new Date();
|
|
1747
1741
|
return new Date(now.getFullYear(), now.getMonth(), 1);
|
|
1748
1742
|
});
|
|
1749
|
-
|
|
1743
|
+
React.useEffect(() => {
|
|
1744
|
+
if (!isMonthControlled && selected) {
|
|
1745
|
+
let monthToSync = null;
|
|
1746
|
+
if (selected instanceof Date) {
|
|
1747
|
+
monthToSync = new Date(selected.getFullYear(), selected.getMonth(), 1);
|
|
1748
|
+
} else if (typeof selected === "object" && "from" in selected && selected.from) {
|
|
1749
|
+
monthToSync = new Date(selected.from.getFullYear(), selected.from.getMonth(), 1);
|
|
1750
|
+
} else if (Array.isArray(selected) && selected.length > 0 && selected[0] instanceof Date) {
|
|
1751
|
+
monthToSync = new Date(selected[0].getFullYear(), selected[0].getMonth(), 1);
|
|
1752
|
+
}
|
|
1753
|
+
if (monthToSync) {
|
|
1754
|
+
setInternalMonth((prevMonth) => {
|
|
1755
|
+
const currentMonth = new Date(prevMonth.getFullYear(), prevMonth.getMonth(), 1);
|
|
1756
|
+
if (monthToSync.getTime() !== currentMonth.getTime()) {
|
|
1757
|
+
return monthToSync;
|
|
1758
|
+
}
|
|
1759
|
+
return prevMonth;
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
}
|
|
1763
|
+
}, [selected, isMonthControlled]);
|
|
1764
|
+
const month = React.useMemo(() => {
|
|
1750
1765
|
const monthToUse = isMonthControlled ? controlledMonth : internalMonth;
|
|
1751
1766
|
if (!monthToUse) {
|
|
1752
1767
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -1755,350 +1770,98 @@ var Calendar = React6.forwardRef(
|
|
|
1755
1770
|
const normalized = new Date(monthToUse.getFullYear(), monthToUse.getMonth(), 1);
|
|
1756
1771
|
return normalized;
|
|
1757
1772
|
}, [isMonthControlled, controlledMonth, internalMonth]);
|
|
1758
|
-
const handleMonthChange =
|
|
1773
|
+
const handleMonthChange = React.useCallback((newMonth) => {
|
|
1759
1774
|
if (!isMonthControlled) {
|
|
1760
1775
|
setInternalMonth(newMonth);
|
|
1761
1776
|
}
|
|
1762
1777
|
controlledOnMonthChange?.(newMonth);
|
|
1763
1778
|
}, [isMonthControlled, controlledOnMonthChange]);
|
|
1764
|
-
const
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
}
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
const yearOptions = React6.useMemo(() => {
|
|
1830
|
-
const years = [];
|
|
1831
|
-
const startYear = fromDate.getFullYear();
|
|
1832
|
-
const endYear = toDate.getFullYear();
|
|
1833
|
-
for (let year = startYear; year <= endYear; year++) {
|
|
1834
|
-
years.push({ value: year.toString(), label: year.toString() });
|
|
1835
|
-
}
|
|
1836
|
-
return years;
|
|
1837
|
-
}, [fromDate, toDate]);
|
|
1838
|
-
const currentMonth = displayMonth.getMonth();
|
|
1839
|
-
const currentYear = displayMonth.getFullYear();
|
|
1840
|
-
const handleMonthChange2 = React6.useCallback((value) => {
|
|
1841
|
-
const newMonth = parseInt(value, 10);
|
|
1842
|
-
const newDate = new Date(currentYear, newMonth, 1);
|
|
1843
|
-
goToMonth(newDate);
|
|
1844
|
-
}, [currentYear, goToMonth]);
|
|
1845
|
-
const handleYearChange = React6.useCallback((value) => {
|
|
1846
|
-
const newYear = parseInt(value, 10);
|
|
1847
|
-
const newDate = new Date(newYear, currentMonth, 1);
|
|
1848
|
-
goToMonth(newDate);
|
|
1849
|
-
}, [currentMonth, goToMonth]);
|
|
1850
|
-
return /* @__PURE__ */ jsxs("nav", { className: "relative flex items-center justify-center gap-2", children: [
|
|
1851
|
-
/* @__PURE__ */ jsxs(Select, { value: currentMonth.toString(), onValueChange: handleMonthChange2, children: [
|
|
1852
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-auto min-w-[120px]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
1853
|
-
/* @__PURE__ */ jsx(SelectContent, { children: monthOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
1854
|
-
] }),
|
|
1855
|
-
/* @__PURE__ */ jsxs(Select, { value: currentYear.toString(), onValueChange: handleYearChange, children: [
|
|
1856
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-auto min-w-[100px]", children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
1857
|
-
/* @__PURE__ */ jsx(SelectContent, { children: yearOptions.map((option) => /* @__PURE__ */ jsx(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
1858
|
-
] })
|
|
1859
|
-
] });
|
|
1860
|
-
});
|
|
1861
|
-
CustomMonthCaption.displayName = "CustomMonthCaption";
|
|
1862
|
-
const CustomMonth = React6.memo(({ calendarMonth, displayIndex, className: className2, children, captionLayout: monthCaptionLayout, startMonth: monthStartMonth, endMonth: monthEndMonth }) => {
|
|
1863
|
-
const { formatters, components: components2, labels, classNames: classNames2, previousMonth, nextMonth, goToMonth } = useDayPicker();
|
|
1864
|
-
const caption = formatters.formatCaption(calendarMonth.date, {});
|
|
1865
|
-
const Chevron = components2?.Chevron;
|
|
1866
|
-
const childrenArray = React6.Children.toArray(children);
|
|
1867
|
-
const monthGridIndex = childrenArray.findIndex((child) => {
|
|
1868
|
-
if (!React6.isValidElement(child)) return false;
|
|
1869
|
-
const childType = child.type;
|
|
1870
|
-
return typeof childType === "function" && childType.displayName === "MonthGrid" || child.type === "table";
|
|
1871
|
-
});
|
|
1872
|
-
return /* @__PURE__ */ jsx(Fragment, { children: childrenArray.map((child, index) => {
|
|
1873
|
-
if (React6.isValidElement(child) && child.type?.displayName === "MonthCaption") {
|
|
1874
|
-
return null;
|
|
1875
|
-
}
|
|
1876
|
-
if (index === monthGridIndex && React6.isValidElement(child)) {
|
|
1877
|
-
const monthGridChild = child;
|
|
1878
|
-
const applyRootProps = displayIndex === 0 && index === monthGridIndex;
|
|
1879
|
-
const storedRootProps = applyRootProps ? rootPropsRef.current : null;
|
|
1880
|
-
const { children: monthGridChildren, className: monthGridClassName, style: monthGridStyle, ...monthGridRest } = monthGridChild.props;
|
|
1881
|
-
const mergedClassName = cn(
|
|
1882
|
-
"w-full border-collapse rounded-md border border-sec-200 bg-background",
|
|
1883
|
-
applyRootProps ? storedRootProps?.className : void 0,
|
|
1884
|
-
className2,
|
|
1885
|
-
monthGridClassName
|
|
1886
|
-
);
|
|
1887
|
-
const mergedStyle = {
|
|
1888
|
-
...applyRootProps ? storedRootProps?.style ?? {} : {},
|
|
1889
|
-
...monthGridStyle ?? {}
|
|
1890
|
-
};
|
|
1891
|
-
const tableProps = {
|
|
1892
|
-
...applyRootProps && storedRootProps?.restProps ? storedRootProps.restProps : {},
|
|
1893
|
-
...monthGridRest,
|
|
1894
|
-
className: mergedClassName,
|
|
1895
|
-
...Object.keys(mergedStyle).length ? { style: mergedStyle } : {}
|
|
1896
|
-
};
|
|
1897
|
-
if (mode && tableProps["data-mode"] === void 0) {
|
|
1898
|
-
tableProps["data-mode"] = mode;
|
|
1899
|
-
}
|
|
1900
|
-
const shouldAttachRef = applyRootProps || storedRootProps?.rootRef;
|
|
1901
|
-
const handleTableRef = shouldAttachRef ? (node) => {
|
|
1902
|
-
if (applyRootProps) {
|
|
1903
|
-
setForwardedRef(node);
|
|
1904
|
-
}
|
|
1905
|
-
if (storedRootProps?.rootRef) {
|
|
1906
|
-
assignToRef(storedRootProps.rootRef, node);
|
|
1907
|
-
}
|
|
1908
|
-
} : void 0;
|
|
1909
|
-
const handlePreviousClick = (event) => {
|
|
1910
|
-
event.preventDefault();
|
|
1911
|
-
if (!previousMonth) return;
|
|
1912
|
-
goToMonth(previousMonth);
|
|
1913
|
-
};
|
|
1914
|
-
const handleNextClick = (event) => {
|
|
1915
|
-
event.preventDefault();
|
|
1916
|
-
if (!nextMonth) return;
|
|
1917
|
-
goToMonth(nextMonth);
|
|
1918
|
-
};
|
|
1919
|
-
const monthGridElement = monthGridChild;
|
|
1920
|
-
const mergedRef = handleTableRef || monthGridElement.ref ? (node) => {
|
|
1921
|
-
if (handleTableRef) {
|
|
1922
|
-
handleTableRef(node);
|
|
1923
|
-
}
|
|
1924
|
-
assignToRef(monthGridElement.ref, node);
|
|
1925
|
-
} : void 0;
|
|
1926
|
-
const isDropdownLayout = monthCaptionLayout === "dropdown";
|
|
1927
|
-
return React6.cloneElement(
|
|
1928
|
-
monthGridElement,
|
|
1929
|
-
{
|
|
1930
|
-
key: child.key ?? `month-grid-${displayIndex}`,
|
|
1931
|
-
...tableProps,
|
|
1932
|
-
...mergedRef ? { ref: mergedRef } : {}
|
|
1933
|
-
},
|
|
1934
|
-
/* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1935
|
-
/* @__PURE__ */ jsx("caption", { className: "relative", children: isDropdownLayout ? /* @__PURE__ */ jsx(
|
|
1936
|
-
CustomMonthCaption,
|
|
1937
|
-
{
|
|
1938
|
-
displayMonth: calendarMonth.date,
|
|
1939
|
-
startMonth: monthStartMonth,
|
|
1940
|
-
endMonth: monthEndMonth,
|
|
1941
|
-
locale
|
|
1942
|
-
}
|
|
1943
|
-
) : /* @__PURE__ */ jsxs("nav", { className: "relative flex items-center justify-center gap-1", children: [
|
|
1944
|
-
/* @__PURE__ */ jsx(
|
|
1945
|
-
"button",
|
|
1946
|
-
{
|
|
1947
|
-
type: "button",
|
|
1948
|
-
className: cn(
|
|
1949
|
-
"h-7 w-7 bg-transparent p-0",
|
|
1950
|
-
"inline-flex items-center justify-center rounded-md",
|
|
1951
|
-
"hover:bg-acc-100",
|
|
1952
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2",
|
|
1953
|
-
"disabled:opacity-50 disabled:pointer-events-none",
|
|
1954
|
-
classNames2?.button_previous
|
|
1955
|
-
),
|
|
1956
|
-
tabIndex: previousMonth ? void 0 : -1,
|
|
1957
|
-
"aria-disabled": previousMonth ? void 0 : true,
|
|
1958
|
-
"aria-label": previousMonth ? labels.labelPrevious(previousMonth) : void 0,
|
|
1959
|
-
onClick: handlePreviousClick,
|
|
1960
|
-
disabled: !previousMonth,
|
|
1961
|
-
children: Chevron ? /* @__PURE__ */ jsx(Chevron, { orientation: "left", className: "size-4", disabled: !previousMonth }) : /* @__PURE__ */ jsx("span", { children: "\u2039" })
|
|
1962
|
-
}
|
|
1963
|
-
),
|
|
1964
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium", children: caption }),
|
|
1965
|
-
/* @__PURE__ */ jsx(
|
|
1966
|
-
"button",
|
|
1967
|
-
{
|
|
1968
|
-
type: "button",
|
|
1969
|
-
className: cn(
|
|
1970
|
-
"h-7 w-7 bg-transparent p-0",
|
|
1971
|
-
"inline-flex items-center justify-center rounded-md",
|
|
1972
|
-
"hover:bg-acc-100",
|
|
1973
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2",
|
|
1974
|
-
"disabled:opacity-50 disabled:pointer-events-none",
|
|
1975
|
-
classNames2?.button_next
|
|
1976
|
-
),
|
|
1977
|
-
tabIndex: nextMonth ? void 0 : -1,
|
|
1978
|
-
"aria-disabled": nextMonth ? void 0 : true,
|
|
1979
|
-
"aria-label": nextMonth ? labels.labelNext(nextMonth) : void 0,
|
|
1980
|
-
onClick: handleNextClick,
|
|
1981
|
-
disabled: !nextMonth,
|
|
1982
|
-
children: Chevron ? /* @__PURE__ */ jsx(Chevron, { orientation: "right", className: "size-4", disabled: !nextMonth }) : /* @__PURE__ */ jsx("span", { children: "\u203A" })
|
|
1983
|
-
}
|
|
1984
|
-
)
|
|
1985
|
-
] }) }),
|
|
1986
|
-
monthGridChildren
|
|
1987
|
-
] })
|
|
1988
|
-
);
|
|
1989
|
-
}
|
|
1990
|
-
return React6.isValidElement(child) ? React6.cloneElement(child, { key: child.key ?? `calendar-child-${index}` }) : child;
|
|
1991
|
-
}) });
|
|
1992
|
-
});
|
|
1993
|
-
CustomMonth.displayName = "CustomMonth";
|
|
1994
|
-
const CustomWeekdays = React6.memo(({ className: className2, children, ...props2 }) => {
|
|
1995
|
-
return /* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { className: cn("text-xs text-sec-500", className2), ...props2, children }) });
|
|
1996
|
-
});
|
|
1997
|
-
CustomWeekdays.displayName = "CustomWeekdays";
|
|
1998
|
-
const CustomMonthWithProps = React6.useCallback((props2) => {
|
|
1999
|
-
return /* @__PURE__ */ jsx(
|
|
2000
|
-
CustomMonth,
|
|
2001
|
-
{
|
|
2002
|
-
...props2,
|
|
2003
|
-
captionLayout,
|
|
2004
|
-
startMonth,
|
|
2005
|
-
endMonth
|
|
2006
|
-
}
|
|
2007
|
-
);
|
|
2008
|
-
}, [captionLayout, startMonth, endMonth]);
|
|
2009
|
-
const CustomMonthCaptionWrapper = React6.memo((_props) => {
|
|
2010
|
-
return null;
|
|
2011
|
-
});
|
|
2012
|
-
CustomMonthCaptionWrapper.displayName = "CustomMonthCaptionWrapper";
|
|
2013
|
-
const defaultComponents = React6.useMemo(() => ({
|
|
2014
|
-
Root: CustomRoot,
|
|
2015
|
-
Months: CustomMonths,
|
|
2016
|
-
Month: CustomMonthWithProps,
|
|
2017
|
-
MonthGrid: CustomMonthGrid,
|
|
2018
|
-
// MonthCaption returns null - actual caption is rendered in CustomMonth inside <caption>
|
|
2019
|
-
MonthCaption: CustomMonthCaptionWrapper,
|
|
2020
|
-
Weekdays: CustomWeekdays,
|
|
2021
|
-
// Spread user components AFTER ours so ours take precedence
|
|
2022
|
-
...components || {}
|
|
2023
|
-
}), [components, CustomRoot, CustomMonths, CustomMonthWithProps, CustomMonthCaptionWrapper, CustomWeekdays]);
|
|
2024
|
-
return /* @__PURE__ */ jsx(
|
|
2025
|
-
DayPicker,
|
|
1779
|
+
const {
|
|
1780
|
+
captionLayout: _captionLayoutFromProps,
|
|
1781
|
+
startMonth: _startMonthFromProps,
|
|
1782
|
+
endMonth: _endMonthFromProps,
|
|
1783
|
+
...restProps
|
|
1784
|
+
} = props;
|
|
1785
|
+
const dayPickerProps = {
|
|
1786
|
+
...mode ? { mode } : {},
|
|
1787
|
+
locale: locale ?? enAU,
|
|
1788
|
+
// Explicitly pass captionLayout, startMonth, endMonth to ensure they're not overridden
|
|
1789
|
+
...captionLayout !== void 0 ? { captionLayout } : {},
|
|
1790
|
+
...startMonth !== void 0 ? { startMonth } : {},
|
|
1791
|
+
...endMonth !== void 0 ? { endMonth } : {},
|
|
1792
|
+
...restProps,
|
|
1793
|
+
...selected !== void 0 ? { selected } : {},
|
|
1794
|
+
...onSelect !== void 0 ? { onSelect } : {},
|
|
1795
|
+
month,
|
|
1796
|
+
onMonthChange: handleMonthChange,
|
|
1797
|
+
className,
|
|
1798
|
+
classNames: {
|
|
1799
|
+
// Basic spacing for calendar grid
|
|
1800
|
+
month_grid: "w-full border-collapse",
|
|
1801
|
+
weekdays: "text-xs text-sec-500",
|
|
1802
|
+
weekday: "w-9 p-0 font-normal text-center",
|
|
1803
|
+
week: "mt-2",
|
|
1804
|
+
day: "p-0 text-center",
|
|
1805
|
+
day_button: cn(
|
|
1806
|
+
"h-9 w-9 p-0 font-normal",
|
|
1807
|
+
"hover:bg-acc-100 hover:text-main-600",
|
|
1808
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2",
|
|
1809
|
+
"inline-flex items-center justify-center rounded-md"
|
|
1810
|
+
),
|
|
1811
|
+
selected: "bg-main-600 text-main-50 hover:bg-main-600 hover:text-main-50",
|
|
1812
|
+
today: "bg-sec-100 text-main-600 font-semibold",
|
|
1813
|
+
disabled: "text-sec-400 opacity-50 cursor-not-allowed",
|
|
1814
|
+
// Caption and dropdown layout styling
|
|
1815
|
+
month_caption: "flex items-center justify-center gap-2 mb-2",
|
|
1816
|
+
caption_label: captionLayout === "dropdown" ? "hidden" : "text-sm font-medium",
|
|
1817
|
+
// Hide label when using dropdowns
|
|
1818
|
+
dropdowns: "flex items-center gap-2",
|
|
1819
|
+
months_dropdown: "px-2 py-1 text-sm border border-sec-300 rounded bg-background",
|
|
1820
|
+
years_dropdown: "px-2 py-1 text-sm border border-sec-300 rounded bg-background",
|
|
1821
|
+
chevron: "hidden",
|
|
1822
|
+
// Hide extra chevron icons
|
|
1823
|
+
...classNames
|
|
1824
|
+
},
|
|
1825
|
+
...components ? { components } : {}
|
|
1826
|
+
};
|
|
1827
|
+
return /* @__PURE__ */ jsx("div", { ref: dayPickerRef, children: /* @__PURE__ */ jsx(DayPicker, { ...dayPickerProps }) });
|
|
1828
|
+
}
|
|
1829
|
+
);
|
|
1830
|
+
Calendar.displayName = "Calendar";
|
|
1831
|
+
function DatePickerWithTimezone({
|
|
1832
|
+
selected,
|
|
1833
|
+
onSelect,
|
|
1834
|
+
onDone,
|
|
1835
|
+
timezone,
|
|
1836
|
+
className
|
|
1837
|
+
}) {
|
|
1838
|
+
const userTimezone = getUserTimeZone();
|
|
1839
|
+
const displayTimezone = timezone || userTimezone;
|
|
1840
|
+
const timezoneDisplay = displayTimezone === userTimezone ? "Local" : displayTimezone;
|
|
1841
|
+
return /* @__PURE__ */ jsxs("form", { className: cn("grid grid-cols-[1fr_auto] gap-2", className), children: [
|
|
1842
|
+
/* @__PURE__ */ jsx(
|
|
1843
|
+
Calendar,
|
|
2026
1844
|
{
|
|
2027
|
-
|
|
2028
|
-
locale: locale ?? enAU,
|
|
2029
|
-
hideNavigation: true,
|
|
2030
|
-
...props,
|
|
1845
|
+
mode: "single",
|
|
2031
1846
|
selected,
|
|
2032
1847
|
onSelect,
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
months: "",
|
|
2039
|
-
// No wrapper - removed by CustomMonths
|
|
2040
|
-
month: "",
|
|
2041
|
-
// No wrapper - removed by CustomMonth
|
|
2042
|
-
month_caption: "",
|
|
2043
|
-
// Now handled by custom component (renders as <caption>)
|
|
2044
|
-
caption_label: "text-sm font-medium",
|
|
2045
|
-
nav: "relative flex items-center justify-center space-x-1",
|
|
2046
|
-
// v9: button_previous and button_next for navigation buttons
|
|
2047
|
-
button_previous: cn(
|
|
2048
|
-
"absolute left-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
|
|
2049
|
-
"border border-input hover:bg-acc-100",
|
|
2050
|
-
"inline-flex items-center justify-center rounded-md",
|
|
2051
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2"
|
|
2052
|
-
),
|
|
2053
|
-
button_next: cn(
|
|
2054
|
-
"absolute right-1 h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100",
|
|
2055
|
-
"border border-input hover:bg-acc-100",
|
|
2056
|
-
"inline-flex items-center justify-center rounded-md",
|
|
2057
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2"
|
|
2058
|
-
),
|
|
2059
|
-
// v9: table -> month_grid (now a proper <table>)
|
|
2060
|
-
month_grid: "",
|
|
2061
|
-
// Styles applied directly to table in CustomMonth
|
|
2062
|
-
// v9: head_row -> weekdays (now wrapped in <thead> by custom component)
|
|
2063
|
-
weekdays: "",
|
|
2064
|
-
// Styles applied to <tr> inside <thead>
|
|
2065
|
-
weekday: "text-sec-600 rounded-md w-9 font-normal text-[0.8rem]",
|
|
2066
|
-
// v9: row -> week (now a proper <tr>)
|
|
2067
|
-
week: "mt-2",
|
|
2068
|
-
// v9: cell -> day (now a proper <td> by custom component)
|
|
2069
|
-
day: "",
|
|
2070
|
-
// Styles moved to <td> in custom component
|
|
2071
|
-
// v9: day -> day_button (the button inside the cell)
|
|
2072
|
-
day_button: cn(
|
|
2073
|
-
"h-9 w-9 p-0 font-normal aria-selected:opacity-100",
|
|
2074
|
-
"hover:bg-acc-100 hover:text-main-600",
|
|
2075
|
-
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-main-600 focus-visible:ring-offset-2",
|
|
2076
|
-
"inline-flex items-center justify-center rounded-md"
|
|
2077
|
-
),
|
|
2078
|
-
// v9: day_range_end -> range_end
|
|
2079
|
-
range_end: "range-end",
|
|
2080
|
-
// v9: day_selected -> selected
|
|
2081
|
-
selected: "bg-main-600 text-main-50 hover:bg-main-600 hover:text-main-50 focus:bg-main-600 focus:text-main-50",
|
|
2082
|
-
// v9: day_today -> today
|
|
2083
|
-
today: "bg-sec-100 text-main-600 font-semibold",
|
|
2084
|
-
// v9: day_outside -> outside
|
|
2085
|
-
outside: "outside text-sec-400 opacity-50 aria-selected:bg-acc-50/50 aria-selected:text-sec-400 aria-selected:opacity-30",
|
|
2086
|
-
// v9: day_disabled -> disabled
|
|
2087
|
-
disabled: "text-sec-400 opacity-50 cursor-not-allowed",
|
|
2088
|
-
// v9: day_range_middle -> range_middle
|
|
2089
|
-
range_middle: "aria-selected:bg-acc-100 aria-selected:text-main-600",
|
|
2090
|
-
// v9: day_hidden -> hidden
|
|
2091
|
-
hidden: "invisible",
|
|
2092
|
-
...classNames
|
|
2093
|
-
},
|
|
2094
|
-
components: defaultComponents
|
|
1848
|
+
initialFocus: true,
|
|
1849
|
+
captionLayout: "dropdown",
|
|
1850
|
+
startMonth: new Date(1900, 0),
|
|
1851
|
+
endMonth: new Date(2100, 11),
|
|
1852
|
+
className: "p-0 col-span-full"
|
|
2095
1853
|
}
|
|
2096
|
-
)
|
|
2097
|
-
|
|
2098
|
-
)
|
|
2099
|
-
|
|
1854
|
+
),
|
|
1855
|
+
/* @__PURE__ */ jsxs("label", { htmlFor: "timezone", children: [
|
|
1856
|
+
/* @__PURE__ */ jsx(Clock, { className: "size-4 inline-block mr-2", "aria-hidden": "true" }),
|
|
1857
|
+
"Timezone: ",
|
|
1858
|
+
/* @__PURE__ */ jsx("span", { "aria-label": `Timezone ${timezoneDisplay}`, children: timezoneDisplay })
|
|
1859
|
+
] }),
|
|
1860
|
+
onDone && /* @__PURE__ */ jsx(Button, { onClick: onDone, size: "sm", className: "ml-auto h-8", children: "Done" })
|
|
1861
|
+
] });
|
|
1862
|
+
}
|
|
2100
1863
|
var ToastProvider = ToastPrimitives.Provider;
|
|
2101
|
-
var ToastViewport =
|
|
1864
|
+
var ToastViewport = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2102
1865
|
ToastPrimitives.Viewport,
|
|
2103
1866
|
{
|
|
2104
1867
|
ref,
|
|
@@ -2111,7 +1874,7 @@ var ToastViewport = React6.forwardRef(({ className, ...props }, ref) => /* @__PU
|
|
|
2111
1874
|
}
|
|
2112
1875
|
));
|
|
2113
1876
|
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
|
|
2114
|
-
var Toast =
|
|
1877
|
+
var Toast = React.forwardRef(({ className, ...props }, ref) => {
|
|
2115
1878
|
return /* @__PURE__ */ jsx(
|
|
2116
1879
|
ToastPrimitives.Root,
|
|
2117
1880
|
{
|
|
@@ -2126,7 +1889,7 @@ var Toast = React6.forwardRef(({ className, ...props }, ref) => {
|
|
|
2126
1889
|
);
|
|
2127
1890
|
});
|
|
2128
1891
|
Toast.displayName = ToastPrimitives.Root.displayName;
|
|
2129
|
-
var ToastAction =
|
|
1892
|
+
var ToastAction = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2130
1893
|
ToastPrimitives.Action,
|
|
2131
1894
|
{
|
|
2132
1895
|
ref,
|
|
@@ -2139,7 +1902,7 @@ var ToastAction = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE
|
|
|
2139
1902
|
}
|
|
2140
1903
|
));
|
|
2141
1904
|
ToastAction.displayName = ToastPrimitives.Action.displayName;
|
|
2142
|
-
var ToastClose =
|
|
1905
|
+
var ToastClose = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2143
1906
|
ToastPrimitives.Close,
|
|
2144
1907
|
{
|
|
2145
1908
|
ref,
|
|
@@ -2154,7 +1917,7 @@ var ToastClose = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
2154
1917
|
}
|
|
2155
1918
|
));
|
|
2156
1919
|
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
|
2157
|
-
var ToastTitle =
|
|
1920
|
+
var ToastTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2158
1921
|
ToastPrimitives.Title,
|
|
2159
1922
|
{
|
|
2160
1923
|
ref,
|
|
@@ -2164,7 +1927,7 @@ var ToastTitle = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE_
|
|
|
2164
1927
|
}
|
|
2165
1928
|
));
|
|
2166
1929
|
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
|
2167
|
-
var ToastDescription =
|
|
1930
|
+
var ToastDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2168
1931
|
ToastPrimitives.Description,
|
|
2169
1932
|
{
|
|
2170
1933
|
ref,
|
|
@@ -2198,6 +1961,7 @@ function Form({
|
|
|
2198
1961
|
children,
|
|
2199
1962
|
className
|
|
2200
1963
|
}) {
|
|
1964
|
+
const logger2 = createLogger("Form");
|
|
2201
1965
|
const location = useLocation();
|
|
2202
1966
|
const auth = useUnifiedAuth();
|
|
2203
1967
|
const userId = auth.user?.id || null;
|
|
@@ -2303,7 +2067,7 @@ function Form({
|
|
|
2303
2067
|
valuesToRestore[fieldName] = persistedValues[numericKey];
|
|
2304
2068
|
}
|
|
2305
2069
|
}
|
|
2306
|
-
|
|
2070
|
+
logger2.debug("[Form Persistence] Mapped numeric keys to field names:", {
|
|
2307
2071
|
numericKeys: persistedKeys,
|
|
2308
2072
|
fieldNames,
|
|
2309
2073
|
mappedValues: valuesToRestore
|
|
@@ -2321,7 +2085,7 @@ function Form({
|
|
|
2321
2085
|
const type = fieldTypes?.[name];
|
|
2322
2086
|
return isSensitiveField(name, type);
|
|
2323
2087
|
});
|
|
2324
|
-
|
|
2088
|
+
logger2.debug("[Form Persistence] \u2705 Restoring persisted values:", {
|
|
2325
2089
|
persistenceKey,
|
|
2326
2090
|
persistedValuesKeys: persistedKeys,
|
|
2327
2091
|
persistedValuesString: JSON.stringify(persistedValues),
|
|
@@ -2344,7 +2108,7 @@ function Form({
|
|
|
2344
2108
|
}
|
|
2345
2109
|
}
|
|
2346
2110
|
if (hasValuesToSet) {
|
|
2347
|
-
|
|
2111
|
+
logger2.debug("[Form Persistence] \u{1F504} Setting form values via reset():", {
|
|
2348
2112
|
persistenceKey,
|
|
2349
2113
|
valuesToSetKeys: Object.keys(valuesToSet),
|
|
2350
2114
|
valuesToSet,
|
|
@@ -2354,12 +2118,12 @@ function Form({
|
|
|
2354
2118
|
...methods.getValues(),
|
|
2355
2119
|
...valuesToSet
|
|
2356
2120
|
});
|
|
2357
|
-
|
|
2121
|
+
logger2.debug("[Form Persistence] \u2705 Form values set successfully", {
|
|
2358
2122
|
persistenceKey,
|
|
2359
2123
|
currentValues: methods.getValues()
|
|
2360
2124
|
});
|
|
2361
2125
|
} else {
|
|
2362
|
-
|
|
2126
|
+
logger2.debug("[Form Persistence] \u23ED\uFE0F No values to set (all values already match)", {
|
|
2363
2127
|
persistenceKey
|
|
2364
2128
|
});
|
|
2365
2129
|
}
|
|
@@ -2404,7 +2168,7 @@ function Form({
|
|
|
2404
2168
|
const type = fieldTypes?.[name];
|
|
2405
2169
|
return isSensitiveField(name, type);
|
|
2406
2170
|
});
|
|
2407
|
-
|
|
2171
|
+
logger2.debug("[Form Persistence] \u{1F4BE} Persisting form values:", {
|
|
2408
2172
|
persistenceKey,
|
|
2409
2173
|
filteredValuesKeys: Object.keys(filteredValues),
|
|
2410
2174
|
originalValuesKeys: Object.keys(watchedValues),
|
|
@@ -2415,15 +2179,19 @@ function Form({
|
|
|
2415
2179
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2416
2180
|
});
|
|
2417
2181
|
setPersistedValues(filteredValues);
|
|
2418
|
-
if (persistenceKey) {
|
|
2182
|
+
if (persistenceKey && typeof sessionStorage !== "undefined") {
|
|
2419
2183
|
setTimeout(() => {
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2184
|
+
try {
|
|
2185
|
+
const storageKey = `pace-core:draft:${persistenceKey}`;
|
|
2186
|
+
const stored = sessionStorage.getItem(storageKey);
|
|
2187
|
+
logger2.debug("[Form Persistence] \u{1F4E6} SessionStorage AFTER setPersistedValues:", {
|
|
2188
|
+
persistenceKey,
|
|
2189
|
+
storageKey,
|
|
2190
|
+
stored: stored ? JSON.parse(stored) : null
|
|
2191
|
+
});
|
|
2192
|
+
} catch (error) {
|
|
2193
|
+
logger2.debug("[Form Persistence] Could not access sessionStorage after setPersistedValues", { error });
|
|
2194
|
+
}
|
|
2427
2195
|
}, 100);
|
|
2428
2196
|
}
|
|
2429
2197
|
persistTimeoutRef.current = null;
|
|
@@ -2437,34 +2205,40 @@ function Form({
|
|
|
2437
2205
|
}, [watchedValues, persistenceKey]);
|
|
2438
2206
|
const handleSubmit = methods.handleSubmit(
|
|
2439
2207
|
async (data) => {
|
|
2440
|
-
|
|
2208
|
+
logger2.debug("[Form Lifecycle] \u{1F4E4} Form submit started", {
|
|
2441
2209
|
persistenceKey,
|
|
2442
2210
|
dataKeys: Object.keys(data),
|
|
2443
2211
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2444
2212
|
});
|
|
2445
2213
|
await onSubmit(data);
|
|
2446
|
-
|
|
2214
|
+
logger2.debug("[Form Lifecycle] \u2705 Form submit successful", {
|
|
2447
2215
|
persistenceKey,
|
|
2448
2216
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
2449
2217
|
});
|
|
2450
2218
|
if (persistenceKey && clearDraft) {
|
|
2451
|
-
|
|
2219
|
+
logger2.debug("[Form Persistence] \u{1F5D1}\uFE0F Clearing draft after successful submit", {
|
|
2452
2220
|
persistenceKey
|
|
2453
2221
|
});
|
|
2454
2222
|
clearDraft();
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
|
|
2223
|
+
if (typeof sessionStorage !== "undefined") {
|
|
2224
|
+
setTimeout(() => {
|
|
2225
|
+
try {
|
|
2226
|
+
const storageKey = `pace-core:draft:${persistenceKey}`;
|
|
2227
|
+
const stored = sessionStorage.getItem(storageKey);
|
|
2228
|
+
logger2.debug("[Form Persistence] \u{1F4E6} SessionStorage AFTER clearDraft (submit):", {
|
|
2229
|
+
persistenceKey,
|
|
2230
|
+
storageKey,
|
|
2231
|
+
stored: stored ? JSON.parse(stored) : null
|
|
2232
|
+
});
|
|
2233
|
+
} catch (error) {
|
|
2234
|
+
logger2.debug("[Form Persistence] Could not access sessionStorage after clearDraft", { error });
|
|
2235
|
+
}
|
|
2236
|
+
}, 100);
|
|
2237
|
+
}
|
|
2464
2238
|
}
|
|
2465
2239
|
},
|
|
2466
2240
|
(errors) => {
|
|
2467
|
-
|
|
2241
|
+
logger2.debug("[Form Lifecycle] \u274C Form submit failed with errors", {
|
|
2468
2242
|
persistenceKey,
|
|
2469
2243
|
errors,
|
|
2470
2244
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
@@ -2528,7 +2302,7 @@ function FormField({
|
|
|
2528
2302
|
)
|
|
2529
2303
|
] });
|
|
2530
2304
|
}
|
|
2531
|
-
var LoginForm =
|
|
2305
|
+
var LoginForm = React__default.memo(({
|
|
2532
2306
|
onSignIn,
|
|
2533
2307
|
onSuccess,
|
|
2534
2308
|
onError,
|
|
@@ -2629,6 +2403,363 @@ var LoginForm = React6__default.memo(({
|
|
|
2629
2403
|
] })
|
|
2630
2404
|
] }) });
|
|
2631
2405
|
});
|
|
2406
|
+
function useAccessibleApps(currentAppName) {
|
|
2407
|
+
const supabase = useSecureSupabase();
|
|
2408
|
+
const authContext = useUnifiedAuth();
|
|
2409
|
+
const user = authContext?.user ?? null;
|
|
2410
|
+
const { superAdminContext } = useOrganisationSecurity();
|
|
2411
|
+
const isSuperAdmin2 = superAdminContext.isSuperAdmin;
|
|
2412
|
+
const [apps, setApps] = useState([]);
|
|
2413
|
+
const [loading, setLoading] = useState(true);
|
|
2414
|
+
const [error, setError] = useState(null);
|
|
2415
|
+
const fetchApps = useMemo(
|
|
2416
|
+
() => async () => {
|
|
2417
|
+
if (!supabase || !user) {
|
|
2418
|
+
setApps([]);
|
|
2419
|
+
setLoading(false);
|
|
2420
|
+
return;
|
|
2421
|
+
}
|
|
2422
|
+
setLoading(true);
|
|
2423
|
+
setError(null);
|
|
2424
|
+
try {
|
|
2425
|
+
let data = [];
|
|
2426
|
+
let actualIsSuperAdmin = isSuperAdmin2;
|
|
2427
|
+
if (user && supabase) {
|
|
2428
|
+
try {
|
|
2429
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2430
|
+
const { data: superAdminData, error: superAdminError } = await supabase.from("rbac_global_roles").select("role").eq("user_id", user.id).eq("role", "super_admin").lte("valid_from", now).or(`valid_to.is.null,valid_to.gte.${now}`).limit(1);
|
|
2431
|
+
if (!superAdminError && superAdminData && superAdminData.length > 0) {
|
|
2432
|
+
actualIsSuperAdmin = true;
|
|
2433
|
+
} else {
|
|
2434
|
+
actualIsSuperAdmin = false;
|
|
2435
|
+
}
|
|
2436
|
+
} catch (checkError) {
|
|
2437
|
+
logger.warn("useAccessibleApps", "Error checking super admin status directly:", checkError);
|
|
2438
|
+
actualIsSuperAdmin = isSuperAdmin2;
|
|
2439
|
+
}
|
|
2440
|
+
}
|
|
2441
|
+
if (actualIsSuperAdmin) {
|
|
2442
|
+
const { data: allApps, error: queryError } = await supabase.from("rbac_apps").select("id, name, display_name, is_active").eq("is_active", true).order("display_name");
|
|
2443
|
+
if (queryError) {
|
|
2444
|
+
logger.error("useAccessibleApps", "Failed to fetch all apps for super admin:", queryError);
|
|
2445
|
+
throw new Error(`Failed to fetch all apps: ${queryError.message}`);
|
|
2446
|
+
}
|
|
2447
|
+
data = allApps || [];
|
|
2448
|
+
} else {
|
|
2449
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2450
|
+
const { data: roleData, error: queryError } = await supabase.from("rbac_event_app_roles").select(
|
|
2451
|
+
`
|
|
2452
|
+
app_id,
|
|
2453
|
+
rbac_apps!inner (
|
|
2454
|
+
id,
|
|
2455
|
+
name,
|
|
2456
|
+
display_name,
|
|
2457
|
+
is_active
|
|
2458
|
+
)
|
|
2459
|
+
`
|
|
2460
|
+
).eq("user_id", user.id).eq("status", "active").or(`valid_to.is.null,valid_to.gt.${now}`);
|
|
2461
|
+
if (queryError) {
|
|
2462
|
+
throw new Error(`Failed to fetch accessible apps: ${queryError.message}`);
|
|
2463
|
+
}
|
|
2464
|
+
if (!roleData) {
|
|
2465
|
+
setApps([]);
|
|
2466
|
+
setLoading(false);
|
|
2467
|
+
return;
|
|
2468
|
+
}
|
|
2469
|
+
const appMap2 = /* @__PURE__ */ new Map();
|
|
2470
|
+
for (const row of roleData) {
|
|
2471
|
+
const appData = row.rbac_apps;
|
|
2472
|
+
if (!appData || !appData.is_active) {
|
|
2473
|
+
continue;
|
|
2474
|
+
}
|
|
2475
|
+
if (!appMap2.has(appData.id)) {
|
|
2476
|
+
appMap2.set(appData.id, {
|
|
2477
|
+
id: appData.id,
|
|
2478
|
+
name: appData.name,
|
|
2479
|
+
display_name: appData.display_name,
|
|
2480
|
+
is_active: appData.is_active
|
|
2481
|
+
});
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
data = Array.from(appMap2.values());
|
|
2485
|
+
}
|
|
2486
|
+
const appMap = /* @__PURE__ */ new Map();
|
|
2487
|
+
for (const appData of data) {
|
|
2488
|
+
if (!appData.is_active) {
|
|
2489
|
+
continue;
|
|
2490
|
+
}
|
|
2491
|
+
if (currentAppName && appData.name.toUpperCase() === currentAppName.toUpperCase()) {
|
|
2492
|
+
continue;
|
|
2493
|
+
}
|
|
2494
|
+
if (!appMap.has(appData.id)) {
|
|
2495
|
+
appMap.set(appData.id, {
|
|
2496
|
+
id: appData.id,
|
|
2497
|
+
name: appData.name,
|
|
2498
|
+
displayName: appData.display_name
|
|
2499
|
+
});
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
const appsArray = Array.from(appMap.values()).sort(
|
|
2503
|
+
(a, b) => a.displayName.localeCompare(b.displayName)
|
|
2504
|
+
);
|
|
2505
|
+
setApps(appsArray);
|
|
2506
|
+
} catch (err) {
|
|
2507
|
+
const error2 = err instanceof Error ? err : new Error("Unknown error fetching apps");
|
|
2508
|
+
setError(error2);
|
|
2509
|
+
setApps([]);
|
|
2510
|
+
} finally {
|
|
2511
|
+
setLoading(false);
|
|
2512
|
+
}
|
|
2513
|
+
},
|
|
2514
|
+
[supabase, user, currentAppName, isSuperAdmin2]
|
|
2515
|
+
);
|
|
2516
|
+
useEffect(() => {
|
|
2517
|
+
void fetchApps();
|
|
2518
|
+
}, [fetchApps]);
|
|
2519
|
+
return {
|
|
2520
|
+
apps,
|
|
2521
|
+
loading,
|
|
2522
|
+
error,
|
|
2523
|
+
refetch: fetchApps
|
|
2524
|
+
};
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
// src/utils/app/appPortMap.ts
|
|
2528
|
+
var DEFAULT_APP_PORT_MAP = {
|
|
2529
|
+
"CORE": 8080,
|
|
2530
|
+
"ADMIN": 8081,
|
|
2531
|
+
"BASE": 8082,
|
|
2532
|
+
"CAKE": 8083,
|
|
2533
|
+
"GEAR": 8084,
|
|
2534
|
+
"MINT": 8085,
|
|
2535
|
+
"PORTAL": 8086,
|
|
2536
|
+
"PUMP": 8087,
|
|
2537
|
+
"TRAC": 8088
|
|
2538
|
+
};
|
|
2539
|
+
function getAppPort(appName) {
|
|
2540
|
+
const upperAppName = appName.toUpperCase();
|
|
2541
|
+
return DEFAULT_APP_PORT_MAP[upperAppName];
|
|
2542
|
+
}
|
|
2543
|
+
function getAllAppPorts() {
|
|
2544
|
+
return { ...DEFAULT_APP_PORT_MAP };
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
// src/utils/app/buildAppUrl.ts
|
|
2548
|
+
function buildAppUrl(options) {
|
|
2549
|
+
const { appName, path = "/", port } = options;
|
|
2550
|
+
const isDevelopment = isDevEnvironment();
|
|
2551
|
+
if (isDevelopment) {
|
|
2552
|
+
const appPort = port || getAppPort(appName);
|
|
2553
|
+
if (!appPort) {
|
|
2554
|
+
const currentPort = window.location.port || "3000";
|
|
2555
|
+
return `http://localhost:${currentPort}${path}`;
|
|
2556
|
+
}
|
|
2557
|
+
return `http://localhost:${appPort}${path}`;
|
|
2558
|
+
} else {
|
|
2559
|
+
const baseDomain = getBaseDomain();
|
|
2560
|
+
const appSubdomain = appName.toLowerCase();
|
|
2561
|
+
const protocol = window.location.protocol;
|
|
2562
|
+
const url = `${protocol}//${appSubdomain}.${baseDomain}${path}`;
|
|
2563
|
+
return url;
|
|
2564
|
+
}
|
|
2565
|
+
}
|
|
2566
|
+
function isDevEnvironment() {
|
|
2567
|
+
const hostname = window.location.hostname;
|
|
2568
|
+
return hostname === "localhost" || hostname === "127.0.0.1" || hostname === "[::1]";
|
|
2569
|
+
}
|
|
2570
|
+
function getBaseDomain() {
|
|
2571
|
+
const hostname = window.location.hostname;
|
|
2572
|
+
const parts = hostname.split(".");
|
|
2573
|
+
if (parts.length > 2) {
|
|
2574
|
+
return parts.slice(1).join(".");
|
|
2575
|
+
}
|
|
2576
|
+
return hostname;
|
|
2577
|
+
}
|
|
2578
|
+
var APP_DISPLAY_ORDER = [
|
|
2579
|
+
"ADMIN",
|
|
2580
|
+
"PACE",
|
|
2581
|
+
"TEAM",
|
|
2582
|
+
"TRIP",
|
|
2583
|
+
"BASE",
|
|
2584
|
+
"GEAR",
|
|
2585
|
+
"MINT",
|
|
2586
|
+
"MEDI",
|
|
2587
|
+
"TRAC",
|
|
2588
|
+
"PUMP",
|
|
2589
|
+
"CAKE",
|
|
2590
|
+
"CORE"
|
|
2591
|
+
];
|
|
2592
|
+
var getCacheKey = (userId) => {
|
|
2593
|
+
return `pace-core:appswitcher:apps:${userId}`;
|
|
2594
|
+
};
|
|
2595
|
+
var loadAppsFromCache = (userId) => {
|
|
2596
|
+
if (typeof window === "undefined" || !window.sessionStorage) {
|
|
2597
|
+
return null;
|
|
2598
|
+
}
|
|
2599
|
+
try {
|
|
2600
|
+
const cacheKey = getCacheKey(userId);
|
|
2601
|
+
const cached = window.sessionStorage.getItem(cacheKey);
|
|
2602
|
+
if (!cached) {
|
|
2603
|
+
return null;
|
|
2604
|
+
}
|
|
2605
|
+
const parsed = JSON.parse(cached);
|
|
2606
|
+
return Array.isArray(parsed) ? parsed : null;
|
|
2607
|
+
} catch {
|
|
2608
|
+
return null;
|
|
2609
|
+
}
|
|
2610
|
+
};
|
|
2611
|
+
var saveAppsToCache = (userId, apps) => {
|
|
2612
|
+
if (typeof window === "undefined" || !window.sessionStorage) {
|
|
2613
|
+
return;
|
|
2614
|
+
}
|
|
2615
|
+
try {
|
|
2616
|
+
const cacheKey = getCacheKey(userId);
|
|
2617
|
+
window.sessionStorage.setItem(cacheKey, JSON.stringify(apps));
|
|
2618
|
+
} catch {
|
|
2619
|
+
}
|
|
2620
|
+
};
|
|
2621
|
+
function enrichAppsWithCacheData(apps) {
|
|
2622
|
+
const orderMap = new Map(APP_DISPLAY_ORDER.map((name, index) => [name.toUpperCase(), index]));
|
|
2623
|
+
return apps.map((app) => ({
|
|
2624
|
+
id: app.id,
|
|
2625
|
+
name: app.name,
|
|
2626
|
+
displayName: app.displayName,
|
|
2627
|
+
logoUrl: getAppIcon(app.name),
|
|
2628
|
+
sortId: orderMap.get(app.name.toUpperCase()) ?? -1
|
|
2629
|
+
// -1 if not in APP_DISPLAY_ORDER
|
|
2630
|
+
}));
|
|
2631
|
+
}
|
|
2632
|
+
function AppSwitcher({
|
|
2633
|
+
currentAppName,
|
|
2634
|
+
trigger,
|
|
2635
|
+
className,
|
|
2636
|
+
showSwitcher = true
|
|
2637
|
+
}) {
|
|
2638
|
+
const { apps, loading, error } = useAccessibleApps(currentAppName);
|
|
2639
|
+
const { session, user } = useUnifiedAuth();
|
|
2640
|
+
const [cachedApps, setCachedApps] = React__default.useState(null);
|
|
2641
|
+
React__default.useEffect(() => {
|
|
2642
|
+
if (!user?.id) {
|
|
2643
|
+
setCachedApps(null);
|
|
2644
|
+
return;
|
|
2645
|
+
}
|
|
2646
|
+
const cached = loadAppsFromCache(user.id);
|
|
2647
|
+
if (cached) {
|
|
2648
|
+
setCachedApps(cached);
|
|
2649
|
+
}
|
|
2650
|
+
}, [user?.id]);
|
|
2651
|
+
React__default.useEffect(() => {
|
|
2652
|
+
if (!user?.id || loading || error || apps.length === 0) {
|
|
2653
|
+
return;
|
|
2654
|
+
}
|
|
2655
|
+
const enriched = enrichAppsWithCacheData(apps);
|
|
2656
|
+
saveAppsToCache(user.id, enriched);
|
|
2657
|
+
setCachedApps(enriched);
|
|
2658
|
+
}, [apps, loading, error, user?.id]);
|
|
2659
|
+
React__default.useEffect(() => {
|
|
2660
|
+
return () => {
|
|
2661
|
+
if (user?.id) ;
|
|
2662
|
+
};
|
|
2663
|
+
}, [user?.id]);
|
|
2664
|
+
const processedApps = (() => {
|
|
2665
|
+
if (!cachedApps) return [];
|
|
2666
|
+
const filtered = cachedApps.filter(
|
|
2667
|
+
(app) => app.name.toUpperCase() !== currentAppName.toUpperCase()
|
|
2668
|
+
);
|
|
2669
|
+
return filtered.sort((a, b) => {
|
|
2670
|
+
if (a.sortId >= 0 && b.sortId >= 0) return a.sortId - b.sortId;
|
|
2671
|
+
if (a.sortId >= 0) return -1;
|
|
2672
|
+
if (b.sortId >= 0) return 1;
|
|
2673
|
+
return a.displayName.localeCompare(b.displayName);
|
|
2674
|
+
});
|
|
2675
|
+
})();
|
|
2676
|
+
if (!showSwitcher || !loading && processedApps.length === 0) {
|
|
2677
|
+
return trigger ? /* @__PURE__ */ jsx(Fragment, { children: trigger }) : null;
|
|
2678
|
+
}
|
|
2679
|
+
const handleAppSelect = (appName) => {
|
|
2680
|
+
let url = buildAppUrl({ appName, path: "/" });
|
|
2681
|
+
if (session?.access_token && session?.refresh_token) {
|
|
2682
|
+
const urlObj = new URL(url);
|
|
2683
|
+
try {
|
|
2684
|
+
const sessionData = JSON.stringify({
|
|
2685
|
+
access_token: session.access_token,
|
|
2686
|
+
refresh_token: session.refresh_token,
|
|
2687
|
+
expires_at: session.expires_at,
|
|
2688
|
+
expires_in: session.expires_in,
|
|
2689
|
+
token_type: session.token_type,
|
|
2690
|
+
user: {
|
|
2691
|
+
id: session.user.id,
|
|
2692
|
+
email: session.user.email
|
|
2693
|
+
// Include minimal user data needed
|
|
2694
|
+
}
|
|
2695
|
+
});
|
|
2696
|
+
const encodedSession = btoa(sessionData);
|
|
2697
|
+
urlObj.searchParams.set("session", encodedSession);
|
|
2698
|
+
url = urlObj.toString();
|
|
2699
|
+
} catch (_error) {
|
|
2700
|
+
urlObj.searchParams.set("session_token", session.access_token);
|
|
2701
|
+
url = urlObj.toString();
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
window.open(url, "_blank");
|
|
2705
|
+
};
|
|
2706
|
+
if (error) {
|
|
2707
|
+
return trigger ? /* @__PURE__ */ jsx(Fragment, { children: trigger }) : null;
|
|
2708
|
+
}
|
|
2709
|
+
const hasApps = processedApps.length > 0;
|
|
2710
|
+
const isDisabled = loading || !hasApps;
|
|
2711
|
+
return /* @__PURE__ */ jsxs(
|
|
2712
|
+
Select,
|
|
2713
|
+
{
|
|
2714
|
+
onValueChange: handleAppSelect,
|
|
2715
|
+
disabled: isDisabled,
|
|
2716
|
+
className: cn(className),
|
|
2717
|
+
children: [
|
|
2718
|
+
trigger ? /* @__PURE__ */ jsx(
|
|
2719
|
+
SelectTrigger,
|
|
2720
|
+
{
|
|
2721
|
+
asChild: true,
|
|
2722
|
+
disabled: isDisabled,
|
|
2723
|
+
variant: "ghost",
|
|
2724
|
+
showChevron: false,
|
|
2725
|
+
children: trigger
|
|
2726
|
+
}
|
|
2727
|
+
) : /* @__PURE__ */ jsxs(
|
|
2728
|
+
SelectTrigger,
|
|
2729
|
+
{
|
|
2730
|
+
disabled: isDisabled,
|
|
2731
|
+
variant: "ghost",
|
|
2732
|
+
showChevron: false,
|
|
2733
|
+
className: "p-0 bg-main-500 overflow-hidden hover:bg-none",
|
|
2734
|
+
children: [
|
|
2735
|
+
/* @__PURE__ */ jsx(
|
|
2736
|
+
"img",
|
|
2737
|
+
{
|
|
2738
|
+
src: getAppIcon("pace"),
|
|
2739
|
+
alt: "PACE",
|
|
2740
|
+
className: "absolute inset-0 size-full object-contain hover:hue-rotate-180 hover:invert transition-all"
|
|
2741
|
+
}
|
|
2742
|
+
),
|
|
2743
|
+
/* @__PURE__ */ jsx(SelectValue, { placeholder: "PACE", className: "opacity-0" })
|
|
2744
|
+
]
|
|
2745
|
+
}
|
|
2746
|
+
),
|
|
2747
|
+
hasApps && /* @__PURE__ */ jsx(SelectContent, { className: "grid grid-cols-[2rem_auto_auto] gap-1 auto-rows-min pt-2", children: processedApps.map((app) => /* @__PURE__ */ jsxs(SelectItem, { value: app.name, className: "col-span-3 grid grid-cols-subgrid items-center py-0", children: [
|
|
2748
|
+
/* @__PURE__ */ jsx(
|
|
2749
|
+
"img",
|
|
2750
|
+
{
|
|
2751
|
+
src: app.logoUrl,
|
|
2752
|
+
alt: `${app.displayName} logo`,
|
|
2753
|
+
className: "size-5 col-start-1"
|
|
2754
|
+
}
|
|
2755
|
+
),
|
|
2756
|
+
/* @__PURE__ */ jsx("h6", { className: " uppercase col-start-2 my-0", children: app.name }),
|
|
2757
|
+
/* @__PURE__ */ jsx("small", { className: "col-start-3 whitespace-nowrap", children: app.displayName })
|
|
2758
|
+
] }, app.id)) })
|
|
2759
|
+
]
|
|
2760
|
+
}
|
|
2761
|
+
);
|
|
2762
|
+
}
|
|
2632
2763
|
function ContextSelector({
|
|
2633
2764
|
placeholder = "Select organisation or event",
|
|
2634
2765
|
className,
|
|
@@ -2666,7 +2797,7 @@ function ContextSelector({
|
|
|
2666
2797
|
return `org:${selectedOrganisation.id}`;
|
|
2667
2798
|
}
|
|
2668
2799
|
return "";
|
|
2669
|
-
}, [showOrganisations, showEvents, selectedOrganisation
|
|
2800
|
+
}, [showOrganisations, showEvents, selectedOrganisation, selectedEvent]);
|
|
2670
2801
|
const displayValue = useMemo(() => {
|
|
2671
2802
|
if (showEvents && selectedEvent) {
|
|
2672
2803
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -2727,7 +2858,7 @@ function ContextSelector({
|
|
|
2727
2858
|
};
|
|
2728
2859
|
if (isLoading && !hasItems) {
|
|
2729
2860
|
const loadingText = compact ? "Loading..." : showOrganisations && showEvents ? "Loading organisations and events..." : showOrganisations ? "Loading organisations..." : "Loading events...";
|
|
2730
|
-
return /* @__PURE__ */ jsxs("
|
|
2861
|
+
return /* @__PURE__ */ jsxs("div", { className, children: [
|
|
2731
2862
|
/* @__PURE__ */ jsx(LoadingSpinner, { size: "sm" }),
|
|
2732
2863
|
/* @__PURE__ */ jsx("br", {}),
|
|
2733
2864
|
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: loadingText })
|
|
@@ -2916,7 +3047,7 @@ function PasswordChangeForm({ onSubmit, onSuccess, className }) {
|
|
|
2916
3047
|
)
|
|
2917
3048
|
] });
|
|
2918
3049
|
}
|
|
2919
|
-
var UserMenu =
|
|
3050
|
+
var UserMenu = React__default.memo(function UserMenu2({
|
|
2920
3051
|
user,
|
|
2921
3052
|
onSignOut,
|
|
2922
3053
|
onChangePassword,
|
|
@@ -2961,11 +3092,11 @@ var UserMenu = React6__default.memo(function UserMenu2({
|
|
|
2961
3092
|
/* @__PURE__ */ jsx(ChevronDown, { className: "size-4" })
|
|
2962
3093
|
] }) }),
|
|
2963
3094
|
/* @__PURE__ */ jsxs(SelectContent, { children: [
|
|
2964
|
-
/* @__PURE__ */
|
|
3095
|
+
/* @__PURE__ */ jsxs(SelectLabel, { className: "font-normal pt-2", children: [
|
|
2965
3096
|
userInfo.displayName,
|
|
2966
3097
|
/* @__PURE__ */ jsx("br", {}),
|
|
2967
3098
|
/* @__PURE__ */ jsx("small", { children: userInfo.email })
|
|
2968
|
-
] })
|
|
3099
|
+
] }),
|
|
2969
3100
|
/* @__PURE__ */ jsx(SelectSeparator, {}),
|
|
2970
3101
|
/* @__PURE__ */ jsxs(
|
|
2971
3102
|
SelectItem,
|
|
@@ -2998,7 +3129,7 @@ var UserMenu = React6__default.memo(function UserMenu2({
|
|
|
2998
3129
|
] }) })
|
|
2999
3130
|
] });
|
|
3000
3131
|
});
|
|
3001
|
-
var UserMenuLoading =
|
|
3132
|
+
var UserMenuLoading = React__default.memo(function UserMenuLoading2() {
|
|
3002
3133
|
return /* @__PURE__ */ jsxs(
|
|
3003
3134
|
Button,
|
|
3004
3135
|
{
|
|
@@ -3019,10 +3150,10 @@ UserMenu.Loading = UserMenuLoading;
|
|
|
3019
3150
|
function useNavigationFiltering({
|
|
3020
3151
|
items,
|
|
3021
3152
|
itemsPreFiltered = false,
|
|
3022
|
-
auditLog = true
|
|
3153
|
+
auditLog: _auditLog = true
|
|
3023
3154
|
}) {
|
|
3024
|
-
const [resolvedAppId, setResolvedAppId] =
|
|
3025
|
-
const previousFilteredItemsRef =
|
|
3155
|
+
const [resolvedAppId, setResolvedAppId] = React.useState(void 0);
|
|
3156
|
+
const previousFilteredItemsRef = React.useRef([]);
|
|
3026
3157
|
const authContext = useUnifiedAuth();
|
|
3027
3158
|
const rbacContext = useRBAC();
|
|
3028
3159
|
const eventLoadingRaw = authContext?.eventLoading;
|
|
@@ -3037,14 +3168,14 @@ function useNavigationFiltering({
|
|
|
3037
3168
|
selectedEventId: itemsPreFiltered ? null : selectedEvent?.event_id || null,
|
|
3038
3169
|
selectedEventOrganisationId: itemsPreFiltered ? null : selectedEvent?.organisation_id || null
|
|
3039
3170
|
});
|
|
3040
|
-
|
|
3171
|
+
React.useEffect(() => {
|
|
3041
3172
|
if (!scopeLoading && !resolvedScope?.appId && selectedOrganisation?.id && authContext?.appName && authContext?.user?.id && !resolvedAppId) {
|
|
3042
3173
|
if (!authContext.user || !authContext.appName) {
|
|
3043
3174
|
return;
|
|
3044
3175
|
}
|
|
3045
3176
|
const userId2 = authContext.user.id;
|
|
3046
3177
|
const appName = authContext.appName;
|
|
3047
|
-
import('./api-
|
|
3178
|
+
import('./api-F47QJ7FX.js').then(({ resolveAppContext }) => {
|
|
3048
3179
|
resolveAppContext({
|
|
3049
3180
|
userId: userId2,
|
|
3050
3181
|
appName
|
|
@@ -3062,10 +3193,10 @@ function useNavigationFiltering({
|
|
|
3062
3193
|
resolvedScope?.appId,
|
|
3063
3194
|
selectedOrganisation?.id,
|
|
3064
3195
|
authContext?.appName,
|
|
3065
|
-
authContext?.user
|
|
3196
|
+
authContext?.user,
|
|
3066
3197
|
resolvedAppId
|
|
3067
3198
|
]);
|
|
3068
|
-
const effectiveScope =
|
|
3199
|
+
const effectiveScope = React.useMemo(() => {
|
|
3069
3200
|
if (resolvedScope?.organisationId) {
|
|
3070
3201
|
return resolvedScope;
|
|
3071
3202
|
}
|
|
@@ -3079,8 +3210,7 @@ function useNavigationFiltering({
|
|
|
3079
3210
|
}
|
|
3080
3211
|
return null;
|
|
3081
3212
|
}, [resolvedScope, selectedOrganisation?.id, selectedEvent?.event_id, resolvedAppId]);
|
|
3082
|
-
const
|
|
3083
|
-
const stableScope = React6.useMemo(() => {
|
|
3213
|
+
const stableScope = React.useMemo(() => {
|
|
3084
3214
|
if (effectiveScope?.organisationId) {
|
|
3085
3215
|
return {
|
|
3086
3216
|
organisationId: effectiveScope.organisationId,
|
|
@@ -3093,7 +3223,7 @@ function useNavigationFiltering({
|
|
|
3093
3223
|
eventId: void 0,
|
|
3094
3224
|
appId: void 0
|
|
3095
3225
|
};
|
|
3096
|
-
}, [
|
|
3226
|
+
}, [effectiveScope]);
|
|
3097
3227
|
const userId = authContext?.user?.id || "";
|
|
3098
3228
|
const {
|
|
3099
3229
|
permissions: permissionMap,
|
|
@@ -3106,7 +3236,7 @@ function useNavigationFiltering({
|
|
|
3106
3236
|
itemsPreFiltered ? void 0 : stableScope.eventId,
|
|
3107
3237
|
itemsPreFiltered ? void 0 : stableScope.appId
|
|
3108
3238
|
);
|
|
3109
|
-
const filteredItems =
|
|
3239
|
+
const filteredItems = React.useMemo(() => {
|
|
3110
3240
|
if (itemsPreFiltered && items && items.length > 0) {
|
|
3111
3241
|
const visibleItems = (items || []).filter((item) => !item.meta?.hidden);
|
|
3112
3242
|
previousFilteredItemsRef.current = visibleItems;
|
|
@@ -3264,12 +3394,8 @@ function useNavigationFiltering({
|
|
|
3264
3394
|
scopeLoading,
|
|
3265
3395
|
scopeError,
|
|
3266
3396
|
permissionsLoading,
|
|
3267
|
-
resolvedScope,
|
|
3268
|
-
effectiveScope,
|
|
3269
|
-
auditLog,
|
|
3270
3397
|
eventLoadingRaw,
|
|
3271
3398
|
eventLoading,
|
|
3272
|
-
selectedEvent,
|
|
3273
3399
|
orgContextReady,
|
|
3274
3400
|
selectedOrganisation?.id,
|
|
3275
3401
|
permissionsError,
|
|
@@ -3285,7 +3411,7 @@ function useNavigationFiltering({
|
|
|
3285
3411
|
hasAnyPermission: hasAnyPermission || null
|
|
3286
3412
|
};
|
|
3287
3413
|
}
|
|
3288
|
-
var NavigationMenu =
|
|
3414
|
+
var NavigationMenu = React.forwardRef(({
|
|
3289
3415
|
items,
|
|
3290
3416
|
mode = "dropdown",
|
|
3291
3417
|
currentPath,
|
|
@@ -3293,7 +3419,7 @@ var NavigationMenu = React6.forwardRef(({
|
|
|
3293
3419
|
className,
|
|
3294
3420
|
disabled = false,
|
|
3295
3421
|
buttonText = "Menu",
|
|
3296
|
-
showIcons = true,
|
|
3422
|
+
showIcons: _showIcons = true,
|
|
3297
3423
|
navigationLabel = "Main navigation",
|
|
3298
3424
|
// NEW: Phase 2 - Enhanced Security Features
|
|
3299
3425
|
strictMode = true,
|
|
@@ -3303,8 +3429,8 @@ var NavigationMenu = React6.forwardRef(({
|
|
|
3303
3429
|
itemsPreFiltered = false,
|
|
3304
3430
|
...props
|
|
3305
3431
|
}, ref) => {
|
|
3306
|
-
const [expandedItems, setExpandedItems] =
|
|
3307
|
-
const buttonRef =
|
|
3432
|
+
const [expandedItems, setExpandedItems] = React.useState(/* @__PURE__ */ new Set());
|
|
3433
|
+
const buttonRef = React.useRef(null);
|
|
3308
3434
|
const { authContext, rbacContext, filteredItems, permissionMap, hasAnyPermission } = useNavigationFiltering({ items, itemsPreFiltered, auditLog });
|
|
3309
3435
|
const handleHierarchicalKeyDown = (event, item) => {
|
|
3310
3436
|
switch (event.key) {
|
|
@@ -3446,7 +3572,7 @@ var NavigationMenu = React6.forwardRef(({
|
|
|
3446
3572
|
id: `submenu-${item.id}`,
|
|
3447
3573
|
role: "menu",
|
|
3448
3574
|
"aria-label": `${item.label} submenu`,
|
|
3449
|
-
children: item.children.map((child) => /* @__PURE__ */ jsx(
|
|
3575
|
+
children: item.children.map((child) => /* @__PURE__ */ jsx(React.Fragment, { children: renderHierarchicalItem(child, level + 1) }, child.id))
|
|
3450
3576
|
}
|
|
3451
3577
|
)
|
|
3452
3578
|
] }) : /* @__PURE__ */ jsx(
|
|
@@ -3508,15 +3634,15 @@ var NavigationMenu = React6.forwardRef(({
|
|
|
3508
3634
|
className,
|
|
3509
3635
|
"aria-label": navigationLabel,
|
|
3510
3636
|
...props,
|
|
3511
|
-
children: /* @__PURE__ */ jsx("ul", { role: "menubar", children: filteredItems.map((item) => /* @__PURE__ */ jsx(
|
|
3637
|
+
children: /* @__PURE__ */ jsx("ul", { role: "menubar", children: filteredItems.map((item) => /* @__PURE__ */ jsx(React.Fragment, { children: renderHierarchicalItem(item, 0) }, item.id)) })
|
|
3512
3638
|
}
|
|
3513
3639
|
);
|
|
3514
3640
|
});
|
|
3515
3641
|
NavigationMenu.displayName = "NavigationMenu";
|
|
3642
|
+
var DEFAULT_LOGO_SRC = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIHZpZXdCb3g9IjAgMCAzMiAzMiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cmVjdCB3aWR0aD0iMzIiIGhlaWdodD0iMzIiIGZpbGw9IiNmZmYiLz48L3N2Zz4=";
|
|
3516
3643
|
function Header({
|
|
3517
3644
|
logoUrl,
|
|
3518
3645
|
logoAlt = "Logo",
|
|
3519
|
-
logo,
|
|
3520
3646
|
navItems = [],
|
|
3521
3647
|
user,
|
|
3522
3648
|
onSignOut,
|
|
@@ -3535,39 +3661,54 @@ function Header({
|
|
|
3535
3661
|
const shouldShowContextSelector = showContextSelector !== false;
|
|
3536
3662
|
const { switchOrganisation } = useOrganisations();
|
|
3537
3663
|
const { events, setSelectedEvent } = useEvents();
|
|
3664
|
+
const authContext = useUnifiedAuth();
|
|
3665
|
+
const isAuthenticated = authContext?.isAuthenticated ?? false;
|
|
3666
|
+
const appName = authContext?.appName;
|
|
3538
3667
|
return /* @__PURE__ */ jsx("header", { className: cn(
|
|
3539
3668
|
"w-full border-b border-main-200 h-16 shadow-sm bg-main-100 ",
|
|
3540
3669
|
className
|
|
3541
|
-
), role: "banner", children: /* @__PURE__ */ jsxs("nav", { className:
|
|
3542
|
-
|
|
3670
|
+
), role: "banner", children: /* @__PURE__ */ jsxs("nav", { className: cn(
|
|
3671
|
+
"px-4 w-[min(var(--app-width),100%)] mx-auto grid items-center gap-4 h-full",
|
|
3672
|
+
isAuthenticated && appName ? "grid-cols-[auto_auto_1fr_auto_auto]" : "grid-cols-[auto_1fr_auto_auto]"
|
|
3673
|
+
), children: [
|
|
3674
|
+
isAuthenticated && appName && /* @__PURE__ */ jsx(
|
|
3675
|
+
AppSwitcher,
|
|
3676
|
+
{
|
|
3677
|
+
currentAppName: appName,
|
|
3678
|
+
className: "w-9"
|
|
3679
|
+
}
|
|
3680
|
+
),
|
|
3681
|
+
logoUrl && (logoHref ? /* @__PURE__ */ jsx(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity flex items-center", children: /* @__PURE__ */ jsx(
|
|
3543
3682
|
"img",
|
|
3544
3683
|
{
|
|
3545
3684
|
src: logoUrl,
|
|
3546
3685
|
alt: logoAlt || "Logo",
|
|
3547
|
-
className: "h-
|
|
3686
|
+
className: "h-9 w-auto shadow-md"
|
|
3548
3687
|
}
|
|
3549
3688
|
) }) : /* @__PURE__ */ jsx(
|
|
3550
3689
|
"img",
|
|
3551
3690
|
{
|
|
3552
3691
|
src: logoUrl,
|
|
3553
3692
|
alt: logoAlt || "Logo",
|
|
3554
|
-
className: "h-
|
|
3693
|
+
className: "h-9 w-auto shadow-md"
|
|
3555
3694
|
}
|
|
3556
|
-
)
|
|
3695
|
+
)),
|
|
3696
|
+
!logoUrl && // Default logo when logoUrl is not provided
|
|
3697
|
+
(logoHref ? /* @__PURE__ */ jsx(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity flex items-center", children: /* @__PURE__ */ jsx(
|
|
3557
3698
|
"img",
|
|
3558
3699
|
{
|
|
3559
|
-
src:
|
|
3700
|
+
src: DEFAULT_LOGO_SRC,
|
|
3560
3701
|
alt: logoAlt || "Logo",
|
|
3561
|
-
className: "
|
|
3702
|
+
className: "h-9 w-auto shadow-md"
|
|
3562
3703
|
}
|
|
3563
3704
|
) }) : /* @__PURE__ */ jsx(
|
|
3564
3705
|
"img",
|
|
3565
3706
|
{
|
|
3566
|
-
src:
|
|
3707
|
+
src: DEFAULT_LOGO_SRC,
|
|
3567
3708
|
alt: logoAlt || "Logo",
|
|
3568
|
-
className: "
|
|
3709
|
+
className: "h-9 w-auto shadow-md"
|
|
3569
3710
|
}
|
|
3570
|
-
),
|
|
3711
|
+
)),
|
|
3571
3712
|
navItems && navItems.length > 0 && /* @__PURE__ */ jsx(
|
|
3572
3713
|
NavigationMenu,
|
|
3573
3714
|
{
|
|
@@ -3583,11 +3724,7 @@ function Header({
|
|
|
3583
3724
|
ContextSelector,
|
|
3584
3725
|
{
|
|
3585
3726
|
placeholder: "Select organisation or event",
|
|
3586
|
-
className:
|
|
3587
|
-
"w-96",
|
|
3588
|
-
// Adjust width based on whether actions exist
|
|
3589
|
-
actions ? "col-span-1" : "col-span-2"
|
|
3590
|
-
),
|
|
3727
|
+
className: "w-96",
|
|
3591
3728
|
showOrganisations,
|
|
3592
3729
|
showEvents,
|
|
3593
3730
|
onOrganisationSelect: async (org) => {
|
|
@@ -3631,7 +3768,7 @@ var FooterComponent = ({
|
|
|
3631
3768
|
] }) });
|
|
3632
3769
|
};
|
|
3633
3770
|
FooterComponent.displayName = "Footer";
|
|
3634
|
-
var Footer =
|
|
3771
|
+
var Footer = React__default.memo(FooterComponent);
|
|
3635
3772
|
Footer.displayName = "Footer";
|
|
3636
3773
|
var EMPTY_PAGE_ID_MAPPING = {};
|
|
3637
3774
|
var EMPTY_ROUTE_PERMISSIONS = {};
|
|
@@ -3642,7 +3779,6 @@ function PaceAppLayout({
|
|
|
3642
3779
|
showOrganisations = true,
|
|
3643
3780
|
showEvents = true,
|
|
3644
3781
|
headerActions,
|
|
3645
|
-
customLogo,
|
|
3646
3782
|
logoHref = "/dashboard",
|
|
3647
3783
|
customUserMenu,
|
|
3648
3784
|
headerClassName,
|
|
@@ -3669,9 +3805,9 @@ function PaceAppLayout({
|
|
|
3669
3805
|
const { user, signOut, updatePassword, supabase, appId: contextAppId, selectedOrganisationId } = useUnifiedAuth();
|
|
3670
3806
|
const {
|
|
3671
3807
|
selectedOrganisation,
|
|
3672
|
-
isContextReady,
|
|
3673
|
-
hasValidOrganisationContext,
|
|
3674
|
-
ensureOrganisationContext,
|
|
3808
|
+
isContextReady: _isContextReady,
|
|
3809
|
+
hasValidOrganisationContext: _hasValidOrganisationContext,
|
|
3810
|
+
ensureOrganisationContext: _ensureOrganisationContext,
|
|
3675
3811
|
isLoading: organisationLoading
|
|
3676
3812
|
} = useOrganisations();
|
|
3677
3813
|
const { isSuperAdmin: isSuperAdminFromRBAC, isLoading: rbacLoading } = useRBAC();
|
|
@@ -3709,7 +3845,7 @@ function PaceAppLayout({
|
|
|
3709
3845
|
try {
|
|
3710
3846
|
const eventsContext = useEvents();
|
|
3711
3847
|
selectedEvent = eventsContext.selectedEvent;
|
|
3712
|
-
} catch (
|
|
3848
|
+
} catch (_error) {
|
|
3713
3849
|
}
|
|
3714
3850
|
const { resolvedScope, isLoading: scopeLoading } = useResolvedScope({
|
|
3715
3851
|
supabase: supabase || null,
|
|
@@ -3741,7 +3877,7 @@ function PaceAppLayout({
|
|
|
3741
3877
|
{ id: "ui-showcase", label: "UI Showcase", href: "/ui-showcase", icon: "Component" },
|
|
3742
3878
|
{ id: "data-table-showcase", label: "DataTable Showcase", href: "/data-table-showcase", icon: "Table" }
|
|
3743
3879
|
], []);
|
|
3744
|
-
const baseMenuItems = useMemo(() => navItems || defaultNavItems, [navItems]);
|
|
3880
|
+
const baseMenuItems = useMemo(() => navItems || defaultNavItems, [navItems, defaultNavItems]);
|
|
3745
3881
|
const currentRoutePermission = useMemo(() => {
|
|
3746
3882
|
const currentPath = location.pathname;
|
|
3747
3883
|
return routePermissions[currentPath] || defaultPermission;
|
|
@@ -3833,7 +3969,7 @@ function PaceAppLayout({
|
|
|
3833
3969
|
return;
|
|
3834
3970
|
}
|
|
3835
3971
|
try {
|
|
3836
|
-
const { isSuperAdmin: checkSuperAdminDynamic } = await import('./api-
|
|
3972
|
+
const { isSuperAdmin: checkSuperAdminDynamic } = await import('./api-F47QJ7FX.js');
|
|
3837
3973
|
const isSuper = await checkSuperAdminDynamic(user.id);
|
|
3838
3974
|
if (isSuper) {
|
|
3839
3975
|
if (isMounted) {
|
|
@@ -3847,7 +3983,7 @@ function PaceAppLayout({
|
|
|
3847
3983
|
}
|
|
3848
3984
|
}
|
|
3849
3985
|
try {
|
|
3850
|
-
const { getPermissionMap } = await import('./api-
|
|
3986
|
+
const { getPermissionMap } = await import('./api-F47QJ7FX.js');
|
|
3851
3987
|
const permissionScope = {
|
|
3852
3988
|
organisationId: currentScope.organisationId,
|
|
3853
3989
|
eventId: currentScope.eventId,
|
|
@@ -3858,7 +3994,7 @@ function PaceAppLayout({
|
|
|
3858
3994
|
userId: user.id,
|
|
3859
3995
|
scope: permissionScope
|
|
3860
3996
|
});
|
|
3861
|
-
const { getPageScopeType } = await import('./api-
|
|
3997
|
+
const { getPageScopeType } = await import('./api-F47QJ7FX.js');
|
|
3862
3998
|
const effectiveAppId = currentScope.appId || resolvedAppId;
|
|
3863
3999
|
const effectiveAppName = appName;
|
|
3864
4000
|
const hasEventContext = !!currentScope.eventId;
|
|
@@ -3944,7 +4080,7 @@ function PaceAppLayout({
|
|
|
3944
4080
|
return () => {
|
|
3945
4081
|
isMounted = false;
|
|
3946
4082
|
};
|
|
3947
|
-
}, [baseMenuItems, pageIdMapping, routePermissions, defaultPermission, can, user?.id, scope, scopeLoading, contextAppId, resolvedScope?.appId, selectedOrganisation?.id, selectedEvent?.event_id, appName]);
|
|
4083
|
+
}, [baseMenuItems, pageIdMapping, routePermissions, defaultPermission, can, user?.id, scope, scopeLoading, contextAppId, resolvedScope?.appId, resolvedAppId, selectedOrganisation?.id, selectedEvent?.event_id, appName]);
|
|
3948
4084
|
useEffect(() => {
|
|
3949
4085
|
if (!roleBasedRouting || routeConfig.length === 0) return;
|
|
3950
4086
|
let isMounted = true;
|
|
@@ -3967,7 +4103,7 @@ function PaceAppLayout({
|
|
|
3967
4103
|
let hasAccess = true;
|
|
3968
4104
|
if (currentRoute.pageId && currentRoute.permissions && currentRoute.permissions.length > 0) {
|
|
3969
4105
|
try {
|
|
3970
|
-
const { isPermittedCached } = await import('./api-
|
|
4106
|
+
const { isPermittedCached } = await import('./api-F47QJ7FX.js');
|
|
3971
4107
|
const hasPagePermission = await isPermittedCached({
|
|
3972
4108
|
userId: user?.id || "",
|
|
3973
4109
|
scope,
|
|
@@ -3983,7 +4119,7 @@ function PaceAppLayout({
|
|
|
3983
4119
|
}
|
|
3984
4120
|
}
|
|
3985
4121
|
if (hasAccess && currentRoute.roles && currentRoute.roles.length > 0 && user?.id) {
|
|
3986
|
-
const { useUnifiedAuth: useUnifiedAuth2 } = await import('./UnifiedAuthProvider-
|
|
4122
|
+
const { useUnifiedAuth: useUnifiedAuth2 } = await import('./UnifiedAuthProvider-BBD2PS3Q.js');
|
|
3987
4123
|
hasAccess = true;
|
|
3988
4124
|
}
|
|
3989
4125
|
if (!isMounted) return;
|
|
@@ -4020,7 +4156,7 @@ function PaceAppLayout({
|
|
|
4020
4156
|
logger.error("PaceAppLayout", "Failed to sign out", { error: error instanceof Error ? error.message : String(error) });
|
|
4021
4157
|
}
|
|
4022
4158
|
};
|
|
4023
|
-
const handleChangePassword = async (newPassword,
|
|
4159
|
+
const handleChangePassword = async (newPassword, _confirmPassword) => {
|
|
4024
4160
|
try {
|
|
4025
4161
|
const result = await updatePassword(newPassword);
|
|
4026
4162
|
if (result?.error) {
|
|
@@ -4098,8 +4234,7 @@ function PaceAppLayout({
|
|
|
4098
4234
|
/* @__PURE__ */ jsx(
|
|
4099
4235
|
Header,
|
|
4100
4236
|
{
|
|
4101
|
-
|
|
4102
|
-
logoUrl: !customLogo ? `/${appName.toLowerCase()}_logo_wide.svg` : void 0,
|
|
4237
|
+
logoUrl: `/${appName.toLowerCase()}_logo_wide.svg`,
|
|
4103
4238
|
logoAlt: `${appName} Logo`,
|
|
4104
4239
|
logoHref,
|
|
4105
4240
|
navItems: filteredMenuItems,
|
|
@@ -4160,7 +4295,7 @@ var PaceLoginPage = ({
|
|
|
4160
4295
|
if (isOnLoginPage && eventService) {
|
|
4161
4296
|
await eventService.restorePersistedEvent();
|
|
4162
4297
|
}
|
|
4163
|
-
} catch (
|
|
4298
|
+
} catch (_error) {
|
|
4164
4299
|
}
|
|
4165
4300
|
};
|
|
4166
4301
|
const timeoutId = setTimeout(() => {
|
|
@@ -4407,6 +4542,10 @@ function ProtectedRoute({
|
|
|
4407
4542
|
});
|
|
4408
4543
|
return /* @__PURE__ */ jsx(Navigate, { to: loginPath, replace: true });
|
|
4409
4544
|
}
|
|
4545
|
+
const restorationNotComplete = !sessionRestoration.restorationComplete && !sessionRestoration.hasTimedOut && !sessionRestoration.restorationError;
|
|
4546
|
+
if (restorationNotComplete || sessionRestoration.isRestoring || isLoading) {
|
|
4547
|
+
return loadingFallback || /* @__PURE__ */ jsx("main", { className: "grid place-items-center size-full", children: /* @__PURE__ */ jsx(LoadingSpinner, {}) });
|
|
4548
|
+
}
|
|
4410
4549
|
if (!wasAuthenticatedRef.current) {
|
|
4411
4550
|
return /* @__PURE__ */ jsx(Navigate, { to: loginPath, replace: true });
|
|
4412
4551
|
}
|
|
@@ -4436,6 +4575,168 @@ function ProtectedRoute({
|
|
|
4436
4575
|
}
|
|
4437
4576
|
return /* @__PURE__ */ jsx(Outlet, {});
|
|
4438
4577
|
}
|
|
4578
|
+
var ErrorBoundaryContext = createContext(void 0);
|
|
4579
|
+
function ErrorBoundaryProvider({
|
|
4580
|
+
children,
|
|
4581
|
+
defaultErrorHandler
|
|
4582
|
+
}) {
|
|
4583
|
+
const contextValue = {
|
|
4584
|
+
defaultErrorHandler
|
|
4585
|
+
};
|
|
4586
|
+
return /* @__PURE__ */ jsx(ErrorBoundaryContext.Provider, { value: contextValue, children });
|
|
4587
|
+
}
|
|
4588
|
+
var ErrorBoundary = class extends Component {
|
|
4589
|
+
constructor(props) {
|
|
4590
|
+
super(props);
|
|
4591
|
+
this.retryTimeoutId = null;
|
|
4592
|
+
this.reportError = (errorId, componentName) => {
|
|
4593
|
+
if (import.meta.env.MODE === "production") {
|
|
4594
|
+
logger.warn("ErrorBoundary", "Error reporting would be triggered in production:", { errorId, componentName });
|
|
4595
|
+
}
|
|
4596
|
+
};
|
|
4597
|
+
this.handleRetry = () => {
|
|
4598
|
+
const { maxRetries = 3 } = this.props;
|
|
4599
|
+
const { retryCount } = this.state;
|
|
4600
|
+
if (retryCount < maxRetries) {
|
|
4601
|
+
logger.debug("ErrorBoundary", `Retrying component render (attempt ${retryCount + 1}/${maxRetries})`);
|
|
4602
|
+
this.setState((prevState) => ({
|
|
4603
|
+
hasError: false,
|
|
4604
|
+
error: void 0,
|
|
4605
|
+
errorInfo: void 0,
|
|
4606
|
+
errorId: void 0,
|
|
4607
|
+
retryCount: prevState.retryCount + 1
|
|
4608
|
+
}));
|
|
4609
|
+
}
|
|
4610
|
+
};
|
|
4611
|
+
this.state = {
|
|
4612
|
+
hasError: false,
|
|
4613
|
+
retryCount: 0
|
|
4614
|
+
};
|
|
4615
|
+
}
|
|
4616
|
+
static getDerivedStateFromError(error) {
|
|
4617
|
+
const errorId = `error_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
4618
|
+
return {
|
|
4619
|
+
hasError: true,
|
|
4620
|
+
error,
|
|
4621
|
+
errorId
|
|
4622
|
+
};
|
|
4623
|
+
}
|
|
4624
|
+
componentDidCatch(error, errorInfo) {
|
|
4625
|
+
const { componentName = "Unknown Component", onError, enableReporting = true } = this.props;
|
|
4626
|
+
const errorId = this.state.errorId;
|
|
4627
|
+
const componentNameForHandler = componentName || "Unknown Component";
|
|
4628
|
+
this.setState({ errorInfo });
|
|
4629
|
+
logger.error("ErrorBoundary", `[${componentNameForHandler}] Caught error ${errorId}:`, error, errorInfo);
|
|
4630
|
+
performanceBudgetMonitor.measure("ERROR_BOUNDARY_TRIGGER", 1, {
|
|
4631
|
+
componentName: componentNameForHandler,
|
|
4632
|
+
errorId,
|
|
4633
|
+
errorMessage: error.message,
|
|
4634
|
+
stack: error.stack?.substring(0, 200)
|
|
4635
|
+
// Truncated stack trace
|
|
4636
|
+
});
|
|
4637
|
+
if (enableReporting) {
|
|
4638
|
+
this.reportError(errorId, componentNameForHandler);
|
|
4639
|
+
}
|
|
4640
|
+
if (onError) {
|
|
4641
|
+
onError(error, errorInfo, errorId);
|
|
4642
|
+
} else if (this.props._globalErrorHandler) {
|
|
4643
|
+
this.props._globalErrorHandler(error, errorInfo, errorId, componentNameForHandler);
|
|
4644
|
+
}
|
|
4645
|
+
}
|
|
4646
|
+
componentWillUnmount() {
|
|
4647
|
+
if (this.retryTimeoutId) {
|
|
4648
|
+
clearTimeout(this.retryTimeoutId);
|
|
4649
|
+
}
|
|
4650
|
+
}
|
|
4651
|
+
render() {
|
|
4652
|
+
if (this.state.hasError) {
|
|
4653
|
+
const {
|
|
4654
|
+
componentName = "Component",
|
|
4655
|
+
fallback,
|
|
4656
|
+
enableRetry = true,
|
|
4657
|
+
maxRetries = 3
|
|
4658
|
+
} = this.props;
|
|
4659
|
+
const { retryCount, errorId } = this.state;
|
|
4660
|
+
if (fallback) {
|
|
4661
|
+
return fallback;
|
|
4662
|
+
}
|
|
4663
|
+
return /* @__PURE__ */ jsxs(
|
|
4664
|
+
Card,
|
|
4665
|
+
{
|
|
4666
|
+
role: "alert",
|
|
4667
|
+
className: "bg-destructive/10 border-destructive/20",
|
|
4668
|
+
"data-error-boundary": errorId,
|
|
4669
|
+
children: [
|
|
4670
|
+
/* @__PURE__ */ jsxs(CardHeader, { className: "flex items-start gap-3", children: [
|
|
4671
|
+
/* @__PURE__ */ jsx("svg", { className: "w-5 h-5 text-destructive flex-shrink-0", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx("path", { fillRule: "evenodd", d: "M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7 4a1 1 0 11-2 0 1 1 0 012 0zm-1-9a1 1 0 00-1 1v4a1 1 0 102 0V6a1 1 0 00-1-1z", clipRule: "evenodd" }) }),
|
|
4672
|
+
/* @__PURE__ */ jsxs(CardTitle, { className: "text-destructive", children: [
|
|
4673
|
+
"Error in ",
|
|
4674
|
+
componentName
|
|
4675
|
+
] }),
|
|
4676
|
+
/* @__PURE__ */ jsx(CardDescription, { className: "text-destructive/80", children: this.state.error?.message || "An unexpected error occurred." })
|
|
4677
|
+
] }),
|
|
4678
|
+
import.meta.env.MODE === "development" && this.state.error && /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs("details", { className: "text-sm text-destructive/70", children: [
|
|
4679
|
+
/* @__PURE__ */ jsx("summary", { className: "cursor-pointer font-medium mb-2", children: "Error Details (Development)" }),
|
|
4680
|
+
/* @__PURE__ */ jsxs("pre", { children: [
|
|
4681
|
+
"Error ID: ",
|
|
4682
|
+
errorId,
|
|
4683
|
+
/* @__PURE__ */ jsxs("code", { className: "overflow-auto max-h-32", children: [
|
|
4684
|
+
this.state.error.toString(),
|
|
4685
|
+
this.state.errorInfo?.componentStack
|
|
4686
|
+
] })
|
|
4687
|
+
] })
|
|
4688
|
+
] }) }),
|
|
4689
|
+
enableRetry && retryCount < maxRetries && /* @__PURE__ */ jsxs(CardFooter, { className: "flex gap-3", children: [
|
|
4690
|
+
/* @__PURE__ */ jsxs(
|
|
4691
|
+
"button",
|
|
4692
|
+
{
|
|
4693
|
+
onClick: this.handleRetry,
|
|
4694
|
+
className: "px-4 py-2 bg-destructive text-destructive-foreground rounded-md hover:bg-destructive/90 transition-colors text-sm font-medium",
|
|
4695
|
+
children: [
|
|
4696
|
+
"Retry (",
|
|
4697
|
+
retryCount + 1,
|
|
4698
|
+
"/",
|
|
4699
|
+
maxRetries,
|
|
4700
|
+
")"
|
|
4701
|
+
]
|
|
4702
|
+
}
|
|
4703
|
+
),
|
|
4704
|
+
/* @__PURE__ */ jsx(
|
|
4705
|
+
"button",
|
|
4706
|
+
{
|
|
4707
|
+
onClick: () => window.location.reload(),
|
|
4708
|
+
className: "px-4 py-2 bg-sec-600 text-main-50 rounded-md hover:bg-sec-700 transition-colors text-sm font-medium",
|
|
4709
|
+
children: "Reload Page"
|
|
4710
|
+
}
|
|
4711
|
+
)
|
|
4712
|
+
] }),
|
|
4713
|
+
retryCount >= maxRetries && /* @__PURE__ */ jsxs(CardFooter, { className: "flex flex-col gap-3", children: [
|
|
4714
|
+
/* @__PURE__ */ jsx("p", { className: "text-acc-800", children: "Maximum retry attempts reached. Please reload the page or contact support." }),
|
|
4715
|
+
/* @__PURE__ */ jsx(
|
|
4716
|
+
"button",
|
|
4717
|
+
{
|
|
4718
|
+
onClick: () => window.location.reload(),
|
|
4719
|
+
className: "px-3 py-1 bg-acc-600 text-main-50 rounded text-sm hover:bg-acc-700",
|
|
4720
|
+
children: "Reload Page"
|
|
4721
|
+
}
|
|
4722
|
+
)
|
|
4723
|
+
] })
|
|
4724
|
+
]
|
|
4725
|
+
}
|
|
4726
|
+
);
|
|
4727
|
+
}
|
|
4728
|
+
return this.props.children;
|
|
4729
|
+
}
|
|
4730
|
+
};
|
|
4731
|
+
function useErrorBoundaryContext() {
|
|
4732
|
+
return useContext(ErrorBoundaryContext);
|
|
4733
|
+
}
|
|
4734
|
+
var ErrorBoundary2 = React__default.forwardRef((props, ref) => {
|
|
4735
|
+
const context = useErrorBoundaryContext();
|
|
4736
|
+
const globalErrorHandler = context?.defaultErrorHandler;
|
|
4737
|
+
return React__default.createElement(ErrorBoundary, { ...props, ref, _globalErrorHandler: globalErrorHandler });
|
|
4738
|
+
});
|
|
4739
|
+
ErrorBoundary2.displayName = "ErrorBoundary";
|
|
4439
4740
|
function FileUpload({
|
|
4440
4741
|
supabase,
|
|
4441
4742
|
table_name,
|
|
@@ -4461,11 +4762,10 @@ function FileUpload({
|
|
|
4461
4762
|
onProgress,
|
|
4462
4763
|
children
|
|
4463
4764
|
}) {
|
|
4765
|
+
const logger2 = createLogger("FileUpload");
|
|
4464
4766
|
if (!pageContext) {
|
|
4465
4767
|
const errorMsg = "pageContext is required for FileUpload component. This is used for permission checks.";
|
|
4466
|
-
|
|
4467
|
-
console.error("[FileUpload]", errorMsg);
|
|
4468
|
-
}
|
|
4768
|
+
logger2.error(errorMsg);
|
|
4469
4769
|
throw new Error(errorMsg);
|
|
4470
4770
|
}
|
|
4471
4771
|
const [isDragging, setIsDragging] = useState(false);
|
|
@@ -4475,13 +4775,14 @@ function FileUpload({
|
|
|
4475
4775
|
const [appIdError, setAppIdError] = useState(null);
|
|
4476
4776
|
const fileInputRef = useRef(null);
|
|
4477
4777
|
const progressIntervalsRef = useRef(/* @__PURE__ */ new Map());
|
|
4478
|
-
const { uploadFile,
|
|
4778
|
+
const { uploadFile, error } = useFileReference(supabase);
|
|
4479
4779
|
useEffect(() => {
|
|
4780
|
+
const intervals = progressIntervalsRef.current;
|
|
4480
4781
|
return () => {
|
|
4481
|
-
|
|
4782
|
+
intervals.forEach((interval) => {
|
|
4482
4783
|
clearInterval(interval);
|
|
4483
4784
|
});
|
|
4484
|
-
|
|
4785
|
+
intervals.clear();
|
|
4485
4786
|
};
|
|
4486
4787
|
}, []);
|
|
4487
4788
|
useEffect(() => {
|
|
@@ -4754,7 +5055,7 @@ function FileUpload({
|
|
|
4754
5055
|
onUploadError?.(errorMessage, file);
|
|
4755
5056
|
}
|
|
4756
5057
|
}
|
|
4757
|
-
}, [uploadFile, table_name, record_id, organisation_id, resolvedAppId, category, folder, isPublic,
|
|
5058
|
+
}, [uploadFile, table_name, record_id, organisation_id, resolvedAppId, category, folder, isPublic, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError, pageContext, event_id, userId]);
|
|
4758
5059
|
const handleDragOver = useCallback((e) => {
|
|
4759
5060
|
e.preventDefault();
|
|
4760
5061
|
e.stopPropagation();
|
|
@@ -4908,7 +5209,7 @@ function FileUpload({
|
|
|
4908
5209
|
}
|
|
4909
5210
|
function PublicPageHeader({
|
|
4910
5211
|
event,
|
|
4911
|
-
eventCode,
|
|
5212
|
+
eventCode: _eventCode,
|
|
4912
5213
|
title,
|
|
4913
5214
|
description,
|
|
4914
5215
|
showEventLogo = true,
|
|
@@ -4935,7 +5236,7 @@ function PublicPageHeader({
|
|
|
4935
5236
|
showEventLogo && event && /* @__PURE__ */ jsx(Fragment, { children: customEventLogo || /* @__PURE__ */ jsx(
|
|
4936
5237
|
FileDisplay,
|
|
4937
5238
|
{
|
|
4938
|
-
table_name: "
|
|
5239
|
+
table_name: "core_events",
|
|
4939
5240
|
record_id: event.event_id,
|
|
4940
5241
|
organisation_id: event.organisation_id,
|
|
4941
5242
|
category: "event_logos" /* EVENT_LOGOS */,
|
|
@@ -4943,7 +5244,7 @@ function PublicPageHeader({
|
|
|
4943
5244
|
showFallback: true,
|
|
4944
5245
|
fallbackSize: "md",
|
|
4945
5246
|
className: "mr-4 max-w-36 row-span-2",
|
|
4946
|
-
generateFallbackText: (
|
|
5247
|
+
generateFallbackText: (_fileName) => {
|
|
4947
5248
|
if (!event.event_name) return "EV";
|
|
4948
5249
|
return event.event_name.split(/[\s\-_]+/).map((word) => word.charAt(0).toUpperCase()).join("").substring(0, 3);
|
|
4949
5250
|
}
|
|
@@ -4959,7 +5260,7 @@ function PublicPageHeader({
|
|
|
4959
5260
|
] });
|
|
4960
5261
|
}
|
|
4961
5262
|
function PublicPageFooter({
|
|
4962
|
-
event,
|
|
5263
|
+
event: _event,
|
|
4963
5264
|
companyName = "Solvera Solutions Pty Ltd",
|
|
4964
5265
|
year = (/* @__PURE__ */ new Date()).getFullYear(),
|
|
4965
5266
|
links,
|
|
@@ -4998,7 +5299,7 @@ function PublicPageLayout({
|
|
|
4998
5299
|
if (LoadingFallback) {
|
|
4999
5300
|
return /* @__PURE__ */ jsx(LoadingFallback, {});
|
|
5000
5301
|
}
|
|
5001
|
-
return /* @__PURE__ */ jsxs("
|
|
5302
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid place-items-center text-center size-full", children: [
|
|
5002
5303
|
/* @__PURE__ */ jsx(
|
|
5003
5304
|
LoadingSpinner,
|
|
5004
5305
|
{
|
|
@@ -5030,7 +5331,7 @@ function PublicPageLayout({
|
|
|
5030
5331
|
handleRefetch && /* @__PURE__ */ jsx(Button, { onClick: handleRefetch, children: "Try Again" })
|
|
5031
5332
|
] });
|
|
5032
5333
|
}
|
|
5033
|
-
return /* @__PURE__ */ jsx(
|
|
5334
|
+
return /* @__PURE__ */ jsx(ErrorBoundary2, { componentName: "PublicPageLayout", children: /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5034
5335
|
customHeader || /* @__PURE__ */ jsx(
|
|
5035
5336
|
PublicPageHeader,
|
|
5036
5337
|
{
|
|
@@ -5042,5 +5343,37 @@ function PublicPageLayout({
|
|
|
5042
5343
|
showFooter && event && (customFooter || /* @__PURE__ */ jsx(PublicPageFooter, { event }))
|
|
5043
5344
|
] }) });
|
|
5044
5345
|
}
|
|
5346
|
+
function PublicPageProvider({ children, appName }) {
|
|
5347
|
+
const getEnvVar = (key) => {
|
|
5348
|
+
if (typeof import.meta !== "undefined" && import.meta.env) {
|
|
5349
|
+
const env = import.meta.env;
|
|
5350
|
+
return env[key];
|
|
5351
|
+
}
|
|
5352
|
+
if (typeof process !== "undefined" && process.env) {
|
|
5353
|
+
return process.env[key];
|
|
5354
|
+
}
|
|
5355
|
+
return void 0;
|
|
5356
|
+
};
|
|
5357
|
+
const supabaseUrl = getEnvVar("VITE_SUPABASE_URL") || getEnvVar("NEXT_PUBLIC_SUPABASE_URL") || null;
|
|
5358
|
+
const supabaseKey = getEnvVar("VITE_SUPABASE_PUBLISHABLE_KEY") || getEnvVar("NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY") || getEnvVar("VITE_SUPABASE_ANON_KEY") || getEnvVar("NEXT_PUBLIC_SUPABASE_ANON_KEY") || null;
|
|
5359
|
+
const supabase = useMemo(() => {
|
|
5360
|
+
if (!supabaseUrl || !supabaseKey) {
|
|
5361
|
+
logger.warn("PublicPageProvider", "Missing Supabase environment variables. Please ensure VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY are set in your environment.");
|
|
5362
|
+
return null;
|
|
5363
|
+
}
|
|
5364
|
+
const client = createClient(supabaseUrl, supabaseKey);
|
|
5365
|
+
return client;
|
|
5366
|
+
}, [supabaseUrl, supabaseKey]);
|
|
5367
|
+
const contextValue = {
|
|
5368
|
+
isPublicPage: true,
|
|
5369
|
+
supabase,
|
|
5370
|
+
appName: appName || null,
|
|
5371
|
+
environment: {
|
|
5372
|
+
supabaseUrl,
|
|
5373
|
+
supabaseKey
|
|
5374
|
+
}
|
|
5375
|
+
};
|
|
5376
|
+
return /* @__PURE__ */ jsx(PublicPageContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(ErrorBoundary2, { componentName: "PublicPageProvider", children }) });
|
|
5377
|
+
}
|
|
5045
5378
|
|
|
5046
|
-
export { AddressField, Avatar, Badge, Calendar, ContextSelector, FileDisplay, FileUpload, Footer, Form, FormField, Header, LoginForm, NavigationMenu, PaceAppLayout, PaceLoginPage, PasswordChangeForm, ProtectedRoute, PublicPageFooter, PublicPageHeader, PublicPageLayout, SessionRestorationLoader, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, Toaster, UserMenu, useFileReference, useFileReferenceById, useFileReferenceForRecord, useFilesByCategory };
|
|
5379
|
+
export { AddressField, AppSwitcher, Avatar, Badge, Calendar, ContextSelector, DEFAULT_APP_PORT_MAP, DatePickerWithTimezone, ErrorBoundary2 as ErrorBoundary, ErrorBoundaryProvider, FileDisplay, FileUpload, Footer, Form, FormField, Header, LoginForm, NavigationMenu, PaceAppLayout, PaceLoginPage, PasswordChangeForm, ProtectedRoute, PublicPageFooter, PublicPageHeader, PublicPageLayout, PublicPageProvider, SessionRestorationLoader, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Toast, ToastAction, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport, Toaster, UserMenu, buildAppUrl, getAllAppPorts, getAppPort, useAccessibleApps, useFileReference, useFileReferenceById, useFileReferenceForRecord, useFilesByCategory };
|