@jmruthers/pace-core 0.5.184 → 0.5.186

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.
Files changed (319) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +60 -1
  3. package/core-usage-manifest.json +312 -0
  4. package/dist/{DataTable-QAB34V6K.js → DataTable-IX2NBUTP.js} +6 -6
  5. package/dist/{DataTable-Bz8ffqyA.d.ts → DataTable-Z9NLVJh0.d.ts} +1 -1
  6. package/dist/{index-Bl--n7-T.d.ts → PublicPageProvider-DIzEzwKl.d.ts} +23 -10
  7. package/dist/{UnifiedAuthProvider-7F6T4B6K.js → UnifiedAuthProvider-A4BCQRJY.js} +4 -2
  8. package/dist/{UnifiedAuthProvider-F86d7dSi.d.ts → UnifiedAuthProvider-BG0AL5eE.d.ts} +2 -1
  9. package/dist/{api-ROMBCNKU.js → api-BMFCXVQX.js} +2 -2
  10. package/dist/{chunk-RA3JUFMW.js → chunk-445GEP27.js} +154 -4
  11. package/dist/{chunk-RA3JUFMW.js.map → chunk-445GEP27.js.map} +1 -1
  12. package/dist/{chunk-W22JP75J.js → chunk-DAGICKHT.js} +9 -7
  13. package/dist/chunk-DAGICKHT.js.map +1 -0
  14. package/dist/{chunk-FUEYYMX5.js → chunk-FXFJRTKI.js} +24 -3
  15. package/dist/chunk-FXFJRTKI.js.map +1 -0
  16. package/dist/{chunk-CSOFYHAG.js → chunk-GRIQLQ52.js} +374 -60
  17. package/dist/chunk-GRIQLQ52.js.map +1 -0
  18. package/dist/{chunk-NQPMQGS2.js → chunk-HDCUMOOI.js} +497 -399
  19. package/dist/chunk-HDCUMOOI.js.map +1 -0
  20. package/dist/chunk-HESYZWZW.js +388 -0
  21. package/dist/chunk-HESYZWZW.js.map +1 -0
  22. package/dist/{chunk-QUVSNGIP.js → chunk-HGPQUCBC.js} +34 -9
  23. package/dist/{chunk-QUVSNGIP.js.map → chunk-HGPQUCBC.js.map} +1 -1
  24. package/dist/{chunk-PWAHJW4G.js → chunk-OALXJH4Y.js} +86 -33
  25. package/dist/chunk-OALXJH4Y.js.map +1 -0
  26. package/dist/{chunk-MI7HBHN3.js → chunk-TC7D3CR3.js} +89 -9
  27. package/dist/chunk-TC7D3CR3.js.map +1 -0
  28. package/dist/chunk-THRPYOFK.js +215 -0
  29. package/dist/chunk-THRPYOFK.js.map +1 -0
  30. package/dist/{chunk-M7W4CP3M.js → chunk-U6WNSFX5.js} +2 -1
  31. package/dist/chunk-U6WNSFX5.js.map +1 -0
  32. package/dist/{chunk-UHNYIBXL.js → chunk-UQWSHFVX.js} +1 -1
  33. package/dist/chunk-UQWSHFVX.js.map +1 -0
  34. package/dist/{chunk-QCDXODCA.js → chunk-XAUHJD3L.js} +2 -2
  35. package/dist/components.d.ts +182 -6
  36. package/dist/components.js +157 -11
  37. package/dist/components.js.map +1 -1
  38. package/dist/{database.generated-CBmg2950.d.ts → database.generated-DI89OQeI.d.ts} +63 -9
  39. package/dist/eslint-rules/pace-core-compliance.cjs +406 -0
  40. package/dist/{file-reference-D06mEEWW.d.ts → file-reference-PRTSLxKx.d.ts} +10 -1
  41. package/dist/hooks.d.ts +52 -15
  42. package/dist/hooks.js +12 -22
  43. package/dist/hooks.js.map +1 -1
  44. package/dist/index.d.ts +12 -12
  45. package/dist/index.js +82 -18
  46. package/dist/index.js.map +1 -1
  47. package/dist/providers.d.ts +1 -1
  48. package/dist/providers.js +3 -1
  49. package/dist/rbac/index.d.ts +206 -15
  50. package/dist/rbac/index.js +28 -6
  51. package/dist/timezone-_pgH8qrY.d.ts +530 -0
  52. package/dist/{types-_x1f4QBF.d.ts → types-DUyCRSTj.d.ts} +1 -1
  53. package/dist/types.d.ts +2 -2
  54. package/dist/types.js +1 -1
  55. package/dist/{usePublicRouteParams-JJczomYq.d.ts → usePublicRouteParams-D71QLlg4.d.ts} +114 -3
  56. package/dist/utils.d.ts +110 -152
  57. package/dist/utils.js +128 -138
  58. package/dist/utils.js.map +1 -1
  59. package/docs/api/README.md +60 -1
  60. package/docs/api/classes/ColumnFactory.md +1 -1
  61. package/docs/api/classes/ErrorBoundary.md +1 -1
  62. package/docs/api/classes/InvalidScopeError.md +1 -1
  63. package/docs/api/classes/Logger.md +178 -0
  64. package/docs/api/classes/MissingUserContextError.md +1 -1
  65. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  66. package/docs/api/classes/PermissionDeniedError.md +1 -1
  67. package/docs/api/classes/RBACAuditManager.md +2 -2
  68. package/docs/api/classes/RBACCache.md +1 -1
  69. package/docs/api/classes/RBACEngine.md +2 -2
  70. package/docs/api/classes/RBACError.md +1 -1
  71. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  72. package/docs/api/classes/SecureSupabaseClient.md +5 -5
  73. package/docs/api/classes/StorageUtils.md +1 -1
  74. package/docs/api/enums/FileCategory.md +1 -1
  75. package/docs/api/enums/LogLevel.md +54 -0
  76. package/docs/api/enums/RBACErrorCode.md +1 -1
  77. package/docs/api/enums/RPCFunction.md +1 -1
  78. package/docs/api/interfaces/AggregateConfig.md +1 -1
  79. package/docs/api/interfaces/BadgeProps.md +1 -1
  80. package/docs/api/interfaces/ButtonProps.md +1 -1
  81. package/docs/api/interfaces/CalendarProps.md +18 -2
  82. package/docs/api/interfaces/CardProps.md +1 -1
  83. package/docs/api/interfaces/ColorPalette.md +1 -1
  84. package/docs/api/interfaces/ColorShade.md +1 -1
  85. package/docs/api/interfaces/ComplianceResult.md +30 -0
  86. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  87. package/docs/api/interfaces/DataRecord.md +1 -1
  88. package/docs/api/interfaces/DataTableAction.md +1 -1
  89. package/docs/api/interfaces/DataTableColumn.md +1 -1
  90. package/docs/api/interfaces/DataTableProps.md +1 -1
  91. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  92. package/docs/api/interfaces/DatabaseComplianceResult.md +85 -0
  93. package/docs/api/interfaces/DatabaseIssue.md +41 -0
  94. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  95. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  96. package/docs/api/interfaces/EventAppRoleData.md +6 -6
  97. package/docs/api/interfaces/ExportColumn.md +1 -1
  98. package/docs/api/interfaces/ExportOptions.md +1 -1
  99. package/docs/api/interfaces/FileDisplayProps.md +1 -1
  100. package/docs/api/interfaces/FileMetadata.md +1 -1
  101. package/docs/api/interfaces/FileReference.md +1 -1
  102. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  103. package/docs/api/interfaces/FileUploadOptions.md +48 -8
  104. package/docs/api/interfaces/FileUploadProps.md +46 -13
  105. package/docs/api/interfaces/FooterProps.md +1 -1
  106. package/docs/api/interfaces/FormFieldProps.md +1 -1
  107. package/docs/api/interfaces/FormProps.md +1 -1
  108. package/docs/api/interfaces/GrantEventAppRoleParams.md +9 -9
  109. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  110. package/docs/api/interfaces/InputProps.md +1 -1
  111. package/docs/api/interfaces/LabelProps.md +1 -1
  112. package/docs/api/interfaces/LoggerConfig.md +62 -0
  113. package/docs/api/interfaces/LoginFormProps.md +1 -1
  114. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  115. package/docs/api/interfaces/NavigationContextType.md +1 -1
  116. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  117. package/docs/api/interfaces/NavigationItem.md +1 -1
  118. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  119. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  120. package/docs/api/interfaces/Organisation.md +1 -1
  121. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  122. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  123. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  124. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  125. package/docs/api/interfaces/PaceAppLayoutProps.md +36 -23
  126. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  127. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  128. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  129. package/docs/api/interfaces/PagePermissionGuardProps.md +11 -11
  130. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  131. package/docs/api/interfaces/PaletteData.md +1 -1
  132. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  133. package/docs/api/interfaces/ProgressProps.md +1 -1
  134. package/docs/api/interfaces/ProtectedRouteProps.md +6 -6
  135. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  136. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  137. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  138. package/docs/api/interfaces/QuickFix.md +52 -0
  139. package/docs/api/interfaces/RBACAccessValidateParams.md +1 -1
  140. package/docs/api/interfaces/RBACAccessValidateResult.md +1 -1
  141. package/docs/api/interfaces/RBACAuditLogParams.md +1 -1
  142. package/docs/api/interfaces/RBACAuditLogResult.md +1 -1
  143. package/docs/api/interfaces/RBACConfig.md +4 -4
  144. package/docs/api/interfaces/RBACContext.md +1 -1
  145. package/docs/api/interfaces/RBACLogger.md +1 -1
  146. package/docs/api/interfaces/RBACPageAccessCheckParams.md +1 -1
  147. package/docs/api/interfaces/RBACPermissionCheckParams.md +1 -1
  148. package/docs/api/interfaces/RBACPermissionCheckResult.md +1 -1
  149. package/docs/api/interfaces/RBACPermissionsGetParams.md +1 -1
  150. package/docs/api/interfaces/RBACPermissionsGetResult.md +1 -1
  151. package/docs/api/interfaces/RBACResult.md +1 -1
  152. package/docs/api/interfaces/RBACRoleGrantParams.md +1 -1
  153. package/docs/api/interfaces/RBACRoleGrantResult.md +1 -1
  154. package/docs/api/interfaces/RBACRoleRevokeParams.md +1 -1
  155. package/docs/api/interfaces/RBACRoleRevokeResult.md +1 -1
  156. package/docs/api/interfaces/RBACRoleValidateParams.md +1 -1
  157. package/docs/api/interfaces/RBACRoleValidateResult.md +1 -1
  158. package/docs/api/interfaces/RBACRolesListParams.md +1 -1
  159. package/docs/api/interfaces/RBACRolesListResult.md +1 -1
  160. package/docs/api/interfaces/RBACSessionTrackParams.md +1 -1
  161. package/docs/api/interfaces/RBACSessionTrackResult.md +1 -1
  162. package/docs/api/interfaces/ResourcePermissions.md +1 -1
  163. package/docs/api/interfaces/RevokeEventAppRoleParams.md +7 -7
  164. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  165. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  166. package/docs/api/interfaces/RoleManagementResult.md +5 -5
  167. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  168. package/docs/api/interfaces/RouteConfig.md +1 -1
  169. package/docs/api/interfaces/RuntimeComplianceResult.md +55 -0
  170. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  171. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  172. package/docs/api/interfaces/SessionRestorationLoaderProps.md +1 -1
  173. package/docs/api/interfaces/SetupIssue.md +41 -0
  174. package/docs/api/interfaces/StorageConfig.md +1 -1
  175. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  176. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  177. package/docs/api/interfaces/StorageListOptions.md +1 -1
  178. package/docs/api/interfaces/StorageListResult.md +1 -1
  179. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  180. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  181. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  182. package/docs/api/interfaces/StyleImport.md +1 -1
  183. package/docs/api/interfaces/SwitchProps.md +1 -1
  184. package/docs/api/interfaces/TabsContentProps.md +1 -1
  185. package/docs/api/interfaces/TabsListProps.md +1 -1
  186. package/docs/api/interfaces/TabsProps.md +1 -1
  187. package/docs/api/interfaces/TabsTriggerProps.md +1 -1
  188. package/docs/api/interfaces/TextareaProps.md +1 -1
  189. package/docs/api/interfaces/ToastActionElement.md +1 -1
  190. package/docs/api/interfaces/ToastProps.md +1 -1
  191. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  192. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  193. package/docs/api/interfaces/UseFormDialogOptions.md +62 -0
  194. package/docs/api/interfaces/UseFormDialogReturn.md +117 -0
  195. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  196. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  197. package/docs/api/interfaces/UsePublicEventLogoOptions.md +2 -2
  198. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  199. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  200. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  201. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +2 -2
  202. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +1 -1
  203. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  204. package/docs/api/interfaces/UseResolvedScopeOptions.md +2 -2
  205. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  206. package/docs/api/interfaces/UseResourcePermissionsOptions.md +1 -1
  207. package/docs/api/interfaces/UserEventAccess.md +1 -1
  208. package/docs/api/interfaces/UserMenuProps.md +1 -1
  209. package/docs/api/interfaces/UserProfile.md +1 -1
  210. package/docs/api/modules.md +746 -50
  211. package/docs/api-reference/components.md +26 -12
  212. package/docs/api-reference/hooks.md +111 -0
  213. package/docs/api-reference/rpc-functions.md +1 -1
  214. package/docs/api-reference/utilities.md +184 -0
  215. package/docs/getting-started/installation-guide.md +75 -16
  216. package/docs/getting-started/quick-start.md +61 -11
  217. package/docs/implementation-guides/authentication.md +88 -12
  218. package/docs/implementation-guides/file-reference-system.md +26 -3
  219. package/docs/implementation-guides/file-upload-storage.md +30 -1
  220. package/docs/rbac/README.md +1 -0
  221. package/docs/rbac/compliance/compliance-guide.md +544 -0
  222. package/docs/rbac/getting-started.md +158 -33
  223. package/docs/standards/pace-core-compliance.md +432 -0
  224. package/eslint-config-pace-core.cjs +93 -0
  225. package/package.json +15 -3
  226. package/scripts/analyze-bundle.js +232 -0
  227. package/scripts/build-css.js +56 -0
  228. package/scripts/build-docs-incremental.js +1015 -0
  229. package/scripts/check-pace-core-compliance.cjs +2353 -0
  230. package/scripts/check-pace-core-compliance.js +512 -0
  231. package/scripts/generate-docs.js +157 -0
  232. package/scripts/setup-build-cache.js +73 -0
  233. package/scripts/utils/command-runner.js +131 -0
  234. package/scripts/utils/env.js +33 -0
  235. package/scripts/utils/index.js +10 -0
  236. package/scripts/utils/logger.js +88 -0
  237. package/scripts/utils/path-helpers.js +37 -0
  238. package/scripts/validate-formats.js +133 -0
  239. package/scripts/validate-master.js +155 -0
  240. package/scripts/validate-pre-publish.js +140 -0
  241. package/scripts/validate-theme.js +142 -0
  242. package/src/components/Calendar/Calendar.tsx +8 -1
  243. package/src/components/Card/Card.tsx +47 -8
  244. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.test.tsx +314 -0
  245. package/src/components/DatePickerWithTimezone/DatePickerWithTimezone.tsx +126 -0
  246. package/src/components/DatePickerWithTimezone/README.md +135 -0
  247. package/src/components/DatePickerWithTimezone/index.ts +10 -0
  248. package/src/components/DateTimeField/DateTimeField.test.tsx +358 -0
  249. package/src/components/DateTimeField/DateTimeField.tsx +232 -0
  250. package/src/components/DateTimeField/README.md +148 -0
  251. package/src/components/DateTimeField/index.ts +10 -0
  252. package/src/components/FileUpload/FileUpload.test.tsx +2 -0
  253. package/src/components/FileUpload/FileUpload.tsx +10 -1
  254. package/src/components/Header/Header.test.tsx +47 -18
  255. package/src/components/Header/Header.tsx +22 -7
  256. package/src/components/PaceAppLayout/PaceAppLayout.tsx +29 -20
  257. package/src/components/PaceAppLayout/README.md +9 -0
  258. package/src/components/ProtectedRoute/ProtectedRoute.test.tsx +37 -8
  259. package/src/components/ProtectedRoute/ProtectedRoute.tsx +146 -5
  260. package/src/components/index.ts +8 -0
  261. package/src/eslint-rules/pace-core-compliance.cjs +406 -0
  262. package/src/eslint-rules/pace-core-compliance.js +640 -0
  263. package/src/hooks/__tests__/useFormDialog.test.ts +478 -0
  264. package/src/hooks/index.ts +5 -0
  265. package/src/hooks/useFileReference.test.ts +2 -0
  266. package/src/hooks/useFormDialog.ts +147 -0
  267. package/src/hooks/usePreventTabReload.ts +106 -0
  268. package/src/hooks/useSecureDataAccess.ts +2 -2
  269. package/src/index.ts +27 -0
  270. package/src/providers/services/OrganisationServiceProvider.tsx +6 -5
  271. package/src/providers/services/UnifiedAuthProvider.tsx +24 -3
  272. package/src/rbac/__tests__/rbac-role-isolation.test.ts +456 -0
  273. package/src/rbac/__tests__/scenarios.user-role.test.tsx +3 -0
  274. package/src/rbac/compliance/database-validator.ts +165 -0
  275. package/src/rbac/compliance/index.ts +38 -0
  276. package/src/rbac/compliance/quick-fix-suggestions.ts +209 -0
  277. package/src/rbac/compliance/runtime-compliance.ts +77 -0
  278. package/src/rbac/compliance/setup-validator.ts +131 -0
  279. package/src/rbac/components/PagePermissionGuard.tsx +8 -64
  280. package/src/rbac/components/__tests__/PagePermissionGuard.test.tsx +35 -21
  281. package/src/rbac/docs/event-based-apps.md +285 -0
  282. package/src/rbac/errors.ts +11 -0
  283. package/src/rbac/hooks/useRoleManagement.ts +292 -12
  284. package/src/rbac/index.ts +30 -0
  285. package/src/services/OrganisationService.ts +4 -0
  286. package/src/styles/core.css +5 -5
  287. package/src/types/database.generated.ts +63 -9
  288. package/src/types/file-reference.ts +9 -0
  289. package/src/utils/__tests__/timezone.test.ts +345 -0
  290. package/src/utils/file-reference/__tests__/file-reference.test.ts +60 -4
  291. package/src/utils/file-reference/index.ts +13 -2
  292. package/src/utils/formatting/formatDateTimeTimezone.test.ts +167 -0
  293. package/src/utils/formatting/formatting.ts +179 -0
  294. package/src/utils/index.ts +27 -1
  295. package/src/utils/location/index.ts +16 -0
  296. package/src/utils/location/location.test.ts +286 -0
  297. package/src/utils/location/location.ts +175 -0
  298. package/src/utils/security/secureDataAccess.ts +1 -1
  299. package/src/utils/storage/helpers.ts +68 -0
  300. package/src/utils/timezone/index.ts +17 -0
  301. package/src/utils/timezone/timezone.test.ts +349 -0
  302. package/src/utils/timezone/timezone.ts +281 -0
  303. package/dist/chunk-CSOFYHAG.js.map +0 -1
  304. package/dist/chunk-FUEYYMX5.js.map +0 -1
  305. package/dist/chunk-HKIT6O7W.js +0 -198
  306. package/dist/chunk-HKIT6O7W.js.map +0 -1
  307. package/dist/chunk-KUEN3HFB.js +0 -94
  308. package/dist/chunk-KUEN3HFB.js.map +0 -1
  309. package/dist/chunk-M7W4CP3M.js.map +0 -1
  310. package/dist/chunk-MI7HBHN3.js.map +0 -1
  311. package/dist/chunk-NQPMQGS2.js.map +0 -1
  312. package/dist/chunk-PWAHJW4G.js.map +0 -1
  313. package/dist/chunk-UHNYIBXL.js.map +0 -1
  314. package/dist/chunk-W22JP75J.js.map +0 -1
  315. package/dist/formatting-5wETwiGF.d.ts +0 -162
  316. /package/dist/{DataTable-QAB34V6K.js.map → DataTable-IX2NBUTP.js.map} +0 -0
  317. /package/dist/{UnifiedAuthProvider-7F6T4B6K.js.map → UnifiedAuthProvider-A4BCQRJY.js.map} +0 -0
  318. /package/dist/{api-ROMBCNKU.js.map → api-BMFCXVQX.js.map} +0 -0
  319. /package/dist/{chunk-QCDXODCA.js.map → chunk-XAUHJD3L.js.map} +0 -0
@@ -25,16 +25,16 @@ import {
25
25
  SelectSeparator,
26
26
  SelectTrigger,
27
27
  SelectValue
28
- } from "./chunk-QUVSNGIP.js";
28
+ } from "./chunk-HGPQUCBC.js";
29
29
  import {
30
30
  useCan,
31
31
  usePermissions,
32
32
  useRBAC,
33
33
  useResolvedScope
34
- } from "./chunk-RA3JUFMW.js";
34
+ } from "./chunk-445GEP27.js";
35
35
  import {
36
36
  isSuperAdmin
37
- } from "./chunk-M7W4CP3M.js";
37
+ } from "./chunk-U6WNSFX5.js";
38
38
  import {
39
39
  ErrorBoundary,
40
40
  PublicPageContext,
@@ -46,27 +46,28 @@ import {
46
46
  useEventTheme,
47
47
  useFileDisplay,
48
48
  useIsPublicPage,
49
+ usePreventTabReload,
49
50
  usePublicFileDisplay
50
- } from "./chunk-MI7HBHN3.js";
51
+ } from "./chunk-TC7D3CR3.js";
51
52
  import {
52
53
  useToast
53
54
  } from "./chunk-6C4YBBJM.js";
54
55
  import {
55
56
  useEvents,
56
57
  useOrganisations
57
- } from "./chunk-QCDXODCA.js";
58
+ } from "./chunk-XAUHJD3L.js";
58
59
  import {
59
60
  EventServiceContext,
60
61
  useSessionRestoration,
61
62
  useUnifiedAuth
62
- } from "./chunk-FUEYYMX5.js";
63
+ } from "./chunk-FXFJRTKI.js";
63
64
  import {
64
65
  assertAppId
65
66
  } from "./chunk-QXHPKYJV.js";
66
67
  import {
67
68
  LoadingSpinner,
68
69
  getAppId
69
- } from "./chunk-KUEN3HFB.js";
70
+ } from "./chunk-THRPYOFK.js";
70
71
  import {
71
72
  cn
72
73
  } from "./chunk-R77UEZ4E.js";
@@ -980,14 +981,185 @@ function EventSelector({
980
981
  );
981
982
  }
982
983
 
983
- // src/components/PasswordChange/PasswordChangeForm.tsx
984
- import { useState as useState2 } from "react";
984
+ // src/components/OrganisationSelector/OrganisationSelector.tsx
985
+ import { useState as useState2, useCallback as useCallback2 } from "react";
986
+ import { RefreshCw as RefreshCw2, AlertCircle as AlertCircle2, Building2, Shield } from "lucide-react";
985
987
  import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
988
+ function OrganisationSelector({
989
+ placeholder = "Select organisation",
990
+ className,
991
+ onOrganisationChange,
992
+ showNoOrganisationsMessage = true,
993
+ showRetryButton = true,
994
+ showRole = false,
995
+ compact = false,
996
+ disabled = false
997
+ }) {
998
+ const [isLoading, setIsLoading] = useState2(false);
999
+ const [switchError, setSwitchError] = useState2(null);
1000
+ const {
1001
+ organisations,
1002
+ selectedOrganisation,
1003
+ isLoading: orgLoading,
1004
+ error: orgError,
1005
+ switchOrganisation,
1006
+ getUserRole,
1007
+ validateOrganisationAccess,
1008
+ refreshOrganisations
1009
+ } = useOrganisations();
1010
+ const handleOrganisationChange = useCallback2(async (orgId) => {
1011
+ if (disabled || isLoading) return;
1012
+ setSwitchError(null);
1013
+ setIsLoading(true);
1014
+ try {
1015
+ if (!validateOrganisationAccess(orgId)) {
1016
+ throw new Error("You do not have access to this organisation");
1017
+ }
1018
+ await switchOrganisation(orgId);
1019
+ const newOrganisation = organisations.find((org) => org.id === orgId);
1020
+ if (newOrganisation && onOrganisationChange) {
1021
+ onOrganisationChange(newOrganisation);
1022
+ }
1023
+ logger.debug("OrganisationSelector", "Successfully switched to organisation:", orgId);
1024
+ } catch (error) {
1025
+ logger.error("OrganisationSelector", "Failed to switch organisation:", error);
1026
+ setSwitchError(error instanceof Error ? error.message : "Failed to switch organisation");
1027
+ } finally {
1028
+ setIsLoading(false);
1029
+ }
1030
+ }, [
1031
+ disabled,
1032
+ isLoading,
1033
+ validateOrganisationAccess,
1034
+ switchOrganisation,
1035
+ organisations,
1036
+ onOrganisationChange
1037
+ ]);
1038
+ const handleRetry = useCallback2(async () => {
1039
+ setIsLoading(true);
1040
+ setSwitchError(null);
1041
+ try {
1042
+ await refreshOrganisations();
1043
+ } catch (error) {
1044
+ logger.error("OrganisationSelector", "Failed to refresh organisations:", error);
1045
+ setSwitchError("Failed to refresh organisations");
1046
+ } finally {
1047
+ setIsLoading(false);
1048
+ }
1049
+ }, [refreshOrganisations]);
1050
+ if (orgLoading) {
1051
+ return /* @__PURE__ */ jsxs6("div", { className: `flex items-center gap-2 ${className}`, children: [
1052
+ /* @__PURE__ */ jsx12(LoadingSpinner, { size: "sm" }),
1053
+ /* @__PURE__ */ jsx12("span", { className: "text-sm text-muted-foreground", children: compact ? "Loading..." : "Loading organisations..." })
1054
+ ] });
1055
+ }
1056
+ if (orgError) {
1057
+ return /* @__PURE__ */ jsxs6("div", { className: `space-y-2 ${className}`, children: [
1058
+ /* @__PURE__ */ jsxs6(Alert, { variant: "destructive", children: [
1059
+ /* @__PURE__ */ jsx12(AlertCircle2, { className: "h-4 w-4" }),
1060
+ /* @__PURE__ */ jsxs6(AlertDescription, { children: [
1061
+ "Failed to load organisations: ",
1062
+ orgError.message
1063
+ ] })
1064
+ ] }),
1065
+ showRetryButton && /* @__PURE__ */ jsxs6(
1066
+ Button,
1067
+ {
1068
+ variant: "outline",
1069
+ size: "sm",
1070
+ onClick: handleRetry,
1071
+ disabled: isLoading,
1072
+ className: "w-full",
1073
+ children: [
1074
+ /* @__PURE__ */ jsx12(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
1075
+ "Retry"
1076
+ ]
1077
+ }
1078
+ )
1079
+ ] });
1080
+ }
1081
+ if (organisations.length === 0) {
1082
+ if (showNoOrganisationsMessage) {
1083
+ return /* @__PURE__ */ jsxs6("div", { className: `space-y-2 ${className}`, children: [
1084
+ /* @__PURE__ */ jsxs6(Alert, { children: [
1085
+ /* @__PURE__ */ jsx12(Building2, { className: "h-4 w-4" }),
1086
+ /* @__PURE__ */ jsx12(AlertDescription, { children: "No organisations available. Please contact your administrator to be added to an organisation." })
1087
+ ] }),
1088
+ showRetryButton && /* @__PURE__ */ jsxs6(
1089
+ Button,
1090
+ {
1091
+ variant: "outline",
1092
+ size: "sm",
1093
+ onClick: handleRetry,
1094
+ disabled: isLoading,
1095
+ className: "w-full",
1096
+ children: [
1097
+ /* @__PURE__ */ jsx12(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
1098
+ "Check Again"
1099
+ ]
1100
+ }
1101
+ )
1102
+ ] });
1103
+ }
1104
+ return null;
1105
+ }
1106
+ const switchErrorDisplay = switchError && /* @__PURE__ */ jsxs6(Alert, { variant: "destructive", className: "mt-2", children: [
1107
+ /* @__PURE__ */ jsx12(AlertCircle2, { className: "h-4 w-4" }),
1108
+ /* @__PURE__ */ jsx12(AlertDescription, { children: switchError })
1109
+ ] });
1110
+ return /* @__PURE__ */ jsxs6("div", { className: `space-y-2 ${className}`, children: [
1111
+ /* @__PURE__ */ jsxs6(
1112
+ Select,
1113
+ {
1114
+ value: selectedOrganisation?.id || "",
1115
+ onValueChange: handleOrganisationChange,
1116
+ disabled: disabled || isLoading || !selectedOrganisation,
1117
+ children: [
1118
+ /* @__PURE__ */ jsx12(SelectTrigger, { className: `${isLoading ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
1119
+ isLoading ? /* @__PURE__ */ jsx12(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx12(Building2, { className: "h-4 w-4 text-muted-foreground" }),
1120
+ /* @__PURE__ */ jsx12(SelectValue, { placeholder })
1121
+ ] }) }),
1122
+ /* @__PURE__ */ jsx12(SelectContent, { children: organisations.map((org) => {
1123
+ const userRole = getUserRole(org.id);
1124
+ const hasAccess = validateOrganisationAccess(org.id);
1125
+ return /* @__PURE__ */ jsx12(
1126
+ SelectItem,
1127
+ {
1128
+ value: org.id,
1129
+ disabled: !hasAccess,
1130
+ className: !hasAccess ? "opacity-50" : "",
1131
+ children: /* @__PURE__ */ jsxs6("div", { className: "flex items-center justify-between w-full", children: [
1132
+ /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-2", children: [
1133
+ /* @__PURE__ */ jsx12(Building2, { className: "h-4 w-4" }),
1134
+ /* @__PURE__ */ jsxs6("div", { className: "flex flex-col", children: [
1135
+ /* @__PURE__ */ jsx12("span", { className: "font-medium", children: org.display_name }),
1136
+ !compact && org.description && /* @__PURE__ */ jsx12("span", { className: "text-xs text-muted-foreground truncate max-w-40", children: org.description })
1137
+ ] })
1138
+ ] }),
1139
+ showRole && /* @__PURE__ */ jsxs6("div", { className: "flex items-center gap-1 ml-4", children: [
1140
+ /* @__PURE__ */ jsx12(Shield, { className: "h-3 w-3 text-muted-foreground" }),
1141
+ /* @__PURE__ */ jsx12("span", { className: "text-xs text-muted-foreground capitalize", children: userRole?.replace("_", " ") || "No Role" })
1142
+ ] })
1143
+ ] })
1144
+ },
1145
+ org.id
1146
+ );
1147
+ }) })
1148
+ ]
1149
+ }
1150
+ ),
1151
+ switchErrorDisplay
1152
+ ] });
1153
+ }
1154
+
1155
+ // src/components/PasswordChange/PasswordChangeForm.tsx
1156
+ import { useState as useState3 } from "react";
1157
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
986
1158
  function PasswordChangeForm({ onSubmit, className }) {
987
- const [newPassword, setNewPassword] = useState2("");
988
- const [confirmPassword, setConfirmPassword] = useState2("");
989
- const [error, setError] = useState2(null);
990
- const [isSubmitting, setIsSubmitting] = useState2(false);
1159
+ const [newPassword, setNewPassword] = useState3("");
1160
+ const [confirmPassword, setConfirmPassword] = useState3("");
1161
+ const [error, setError] = useState3(null);
1162
+ const [isSubmitting, setIsSubmitting] = useState3(false);
991
1163
  const handleSubmit = async (e) => {
992
1164
  e.preventDefault();
993
1165
  setError(null);
@@ -1012,11 +1184,11 @@ function PasswordChangeForm({ onSubmit, className }) {
1012
1184
  setIsSubmitting(false);
1013
1185
  }
1014
1186
  };
1015
- return /* @__PURE__ */ jsxs6("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
1016
- error && /* @__PURE__ */ jsx12("div", { role: "alert", children: error }),
1017
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1018
- /* @__PURE__ */ jsx12(Label, { htmlFor: "new-password", children: "New Password" }),
1019
- /* @__PURE__ */ jsx12(
1187
+ return /* @__PURE__ */ jsxs7("form", { onSubmit: handleSubmit, className: cn("space-y-4", className), children: [
1188
+ error && /* @__PURE__ */ jsx13("div", { role: "alert", children: error }),
1189
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1190
+ /* @__PURE__ */ jsx13(Label, { htmlFor: "new-password", children: "New Password" }),
1191
+ /* @__PURE__ */ jsx13(
1020
1192
  Input,
1021
1193
  {
1022
1194
  id: "new-password",
@@ -1028,9 +1200,9 @@ function PasswordChangeForm({ onSubmit, className }) {
1028
1200
  }
1029
1201
  )
1030
1202
  ] }),
1031
- /* @__PURE__ */ jsxs6("div", { className: "space-y-2", children: [
1032
- /* @__PURE__ */ jsx12(Label, { htmlFor: "confirm-password", children: "Confirm Password" }),
1033
- /* @__PURE__ */ jsx12(
1203
+ /* @__PURE__ */ jsxs7("div", { className: "space-y-2", children: [
1204
+ /* @__PURE__ */ jsx13(Label, { htmlFor: "confirm-password", children: "Confirm Password" }),
1205
+ /* @__PURE__ */ jsx13(
1034
1206
  Input,
1035
1207
  {
1036
1208
  id: "confirm-password",
@@ -1042,7 +1214,7 @@ function PasswordChangeForm({ onSubmit, className }) {
1042
1214
  }
1043
1215
  )
1044
1216
  ] }),
1045
- /* @__PURE__ */ jsx12(
1217
+ /* @__PURE__ */ jsx13(
1046
1218
  Button,
1047
1219
  {
1048
1220
  type: "submit",
@@ -1055,17 +1227,17 @@ function PasswordChangeForm({ onSubmit, className }) {
1055
1227
  }
1056
1228
 
1057
1229
  // src/components/UserMenu/UserMenu.tsx
1058
- import React11, { useCallback as useCallback2, useMemo as useMemo3, useState as useState3 } from "react";
1230
+ import React12, { useCallback as useCallback3, useMemo as useMemo3, useState as useState4 } from "react";
1059
1231
  import { ChevronDown, LogOut, KeyRound } from "lucide-react";
1060
- import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1061
- var UserMenu = React11.memo(function UserMenu2({
1232
+ import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1233
+ var UserMenu = React12.memo(function UserMenu2({
1062
1234
  user,
1063
1235
  onSignOut,
1064
1236
  onChangePassword,
1065
1237
  className,
1066
1238
  showAvatar = true
1067
1239
  }) {
1068
- const [isPasswordDialogOpen, setPasswordDialogOpen] = useState3(false);
1240
+ const [isPasswordDialogOpen, setPasswordDialogOpen] = useState4(false);
1069
1241
  const userInfo = useMemo3(() => {
1070
1242
  if (!user) return null;
1071
1243
  return {
@@ -1075,42 +1247,42 @@ var UserMenu = React11.memo(function UserMenu2({
1075
1247
  initial: (user.user_metadata?.display_name || user.user_metadata?.full_name || user.email || "U").charAt(0).toUpperCase()
1076
1248
  };
1077
1249
  }, [user]);
1078
- const handleSignOut = useCallback2(async () => {
1250
+ const handleSignOut = useCallback3(async () => {
1079
1251
  if (onSignOut) await onSignOut();
1080
1252
  }, [onSignOut]);
1081
1253
  if (!user || !userInfo) {
1082
1254
  return null;
1083
1255
  }
1084
- return /* @__PURE__ */ jsxs7(Dialog, { open: isPasswordDialogOpen, onOpenChange: setPasswordDialogOpen, children: [
1085
- /* @__PURE__ */ jsxs7(Select, { className, children: [
1086
- /* @__PURE__ */ jsx13(SelectTrigger, { asChild: true, children: /* @__PURE__ */ jsxs7(Button, { variant: "outline", className: "flex items-center gap-2", "aria-label": userInfo.displayName, children: [
1087
- showAvatar && /* @__PURE__ */ jsxs7(Avatar, { className: "size-7", children: [
1088
- /* @__PURE__ */ jsx13(AvatarImage, { src: userInfo.avatarUrl, alt: userInfo.displayName }),
1089
- /* @__PURE__ */ jsx13(AvatarFallback, { children: userInfo.initial })
1256
+ return /* @__PURE__ */ jsxs8(Dialog, { open: isPasswordDialogOpen, onOpenChange: setPasswordDialogOpen, children: [
1257
+ /* @__PURE__ */ jsxs8(Select, { className, children: [
1258
+ /* @__PURE__ */ jsx14(SelectTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(Button, { variant: "outline", className: "flex items-center gap-2", "aria-label": userInfo.displayName, children: [
1259
+ showAvatar && /* @__PURE__ */ jsxs8(Avatar, { className: "size-7", children: [
1260
+ /* @__PURE__ */ jsx14(AvatarImage, { src: userInfo.avatarUrl, alt: userInfo.displayName }),
1261
+ /* @__PURE__ */ jsx14(AvatarFallback, { children: userInfo.initial })
1090
1262
  ] }),
1091
- /* @__PURE__ */ jsx13("span", { children: userInfo.displayName }),
1092
- /* @__PURE__ */ jsx13(ChevronDown, { className: "h-4 w-4" })
1263
+ /* @__PURE__ */ jsx14("span", { children: userInfo.displayName }),
1264
+ /* @__PURE__ */ jsx14(ChevronDown, { className: "h-4 w-4" })
1093
1265
  ] }) }),
1094
- /* @__PURE__ */ jsxs7(SelectContent, { children: [
1095
- /* @__PURE__ */ jsx13(SelectLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs7("div", { className: "flex flex-col space-y-1", children: [
1096
- /* @__PURE__ */ jsx13("p", { className: "font-medium", children: userInfo.displayName }),
1097
- /* @__PURE__ */ jsx13("p", { className: "text-muted-foreground", children: userInfo.email })
1266
+ /* @__PURE__ */ jsxs8(SelectContent, { children: [
1267
+ /* @__PURE__ */ jsx14(SelectLabel, { className: "font-normal", children: /* @__PURE__ */ jsxs8("div", { className: "flex flex-col space-y-1", children: [
1268
+ /* @__PURE__ */ jsx14("p", { className: "font-medium", children: userInfo.displayName }),
1269
+ /* @__PURE__ */ jsx14("p", { className: "text-muted-foreground", children: userInfo.email })
1098
1270
  ] }) }),
1099
- /* @__PURE__ */ jsx13(SelectSeparator, {}),
1100
- /* @__PURE__ */ jsx13(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs7(SelectItem, { value: "change-password", children: [
1101
- /* @__PURE__ */ jsx13(KeyRound, { className: "mr-2 h-4 w-4" }),
1102
- /* @__PURE__ */ jsx13("span", { children: "Change Password" })
1271
+ /* @__PURE__ */ jsx14(SelectSeparator, {}),
1272
+ /* @__PURE__ */ jsx14(DialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(SelectItem, { value: "change-password", children: [
1273
+ /* @__PURE__ */ jsx14(KeyRound, { className: "mr-2 h-4 w-4" }),
1274
+ /* @__PURE__ */ jsx14("span", { children: "Change Password" })
1103
1275
  ] }) }),
1104
- /* @__PURE__ */ jsxs7(SelectItem, { value: "sign-out", onClick: handleSignOut, children: [
1105
- /* @__PURE__ */ jsx13(LogOut, { className: "mr-2 h-4 w-4" }),
1106
- /* @__PURE__ */ jsx13("span", { children: "Sign out" })
1276
+ /* @__PURE__ */ jsxs8(SelectItem, { value: "sign-out", onClick: handleSignOut, children: [
1277
+ /* @__PURE__ */ jsx14(LogOut, { className: "mr-2 h-4 w-4" }),
1278
+ /* @__PURE__ */ jsx14("span", { children: "Sign out" })
1107
1279
  ] })
1108
1280
  ] })
1109
1281
  ] }),
1110
- /* @__PURE__ */ jsx13(DialogOverlay, {}),
1111
- /* @__PURE__ */ jsxs7(DialogContent, { className, children: [
1112
- /* @__PURE__ */ jsx13(DialogHeader, { children: /* @__PURE__ */ jsx13(DialogTitle, { children: "Change Password" }) }),
1113
- /* @__PURE__ */ jsx13(
1282
+ /* @__PURE__ */ jsx14(DialogOverlay, {}),
1283
+ /* @__PURE__ */ jsxs8(DialogContent, { className, children: [
1284
+ /* @__PURE__ */ jsx14(DialogHeader, { children: /* @__PURE__ */ jsx14(DialogTitle, { children: "Change Password" }) }),
1285
+ /* @__PURE__ */ jsx14(
1114
1286
  PasswordChangeForm,
1115
1287
  {
1116
1288
  onSubmit: async ({ newPassword, confirmPassword }) => {
@@ -1128,31 +1300,31 @@ var UserMenu = React11.memo(function UserMenu2({
1128
1300
  ] })
1129
1301
  ] });
1130
1302
  });
1131
- var UserMenuLoading = React11.memo(function UserMenuLoading2() {
1132
- return /* @__PURE__ */ jsxs7("div", { className: "relative inline-block text-left", children: [
1133
- /* @__PURE__ */ jsxs7(
1303
+ var UserMenuLoading = React12.memo(function UserMenuLoading2() {
1304
+ return /* @__PURE__ */ jsxs8("div", { className: "relative inline-block text-left", children: [
1305
+ /* @__PURE__ */ jsxs8(
1134
1306
  "button",
1135
1307
  {
1136
1308
  type: "button",
1137
1309
  disabled: true,
1138
1310
  className: "flex items-center space-x-2 px-3 py-2 text-sm font-medium text-muted-foreground bg-muted border border-input rounded-md",
1139
1311
  children: [
1140
- /* @__PURE__ */ jsx13("div", { className: "w-6 h-6 rounded-full bg-muted animate-pulse" }),
1141
- /* @__PURE__ */ jsx13("span", { className: "truncate max-w-[150px]", children: "Loading..." }),
1142
- /* @__PURE__ */ jsx13(ChevronDown, { className: "w-4 h-4 text-muted-foreground" })
1312
+ /* @__PURE__ */ jsx14("div", { className: "w-6 h-6 rounded-full bg-muted animate-pulse" }),
1313
+ /* @__PURE__ */ jsx14("span", { className: "truncate max-w-[150px]", children: "Loading..." }),
1314
+ /* @__PURE__ */ jsx14(ChevronDown, { className: "w-4 h-4 text-muted-foreground" })
1143
1315
  ]
1144
1316
  }
1145
1317
  ),
1146
- /* @__PURE__ */ jsx13("div", { role: "status", "aria-label": "Loading user menu", "aria-live": "polite", className: "w-6 h-6 rounded-full bg-muted animate-pulse" })
1318
+ /* @__PURE__ */ jsx14("div", { role: "status", "aria-label": "Loading user menu", "aria-live": "polite", className: "w-6 h-6 rounded-full bg-muted animate-pulse" })
1147
1319
  ] });
1148
1320
  });
1149
1321
  UserMenu.Loading = UserMenuLoading;
1150
1322
 
1151
1323
  // src/components/NavigationMenu/NavigationMenu.tsx
1152
- import * as React12 from "react";
1324
+ import * as React13 from "react";
1153
1325
  import { ChevronDown as ChevronDown2 } from "lucide-react";
1154
- import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1155
- var NavigationMenu = React12.forwardRef(({
1326
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1327
+ var NavigationMenu = React13.forwardRef(({
1156
1328
  items,
1157
1329
  mode = "dropdown",
1158
1330
  currentPath,
@@ -1170,8 +1342,8 @@ var NavigationMenu = React12.forwardRef(({
1170
1342
  itemsPreFiltered = false,
1171
1343
  ...props
1172
1344
  }, ref) => {
1173
- const [expandedItems, setExpandedItems] = React12.useState(/* @__PURE__ */ new Set());
1174
- const buttonRef = React12.useRef(null);
1345
+ const [expandedItems, setExpandedItems] = React13.useState(/* @__PURE__ */ new Set());
1346
+ const buttonRef = React13.useRef(null);
1175
1347
  let authContext = null;
1176
1348
  try {
1177
1349
  authContext = useUnifiedAuth();
@@ -1196,15 +1368,15 @@ var NavigationMenu = React12.forwardRef(({
1196
1368
  selectedOrganisationId: itemsPreFiltered ? null : selectedOrganisation?.id || null,
1197
1369
  selectedEventId: itemsPreFiltered ? null : selectedEvent?.event_id || null
1198
1370
  });
1199
- const [resolvedAppId, setResolvedAppId] = React12.useState(void 0);
1200
- React12.useEffect(() => {
1371
+ const [resolvedAppId, setResolvedAppId] = React13.useState(void 0);
1372
+ React13.useEffect(() => {
1201
1373
  if (!scopeLoading && !resolvedScope?.appId && selectedOrganisation?.id && authContext?.appName && authContext?.user?.id && !resolvedAppId) {
1202
1374
  if (!authContext.user || !authContext.appName) {
1203
1375
  return;
1204
1376
  }
1205
1377
  const userId2 = authContext.user.id;
1206
1378
  const appName = authContext.appName;
1207
- import("./api-ROMBCNKU.js").then(({ resolveAppContext }) => {
1379
+ import("./api-BMFCXVQX.js").then(({ resolveAppContext }) => {
1208
1380
  resolveAppContext({
1209
1381
  userId: userId2,
1210
1382
  appName
@@ -1218,7 +1390,7 @@ var NavigationMenu = React12.forwardRef(({
1218
1390
  });
1219
1391
  }
1220
1392
  }, [scopeLoading, resolvedScope?.appId, selectedOrganisation?.id, authContext?.appName, authContext?.user?.id, resolvedAppId]);
1221
- const effectiveScope = React12.useMemo(() => {
1393
+ const effectiveScope = React13.useMemo(() => {
1222
1394
  if (resolvedScope?.organisationId) {
1223
1395
  return resolvedScope;
1224
1396
  }
@@ -1233,7 +1405,7 @@ var NavigationMenu = React12.forwardRef(({
1233
1405
  return null;
1234
1406
  }, [resolvedScope, selectedOrganisation?.id, selectedEvent?.event_id, resolvedAppId]);
1235
1407
  const scopeKey = effectiveScope ? `${effectiveScope.organisationId || ""}-${effectiveScope.eventId || ""}-${effectiveScope.appId || ""}` : "empty";
1236
- const stableScope = React12.useMemo(() => {
1408
+ const stableScope = React13.useMemo(() => {
1237
1409
  if (effectiveScope?.organisationId) {
1238
1410
  return {
1239
1411
  organisationId: effectiveScope.organisationId,
@@ -1258,8 +1430,8 @@ var NavigationMenu = React12.forwardRef(({
1258
1430
  itemsPreFiltered ? void 0 : stableScope.appId
1259
1431
  // Skip if pre-filtered
1260
1432
  );
1261
- const previousFilteredItemsRef = React12.useRef([]);
1262
- const filteredItems = React12.useMemo(() => {
1433
+ const previousFilteredItemsRef = React13.useRef([]);
1434
+ const filteredItems = React13.useMemo(() => {
1263
1435
  if (itemsPreFiltered && items && items.length > 0) {
1264
1436
  const visibleItems = (items || []).filter((item) => !item.meta?.hidden);
1265
1437
  previousFilteredItemsRef.current = visibleItems;
@@ -1555,8 +1727,8 @@ var NavigationMenu = React12.forwardRef(({
1555
1727
  const hasChildren = item.children && item.children.length > 0;
1556
1728
  const isExpanded = expandedItems.has(item.id);
1557
1729
  const itemIsActive = isActiveItem(item);
1558
- return /* @__PURE__ */ jsx14("li", { role: "none", children: hasChildren ? /* @__PURE__ */ jsxs8("div", { children: [
1559
- /* @__PURE__ */ jsxs8(
1730
+ return /* @__PURE__ */ jsx15("li", { role: "none", children: hasChildren ? /* @__PURE__ */ jsxs9("div", { children: [
1731
+ /* @__PURE__ */ jsxs9(
1560
1732
  "button",
1561
1733
  {
1562
1734
  onClick: () => toggleExpanded(item.id),
@@ -1565,21 +1737,21 @@ var NavigationMenu = React12.forwardRef(({
1565
1737
  "aria-controls": `submenu-${item.id}`,
1566
1738
  "aria-current": itemIsActive ? "page" : void 0,
1567
1739
  children: [
1568
- /* @__PURE__ */ jsx14("span", { children: item.label }),
1569
- /* @__PURE__ */ jsx14(ChevronDown2, { "aria-hidden": "true" })
1740
+ /* @__PURE__ */ jsx15("span", { children: item.label }),
1741
+ /* @__PURE__ */ jsx15(ChevronDown2, { "aria-hidden": "true" })
1570
1742
  ]
1571
1743
  }
1572
1744
  ),
1573
- isExpanded && item.children && /* @__PURE__ */ jsx14(
1745
+ isExpanded && item.children && /* @__PURE__ */ jsx15(
1574
1746
  "ul",
1575
1747
  {
1576
1748
  id: `submenu-${item.id}`,
1577
1749
  role: "menu",
1578
1750
  "aria-label": `${item.label} submenu`,
1579
- children: item.children.map((child) => /* @__PURE__ */ jsx14(React12.Fragment, { children: renderHierarchicalItem(child, level + 1) }, child.id))
1751
+ children: item.children.map((child) => /* @__PURE__ */ jsx15(React13.Fragment, { children: renderHierarchicalItem(child, level + 1) }, child.id))
1580
1752
  }
1581
1753
  )
1582
- ] }) : /* @__PURE__ */ jsx14(
1754
+ ] }) : /* @__PURE__ */ jsx15(
1583
1755
  "a",
1584
1756
  {
1585
1757
  href: item.href || "#",
@@ -1597,26 +1769,26 @@ var NavigationMenu = React12.forwardRef(({
1597
1769
  ) });
1598
1770
  };
1599
1771
  if (mode === "dropdown") {
1600
- return /* @__PURE__ */ jsxs8(
1772
+ return /* @__PURE__ */ jsxs9(
1601
1773
  Select,
1602
1774
  {
1603
1775
  onValueChange: handleNavigationSelect,
1604
1776
  className,
1605
1777
  "data-testid": "navigation-menu-root",
1606
1778
  children: [
1607
- /* @__PURE__ */ jsx14(
1779
+ /* @__PURE__ */ jsx15(
1608
1780
  SelectTrigger,
1609
1781
  {
1610
1782
  ref: buttonRef,
1611
1783
  disabled,
1612
1784
  "aria-label": buttonText,
1613
1785
  "data-testid": "navigation-menu-trigger",
1614
- children: /* @__PURE__ */ jsx14(SelectValue, { placeholder: buttonText })
1786
+ children: /* @__PURE__ */ jsx15(SelectValue, { placeholder: buttonText })
1615
1787
  }
1616
1788
  ),
1617
- /* @__PURE__ */ jsx14(SelectContent, { children: filteredItems.map((item) => {
1789
+ /* @__PURE__ */ jsx15(SelectContent, { children: filteredItems.map((item) => {
1618
1790
  const isActive = isActiveItem(item);
1619
- return /* @__PURE__ */ jsx14(
1791
+ return /* @__PURE__ */ jsx15(
1620
1792
  SelectItem,
1621
1793
  {
1622
1794
  value: item.id,
@@ -1631,14 +1803,14 @@ var NavigationMenu = React12.forwardRef(({
1631
1803
  }
1632
1804
  );
1633
1805
  }
1634
- return /* @__PURE__ */ jsx14(
1806
+ return /* @__PURE__ */ jsx15(
1635
1807
  "nav",
1636
1808
  {
1637
1809
  ref,
1638
1810
  className,
1639
1811
  "aria-label": navigationLabel,
1640
1812
  ...props,
1641
- children: /* @__PURE__ */ jsx14("ul", { role: "menubar", children: filteredItems.map((item) => /* @__PURE__ */ jsx14(React12.Fragment, { children: renderHierarchicalItem(item, 0) }, item.id)) })
1813
+ children: /* @__PURE__ */ jsx15("ul", { role: "menubar", children: filteredItems.map((item) => /* @__PURE__ */ jsx15(React13.Fragment, { children: renderHierarchicalItem(item, 0) }, item.id)) })
1642
1814
  }
1643
1815
  );
1644
1816
  });
@@ -1646,7 +1818,7 @@ NavigationMenu.displayName = "NavigationMenu";
1646
1818
 
1647
1819
  // src/components/Header/Header.tsx
1648
1820
  import { Link } from "react-router-dom";
1649
- import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1821
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1650
1822
  function Header({
1651
1823
  logoUrl,
1652
1824
  logoAlt = "Logo",
@@ -1659,37 +1831,38 @@ function Header({
1659
1831
  userMenu,
1660
1832
  className,
1661
1833
  showEventSelector = true,
1834
+ showOrgSelector = false,
1662
1835
  showUserMenu = true,
1663
1836
  currentPath,
1664
1837
  onNavigate,
1665
1838
  logoHref
1666
1839
  }) {
1667
- return /* @__PURE__ */ jsx15("header", { className: cn(
1840
+ return /* @__PURE__ */ jsx16("header", { className: cn(
1668
1841
  "w-full border-b border-main-200 h-16 shadow-sm bg-main-100 ",
1669
1842
  className
1670
- ), role: "banner", children: /* @__PURE__ */ jsxs9("nav", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto grid grid-cols-[auto_auto_1fr_auto] gap-4 h-full items-center", children: [
1671
- logo ? logoHref ? /* @__PURE__ */ jsx15(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: logo }) : logo : logoUrl ? logoHref ? /* @__PURE__ */ jsx15(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: /* @__PURE__ */ jsx15(
1843
+ ), role: "banner", children: /* @__PURE__ */ jsxs10("nav", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto flex items-center gap-4 h-full", children: [
1844
+ logo ? logoHref ? /* @__PURE__ */ jsx16(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: logo }) : logo : logoUrl ? logoHref ? /* @__PURE__ */ jsx16(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: /* @__PURE__ */ jsx16(
1672
1845
  "img",
1673
1846
  {
1674
1847
  src: logoUrl,
1675
1848
  alt: logoAlt || "Logo",
1676
1849
  className: "h-[2.15rem] w-auto max-w-[200px] object-contain rounded-md shadow-md bg-transparent"
1677
1850
  }
1678
- ) }) : /* @__PURE__ */ jsx15(
1851
+ ) }) : /* @__PURE__ */ jsx16(
1679
1852
  "img",
1680
1853
  {
1681
1854
  src: logoUrl,
1682
1855
  alt: logoAlt || "Logo",
1683
1856
  className: "h-[2.15rem] w-auto max-w-[200px] object-contain rounded-md shadow-md bg-transparent"
1684
1857
  }
1685
- ) : logoHref ? /* @__PURE__ */ jsx15(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: /* @__PURE__ */ jsx15(
1858
+ ) : logoHref ? /* @__PURE__ */ jsx16(Link, { to: logoHref, className: "cursor-pointer hover:opacity-80 transition-opacity", children: /* @__PURE__ */ jsx16(
1686
1859
  "img",
1687
1860
  {
1688
1861
  src: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23000'/%3E%3Ctext x='16' y='20' text-anchor='middle' fill='white' font-family='Arial' font-size='14' font-weight='bold'%3EL%3C/text%3E%3C/svg%3E",
1689
1862
  alt: logoAlt || "Logo",
1690
1863
  className: "h-8 w-8 shadow-md"
1691
1864
  }
1692
- ) }) : /* @__PURE__ */ jsx15(
1865
+ ) }) : /* @__PURE__ */ jsx16(
1693
1866
  "img",
1694
1867
  {
1695
1868
  src: "data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%23000'/%3E%3Ctext x='16' y='20' text-anchor='middle' fill='white' font-family='Arial' font-size='14' font-weight='bold'%3EL%3C/text%3E%3C/svg%3E",
@@ -1697,7 +1870,7 @@ function Header({
1697
1870
  className: "h-8 w-8 shadow-md"
1698
1871
  }
1699
1872
  ),
1700
- navItems && navItems.length > 0 && /* @__PURE__ */ jsx15(
1873
+ navItems && navItems.length > 0 && /* @__PURE__ */ jsx16(
1701
1874
  NavigationMenu,
1702
1875
  {
1703
1876
  items: navItems,
@@ -1708,30 +1881,41 @@ function Header({
1708
1881
  itemsPreFiltered: true
1709
1882
  }
1710
1883
  ),
1711
- showEventSelector ? /* @__PURE__ */ jsx15(
1712
- EventSelector,
1713
- {
1714
- placeholder: "Select event",
1715
- className: "justify-self-end w-96",
1716
- "data-testid": "event-selector"
1717
- }
1718
- ) : /* @__PURE__ */ jsx15("del", { className: "justify-self-end invisible", children: "Event Selector N/A" }),
1719
- actions,
1720
- showUserMenu && (userMenu ? userMenu : /* @__PURE__ */ jsx15(
1721
- UserMenu,
1722
- {
1723
- user: user || null,
1724
- onSignOut,
1725
- onChangePassword,
1726
- className: "w-70"
1727
- }
1728
- ))
1884
+ /* @__PURE__ */ jsxs10("div", { className: "flex items-center gap-4 ml-auto", children: [
1885
+ showOrgSelector ? /* @__PURE__ */ jsx16(
1886
+ OrganisationSelector,
1887
+ {
1888
+ placeholder: "Select organisation",
1889
+ className: "w-64",
1890
+ "data-testid": "org-selector",
1891
+ compact: true
1892
+ }
1893
+ ) : null,
1894
+ showEventSelector ? /* @__PURE__ */ jsx16(
1895
+ EventSelector,
1896
+ {
1897
+ placeholder: "Select event",
1898
+ className: "w-96",
1899
+ "data-testid": "event-selector"
1900
+ }
1901
+ ) : null,
1902
+ actions,
1903
+ showUserMenu && (userMenu ? userMenu : /* @__PURE__ */ jsx16(
1904
+ UserMenu,
1905
+ {
1906
+ user: user || null,
1907
+ onSignOut,
1908
+ onChangePassword,
1909
+ className: "w-70"
1910
+ }
1911
+ ))
1912
+ ] })
1729
1913
  ] }) });
1730
1914
  }
1731
1915
 
1732
1916
  // src/components/Footer/Footer.tsx
1733
- import React13 from "react";
1734
- import { Fragment as Fragment3, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1917
+ import React14 from "react";
1918
+ import { Fragment as Fragment3, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
1735
1919
  var FooterComponent = ({
1736
1920
  companyName = "Solvera Solutions Pty Ltd",
1737
1921
  year = (/* @__PURE__ */ new Date()).getFullYear(),
@@ -1742,27 +1926,28 @@ var FooterComponent = ({
1742
1926
  children
1743
1927
  }) => {
1744
1928
  const copyrightText = copyright || `\xA9 Copyright 2022\u2013${year} all rights reserved, ${companyName}.`;
1745
- return /* @__PURE__ */ jsx16("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs10("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
1746
- logo && /* @__PURE__ */ jsx16("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
1747
- children && /* @__PURE__ */ jsx16(Fragment3, { children }),
1748
- /* @__PURE__ */ jsx16("span", { className: "text-muted-foreground", children: copyrightText }),
1749
- links && links.length > 0 && /* @__PURE__ */ jsx16("ul", { className: "flex gap-4 mt-2 md:mt-0", children: links.map((link, index) => /* @__PURE__ */ jsx16("li", { children: /* @__PURE__ */ jsx16("a", { href: link.href, className: "text-muted-foreground hover:text-foreground", children: link.label }) }, index)) })
1929
+ return /* @__PURE__ */ jsx17("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs11("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
1930
+ logo && /* @__PURE__ */ jsx17("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
1931
+ children && /* @__PURE__ */ jsx17(Fragment3, { children }),
1932
+ /* @__PURE__ */ jsx17("span", { className: "text-muted-foreground", children: copyrightText }),
1933
+ links && links.length > 0 && /* @__PURE__ */ jsx17("ul", { className: "flex gap-4 mt-2 md:mt-0", children: links.map((link, index) => /* @__PURE__ */ jsx17("li", { children: /* @__PURE__ */ jsx17("a", { href: link.href, className: "text-muted-foreground hover:text-foreground", children: link.label }) }, index)) })
1750
1934
  ] }) });
1751
1935
  };
1752
1936
  FooterComponent.displayName = "Footer";
1753
- var Footer = React13.memo(FooterComponent);
1937
+ var Footer = React14.memo(FooterComponent);
1754
1938
  Footer.displayName = "Footer";
1755
1939
 
1756
1940
  // src/components/PaceAppLayout/PaceAppLayout.tsx
1757
- import { useState as useState5, useEffect as useEffect3, useMemo as useMemo5 } from "react";
1941
+ import { useState as useState6, useEffect as useEffect3, useMemo as useMemo5 } from "react";
1758
1942
  import { Outlet, useNavigate, useLocation } from "react-router-dom";
1759
- import { Fragment as Fragment4, jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
1943
+ import { Fragment as Fragment4, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
1760
1944
  var EMPTY_PAGE_ID_MAPPING = {};
1761
1945
  var EMPTY_ROUTE_PERMISSIONS = {};
1762
1946
  function PaceAppLayout({
1763
1947
  appName,
1764
1948
  navItems,
1765
1949
  showEventSelector,
1950
+ showOrgSelector,
1766
1951
  headerActions,
1767
1952
  customLogo,
1768
1953
  logoHref = "/dashboard",
@@ -1849,8 +2034,8 @@ function PaceAppLayout({
1849
2034
  const permissionString = `${currentRoutePermission}:page.${currentPageId}`;
1850
2035
  return permissionString;
1851
2036
  }, [enforcePermissions, currentRoutePermission, currentPageId]);
1852
- const [isSuperAdminUser, setIsSuperAdminUser] = useState5(false);
1853
- const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState5(false);
2037
+ const [isSuperAdminUser, setIsSuperAdminUser] = useState6(false);
2038
+ const [isCheckingSuperAdmin, setIsCheckingSuperAdmin] = useState6(false);
1854
2039
  useEffect3(() => {
1855
2040
  const checkSuperAdminStatus = async () => {
1856
2041
  if (!user?.id) {
@@ -1904,7 +2089,7 @@ function PaceAppLayout({
1904
2089
  onPageAccessDenied(currentPageId, currentRoutePermission);
1905
2090
  }
1906
2091
  }, [enforcePermissions, can, isCheckingPermission, isCheckingSuperAdmin, isSuperAdminUser, currentPageId, currentRoutePermission, user?.id, strictMode, auditLog, onPageAccessDenied, onStrictModeViolation]);
1907
- const [filteredMenuItems, setFilteredMenuItems] = useState5(baseMenuItems);
2092
+ const [filteredMenuItems, setFilteredMenuItems] = useState6(baseMenuItems);
1908
2093
  useEffect3(() => {
1909
2094
  let isMounted = true;
1910
2095
  const filterItems = async () => {
@@ -1918,15 +2103,20 @@ function PaceAppLayout({
1918
2103
  const hasAppId = currentScope.appId || resolvedAppId;
1919
2104
  const hasOrganisationContext = currentScope.organisationId;
1920
2105
  const hasUser = !!user?.id;
1921
- if (hasUser && hasOrganisationContext) {
1922
- } else if (!hasUser || !hasOrganisationContext) {
2106
+ if (!hasUser) {
1923
2107
  if (isMounted) {
1924
- setFilteredMenuItems([]);
2108
+ setFilteredMenuItems(baseMenuItems);
2109
+ }
2110
+ return;
2111
+ }
2112
+ if (!hasOrganisationContext) {
2113
+ if (isMounted) {
2114
+ setFilteredMenuItems(baseMenuItems);
1925
2115
  }
1926
2116
  return;
1927
2117
  }
1928
2118
  try {
1929
- const { isSuperAdmin: isSuperAdmin2 } = await import("./api-ROMBCNKU.js");
2119
+ const { isSuperAdmin: isSuperAdmin2 } = await import("./api-BMFCXVQX.js");
1930
2120
  const isSuper = await isSuperAdmin2(user.id);
1931
2121
  if (isSuper) {
1932
2122
  if (isMounted) {
@@ -1940,14 +2130,8 @@ function PaceAppLayout({
1940
2130
  throw error;
1941
2131
  }
1942
2132
  }
1943
- if (!currentScope.organisationId) {
1944
- if (isMounted) {
1945
- setFilteredMenuItems(baseMenuItems);
1946
- }
1947
- return;
1948
- }
1949
2133
  try {
1950
- const { getPermissionMap } = await import("./api-ROMBCNKU.js");
2134
+ const { getPermissionMap } = await import("./api-BMFCXVQX.js");
1951
2135
  const permissionScope = {
1952
2136
  organisationId: currentScope.organisationId,
1953
2137
  eventId: currentScope.eventId,
@@ -1960,7 +2144,7 @@ function PaceAppLayout({
1960
2144
  });
1961
2145
  const filtered = baseMenuItems.map((item) => {
1962
2146
  if (!item.href) return { item, hasAccess: true };
1963
- const pageId = pageIdMapping[item.href] || item.href.slice(1) || "home";
2147
+ const pageId = pageIdMapping[item.href] || (item.href === "/" ? "dashboard" : item.href.slice(1)) || "dashboard";
1964
2148
  const permission = routePermissions[item.href] || defaultPermission;
1965
2149
  const fullPermission = permission.includes(":") ? permission : pageId ? `${permission}:page.${pageId}` : permission;
1966
2150
  const hasAccess = permissionMap["*"] === true || permissionMap[fullPermission] === true;
@@ -1980,7 +2164,7 @@ function PaceAppLayout({
1980
2164
  return () => {
1981
2165
  isMounted = false;
1982
2166
  };
1983
- }, [baseMenuItems, pageIdMapping, routePermissions, defaultPermission, can, user?.id, scope, scopeLoading, contextAppId, resolvedScope?.appId]);
2167
+ }, [baseMenuItems, pageIdMapping, routePermissions, defaultPermission, can, user?.id, scope, scopeLoading, contextAppId, resolvedScope?.appId, selectedOrganisation?.id]);
1984
2168
  useEffect3(() => {
1985
2169
  if (!roleBasedRouting || routeConfig.length === 0) return;
1986
2170
  let isMounted = true;
@@ -2003,7 +2187,7 @@ function PaceAppLayout({
2003
2187
  let hasAccess = true;
2004
2188
  if (currentRoute.pageId && currentRoute.permissions && currentRoute.permissions.length > 0) {
2005
2189
  try {
2006
- const { isPermittedCached } = await import("./api-ROMBCNKU.js");
2190
+ const { isPermittedCached } = await import("./api-BMFCXVQX.js");
2007
2191
  const hasPagePermission = await isPermittedCached({
2008
2192
  userId: user?.id || "",
2009
2193
  scope,
@@ -2019,7 +2203,7 @@ function PaceAppLayout({
2019
2203
  }
2020
2204
  }
2021
2205
  if (hasAccess && currentRoute.roles && currentRoute.roles.length > 0 && user?.id) {
2022
- const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-7F6T4B6K.js");
2206
+ const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-A4BCQRJY.js");
2023
2207
  hasAccess = true;
2024
2208
  }
2025
2209
  if (!isMounted) return;
@@ -2066,31 +2250,31 @@ function PaceAppLayout({
2066
2250
  return {};
2067
2251
  };
2068
2252
  if (enforcePermissions && (isCheckingSuperAdmin || isCheckingPermission)) {
2069
- return /* @__PURE__ */ jsx17("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs11("div", { className: "text-center", children: [
2070
- /* @__PURE__ */ jsx17("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-sec-900 mx-auto mb-4" }),
2071
- /* @__PURE__ */ jsx17("p", { className: "text-sec-600", children: "Checking permissions..." })
2253
+ return /* @__PURE__ */ jsx18("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs12("div", { className: "text-center", children: [
2254
+ /* @__PURE__ */ jsx18("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-sec-900 mx-auto mb-4" }),
2255
+ /* @__PURE__ */ jsx18("p", { className: "text-sec-600", children: "Checking permissions..." })
2072
2256
  ] }) });
2073
2257
  }
2074
2258
  if (enforcePermissions && permissionError && !isSuperAdminUser) {
2075
- return /* @__PURE__ */ jsx17("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs11("div", { className: "text-center", children: [
2076
- /* @__PURE__ */ jsx17("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Permission Error" }),
2077
- /* @__PURE__ */ jsx17("p", { className: "text-sec-600 mb-4", children: permissionError.message }),
2078
- /* @__PURE__ */ jsx17(Button, { onClick: () => navigate("/"), children: "Go Home" })
2259
+ return /* @__PURE__ */ jsx18("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs12("div", { className: "text-center", children: [
2260
+ /* @__PURE__ */ jsx18("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Permission Error" }),
2261
+ /* @__PURE__ */ jsx18("p", { className: "text-sec-600 mb-4", children: permissionError.message }),
2262
+ /* @__PURE__ */ jsx18(Button, { onClick: () => navigate("/"), children: "Go Home" })
2079
2263
  ] }) });
2080
2264
  }
2081
2265
  if (enforcePermissions && hasPermission === false && !isCheckingSuperAdmin && !isSuperAdminUser) {
2082
2266
  if (enforcePagePermissions && pagePermissionFallback) {
2083
- return /* @__PURE__ */ jsx17(Fragment4, { children: pagePermissionFallback });
2267
+ return /* @__PURE__ */ jsx18(Fragment4, { children: pagePermissionFallback });
2084
2268
  }
2085
2269
  if (permissionFallback) {
2086
- return /* @__PURE__ */ jsx17(Fragment4, { children: permissionFallback });
2270
+ return /* @__PURE__ */ jsx18(Fragment4, { children: permissionFallback });
2087
2271
  }
2088
- return /* @__PURE__ */ jsx17("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs11("div", { className: "text-center", children: [
2089
- /* @__PURE__ */ jsx17("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Access Denied" }),
2090
- /* @__PURE__ */ jsx17("p", { className: "text-sec-600 mb-4", children: "You don't have permission to access this page." }),
2091
- /* @__PURE__ */ jsxs11("div", { className: "flex gap-2 justify-center", children: [
2092
- /* @__PURE__ */ jsx17(Button, { onClick: () => navigate("/"), children: "Go Home" }),
2093
- /* @__PURE__ */ jsx17(
2272
+ return /* @__PURE__ */ jsx18("div", { className: "flex items-center justify-center min-h-screen", children: /* @__PURE__ */ jsxs12("div", { className: "text-center", children: [
2273
+ /* @__PURE__ */ jsx18("h2", { className: "text-xl font-semibold text-acc-600 mb-2", children: "Access Denied" }),
2274
+ /* @__PURE__ */ jsx18("p", { className: "text-sec-600 mb-4", children: "You don't have permission to access this page." }),
2275
+ /* @__PURE__ */ jsxs12("div", { className: "flex gap-2 justify-center", children: [
2276
+ /* @__PURE__ */ jsx18(Button, { onClick: () => navigate("/"), children: "Go Home" }),
2277
+ /* @__PURE__ */ jsx18(
2094
2278
  Button,
2095
2279
  {
2096
2280
  variant: "outline",
@@ -2104,8 +2288,8 @@ function PaceAppLayout({
2104
2288
  ] })
2105
2289
  ] }) });
2106
2290
  }
2107
- return /* @__PURE__ */ jsxs11(Fragment4, { children: [
2108
- /* @__PURE__ */ jsx17(
2291
+ return /* @__PURE__ */ jsxs12(Fragment4, { children: [
2292
+ /* @__PURE__ */ jsx18(
2109
2293
  Header,
2110
2294
  {
2111
2295
  logo: customLogo || void 0,
@@ -2125,19 +2309,20 @@ function PaceAppLayout({
2125
2309
  }
2126
2310
  },
2127
2311
  showEventSelector,
2312
+ showOrgSelector,
2128
2313
  showUserMenu,
2129
2314
  className: headerClassName || "sticky top-0 z-[40] w-full"
2130
2315
  }
2131
2316
  ),
2132
- /* @__PURE__ */ jsx17("main", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children: /* @__PURE__ */ jsx17(Outlet, {}) }),
2133
- /* @__PURE__ */ jsx17(Footer, {})
2317
+ /* @__PURE__ */ jsx18("main", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children: /* @__PURE__ */ jsx18(Outlet, {}) }),
2318
+ /* @__PURE__ */ jsx18(Footer, {})
2134
2319
  ] });
2135
2320
  }
2136
2321
 
2137
2322
  // src/components/PaceLoginPage/PaceLoginPage.tsx
2138
- import { useEffect as useEffect4, useState as useState6, useContext } from "react";
2323
+ import { useEffect as useEffect4, useState as useState7, useContext } from "react";
2139
2324
  import { useNavigate as useNavigate2, useLocation as useLocation2 } from "react-router-dom";
2140
- import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
2325
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
2141
2326
  var PaceLoginPage = ({
2142
2327
  appName = "Pace",
2143
2328
  onSuccessRedirectPath = "/",
@@ -2146,9 +2331,9 @@ var PaceLoginPage = ({
2146
2331
  const { signIn, isAuthenticated, isLoading, authError, user, supabase } = useUnifiedAuth();
2147
2332
  const navigate = useNavigate2();
2148
2333
  const location = useLocation2();
2149
- const [isSigningIn, setIsSigningIn] = useState6(false);
2150
- const [accessError, setAccessError] = useState6(null);
2151
- const [isCheckingAccess, setIsCheckingAccess] = useState6(false);
2334
+ const [isSigningIn, setIsSigningIn] = useState7(false);
2335
+ const [accessError, setAccessError] = useState7(null);
2336
+ const [isCheckingAccess, setIsCheckingAccess] = useState7(false);
2152
2337
  const eventServiceContext = useContext(EventServiceContext);
2153
2338
  const eventService = eventServiceContext?.eventService || null;
2154
2339
  useEffect4(() => {
@@ -2268,8 +2453,8 @@ var PaceLoginPage = ({
2268
2453
  setIsSigningIn(false);
2269
2454
  }
2270
2455
  };
2271
- return /* @__PURE__ */ jsxs12("main", { className: "min-h-screen grid mx-auto w-fit content-center justify-items-center gap-y-8", "aria-label": `${appName} Login Page`, children: [
2272
- /* @__PURE__ */ jsx18(
2456
+ return /* @__PURE__ */ jsxs13("main", { className: "min-h-screen grid mx-auto w-fit content-center justify-items-center gap-y-8", "aria-label": `${appName} Login Page`, children: [
2457
+ /* @__PURE__ */ jsx19(
2273
2458
  "img",
2274
2459
  {
2275
2460
  src: `/${appName.toLowerCase()}_logo_square.svg`,
@@ -2277,7 +2462,7 @@ var PaceLoginPage = ({
2277
2462
  className: "h-48"
2278
2463
  }
2279
2464
  ),
2280
- /* @__PURE__ */ jsx18(
2465
+ /* @__PURE__ */ jsx19(
2281
2466
  LoginForm,
2282
2467
  {
2283
2468
  className: "w-md",
@@ -2291,20 +2476,20 @@ var PaceLoginPage = ({
2291
2476
  ),
2292
2477
  (() => {
2293
2478
  const benign = !!(authError && (authError.name === "AuthSessionMissingError" || /Auth session missing/i.test(authError.message)));
2294
- return authError && !benign ? /* @__PURE__ */ jsx18("em", { className: "mt-4 text-destructive text-center", children: authError.message }) : null;
2479
+ return authError && !benign ? /* @__PURE__ */ jsx19("em", { className: "mt-4 text-destructive text-center", children: authError.message }) : null;
2295
2480
  })(),
2296
- accessError && /* @__PURE__ */ jsx18("em", { className: "mt-4 text-destructive text-center", children: accessError }),
2297
- isCheckingAccess && /* @__PURE__ */ jsx18("em", { className: "mt-4 text-muted-foreground text-center", children: "Checking permissions..." })
2481
+ accessError && /* @__PURE__ */ jsx19("em", { className: "mt-4 text-destructive text-center", children: accessError }),
2482
+ isCheckingAccess && /* @__PURE__ */ jsx19("em", { className: "mt-4 text-muted-foreground text-center", children: "Checking permissions..." })
2298
2483
  ] });
2299
2484
  };
2300
2485
 
2301
2486
  // src/components/SessionRestorationLoader/SessionRestorationLoader.tsx
2302
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
2487
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
2303
2488
  var SessionRestorationLoader = ({
2304
2489
  message = "Restoring session...",
2305
2490
  className
2306
2491
  }) => {
2307
- return /* @__PURE__ */ jsxs13(
2492
+ return /* @__PURE__ */ jsxs14(
2308
2493
  "div",
2309
2494
  {
2310
2495
  className: cn(
@@ -2315,27 +2500,91 @@ var SessionRestorationLoader = ({
2315
2500
  "aria-live": "polite",
2316
2501
  "aria-label": message,
2317
2502
  children: [
2318
- /* @__PURE__ */ jsx19(LoadingSpinner, { size: "lg" }),
2319
- /* @__PURE__ */ jsx19("div", { className: "text-sm text-sec-600", children: message })
2503
+ /* @__PURE__ */ jsx20(LoadingSpinner, { size: "lg" }),
2504
+ /* @__PURE__ */ jsx20("div", { className: "text-sm text-sec-600", children: message })
2320
2505
  ]
2321
2506
  }
2322
2507
  );
2323
2508
  };
2324
2509
 
2325
2510
  // src/components/ProtectedRoute/ProtectedRoute.tsx
2326
- import { useMemo as useMemo6 } from "react";
2511
+ import { useMemo as useMemo6, useEffect as useEffect5, useRef as useRef3, useState as useState8 } from "react";
2327
2512
  import { Navigate, Outlet as Outlet2 } from "react-router-dom";
2328
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
2513
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
2329
2514
  function ProtectedRoute({
2330
- requireEvent = true,
2515
+ requireEvent = false,
2331
2516
  allowSuperAdminBypass = false,
2332
2517
  noEventsFallback,
2333
2518
  loadingFallback,
2334
2519
  loginPath = "/login"
2335
2520
  }) {
2336
- const { isAuthenticated, authLoading } = useUnifiedAuth();
2337
- const { selectedEvent, events, isLoading: eventLoading } = useEvents();
2521
+ const { isAuthenticated, isLoading } = useUnifiedAuth();
2522
+ const eventsContext = useEvents();
2523
+ const selectedEvent = requireEvent ? eventsContext.selectedEvent : null;
2524
+ const events = requireEvent ? eventsContext.events || [] : [];
2525
+ const eventLoading = requireEvent ? eventsContext.isLoading || false : false;
2338
2526
  const sessionRestoration = useSessionRestoration();
2527
+ usePreventTabReload({ enabled: true, gracePeriodMs: 2e3 });
2528
+ const wasAuthenticatedRef = useRef3(false);
2529
+ const [shouldRedirect, setShouldRedirect] = useState8(false);
2530
+ const tabJustBecameVisibleRef = useRef3(false);
2531
+ useEffect5(() => {
2532
+ if (isAuthenticated) {
2533
+ wasAuthenticatedRef.current = true;
2534
+ setShouldRedirect(false);
2535
+ tabJustBecameVisibleRef.current = false;
2536
+ }
2537
+ }, [isAuthenticated]);
2538
+ useEffect5(() => {
2539
+ if (typeof document === "undefined") return;
2540
+ let timeoutId = null;
2541
+ let wasHidden = document.hidden;
2542
+ const handleVisibilityChange = () => {
2543
+ const isNowVisible = !document.hidden;
2544
+ if (isNowVisible && wasHidden) {
2545
+ if (!isAuthenticated && wasAuthenticatedRef.current) {
2546
+ tabJustBecameVisibleRef.current = true;
2547
+ setShouldRedirect(false);
2548
+ if (timeoutId) {
2549
+ clearTimeout(timeoutId);
2550
+ }
2551
+ timeoutId = setTimeout(() => {
2552
+ tabJustBecameVisibleRef.current = false;
2553
+ setShouldRedirect((prev) => {
2554
+ return prev;
2555
+ });
2556
+ }, 2e3);
2557
+ }
2558
+ } else if (!isNowVisible) {
2559
+ tabJustBecameVisibleRef.current = false;
2560
+ if (timeoutId) {
2561
+ clearTimeout(timeoutId);
2562
+ timeoutId = null;
2563
+ }
2564
+ }
2565
+ wasHidden = !isNowVisible;
2566
+ };
2567
+ if (!document.hidden && !isAuthenticated && wasAuthenticatedRef.current) {
2568
+ tabJustBecameVisibleRef.current = true;
2569
+ setShouldRedirect(false);
2570
+ timeoutId = setTimeout(() => {
2571
+ tabJustBecameVisibleRef.current = false;
2572
+ }, 2e3);
2573
+ }
2574
+ document.addEventListener("visibilitychange", handleVisibilityChange);
2575
+ return () => {
2576
+ document.removeEventListener("visibilitychange", handleVisibilityChange);
2577
+ if (timeoutId) {
2578
+ clearTimeout(timeoutId);
2579
+ }
2580
+ };
2581
+ }, [isAuthenticated]);
2582
+ useEffect5(() => {
2583
+ if (isAuthenticated) {
2584
+ setShouldRedirect(false);
2585
+ tabJustBecameVisibleRef.current = false;
2586
+ }
2587
+ }, [isAuthenticated]);
2339
2588
  const isRestoringSession = useMemo6(() => {
2340
2589
  return sessionRestoration.isRestoring && !sessionRestoration.restorationComplete && !sessionRestoration.restorationError && !sessionRestoration.hasTimedOut;
2341
2590
  }, [
@@ -2345,13 +2594,13 @@ function ProtectedRoute({
2345
2594
  sessionRestoration.hasTimedOut
2346
2595
  ]);
2347
2596
  if (isRestoringSession) {
2348
- return /* @__PURE__ */ jsx20(SessionRestorationLoader, {});
2597
+ return /* @__PURE__ */ jsx21(SessionRestorationLoader, {});
2349
2598
  }
2350
2599
  if (requireEvent && eventLoading) {
2351
- return /* @__PURE__ */ jsx20(Outlet2, {});
2600
+ return /* @__PURE__ */ jsx21(Outlet2, {});
2352
2601
  }
2353
- if (authLoading && !sessionRestoration.hasTimedOut) {
2354
- return loadingFallback || /* @__PURE__ */ jsx20("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }, children: /* @__PURE__ */ jsx20(LoadingSpinner, {}) });
2602
+ if (isLoading && !sessionRestoration.hasTimedOut) {
2603
+ return loadingFallback || /* @__PURE__ */ jsx21("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }, children: /* @__PURE__ */ jsx21(LoadingSpinner, {}) });
2355
2604
  }
2356
2605
  if (!isAuthenticated) {
2357
2606
  if (sessionRestoration.hasTimedOut || sessionRestoration.restorationError) {
@@ -2359,202 +2608,45 @@ function ProtectedRoute({
2359
2608
  timedOut: sessionRestoration.hasTimedOut,
2360
2609
  error: sessionRestoration.restorationError?.message
2361
2610
  });
2611
+ return /* @__PURE__ */ jsx21(Navigate, { to: loginPath, replace: true });
2362
2612
  }
2363
- return /* @__PURE__ */ jsx20(Navigate, { to: loginPath, replace: true });
2613
+ if (!wasAuthenticatedRef.current) {
2614
+ return /* @__PURE__ */ jsx21(Navigate, { to: loginPath, replace: true });
2615
+ }
2616
+ const isTabVisible = typeof document !== "undefined" && !document.hidden;
2617
+ if (tabJustBecameVisibleRef.current || isTabVisible && wasAuthenticatedRef.current && isLoading) {
2618
+ return loadingFallback || /* @__PURE__ */ jsx21("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }, children: /* @__PURE__ */ jsx21(LoadingSpinner, {}) });
2619
+ }
2620
+ if (shouldRedirect) {
2621
+ return /* @__PURE__ */ jsx21(Navigate, { to: loginPath, replace: true });
2622
+ }
2623
+ if (isLoading) {
2624
+ return loadingFallback || /* @__PURE__ */ jsx21("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }, children: /* @__PURE__ */ jsx21(LoadingSpinner, {}) });
2625
+ }
2626
+ return /* @__PURE__ */ jsx21(Navigate, { to: loginPath, replace: true });
2364
2627
  }
2365
2628
  if (!requireEvent) {
2366
- return /* @__PURE__ */ jsx20(Outlet2, {});
2629
+ return /* @__PURE__ */ jsx21(Outlet2, {});
2367
2630
  }
2368
2631
  if (!events || events.length === 0) {
2369
- return noEventsFallback || /* @__PURE__ */ jsx20("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh", padding: "2rem" }, children: /* @__PURE__ */ jsxs14(Alert, { variant: "destructive", className: "max-w-md", children: [
2370
- /* @__PURE__ */ jsx20(AlertTitle, { children: "No Events Available" }),
2371
- /* @__PURE__ */ jsx20(AlertDescription, { children: "You don't have access to any events. Please contact your administrator if you believe this is an error." })
2632
+ return noEventsFallback || /* @__PURE__ */ jsx21("div", { style: { display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh", padding: "2rem" }, children: /* @__PURE__ */ jsxs15(Alert, { variant: "destructive", className: "max-w-md", children: [
2633
+ /* @__PURE__ */ jsx21(AlertTitle, { children: "No Events Available" }),
2634
+ /* @__PURE__ */ jsx21(AlertDescription, { children: "You don't have access to any events. Please contact your administrator if you believe this is an error." })
2372
2635
  ] }) });
2373
2636
  }
2374
2637
  if (!selectedEvent) {
2375
2638
  logger.debug("ProtectedRoute", "Events available but none selected - allowing render so selector is visible");
2376
- return /* @__PURE__ */ jsx20(Outlet2, {});
2639
+ return /* @__PURE__ */ jsx21(Outlet2, {});
2377
2640
  }
2378
- return /* @__PURE__ */ jsx20(Outlet2, {});
2379
- }
2380
-
2381
- // src/components/OrganisationSelector/OrganisationSelector.tsx
2382
- import { useState as useState7, useCallback as useCallback4 } from "react";
2383
- import { RefreshCw as RefreshCw2, AlertCircle as AlertCircle2, Building2, Shield } from "lucide-react";
2384
- import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
2385
- function OrganisationSelector({
2386
- placeholder = "Select organisation",
2387
- className,
2388
- onOrganisationChange,
2389
- showNoOrganisationsMessage = true,
2390
- showRetryButton = true,
2391
- showRole = false,
2392
- compact = false,
2393
- disabled = false
2394
- }) {
2395
- const [isLoading, setIsLoading] = useState7(false);
2396
- const [switchError, setSwitchError] = useState7(null);
2397
- const {
2398
- organisations,
2399
- selectedOrganisation,
2400
- isLoading: orgLoading,
2401
- error: orgError,
2402
- switchOrganisation,
2403
- getUserRole,
2404
- validateOrganisationAccess,
2405
- refreshOrganisations
2406
- } = useOrganisations();
2407
- const handleOrganisationChange = useCallback4(async (orgId) => {
2408
- if (disabled || isLoading) return;
2409
- setSwitchError(null);
2410
- setIsLoading(true);
2411
- try {
2412
- if (!validateOrganisationAccess(orgId)) {
2413
- throw new Error("You do not have access to this organisation");
2414
- }
2415
- await switchOrganisation(orgId);
2416
- const newOrganisation = organisations.find((org) => org.id === orgId);
2417
- if (newOrganisation && onOrganisationChange) {
2418
- onOrganisationChange(newOrganisation);
2419
- }
2420
- logger.debug("OrganisationSelector", "Successfully switched to organisation:", orgId);
2421
- } catch (error) {
2422
- logger.error("OrganisationSelector", "Failed to switch organisation:", error);
2423
- setSwitchError(error instanceof Error ? error.message : "Failed to switch organisation");
2424
- } finally {
2425
- setIsLoading(false);
2426
- }
2427
- }, [
2428
- disabled,
2429
- isLoading,
2430
- validateOrganisationAccess,
2431
- switchOrganisation,
2432
- organisations,
2433
- onOrganisationChange
2434
- ]);
2435
- const handleRetry = useCallback4(async () => {
2436
- setIsLoading(true);
2437
- setSwitchError(null);
2438
- try {
2439
- await refreshOrganisations();
2440
- } catch (error) {
2441
- logger.error("OrganisationSelector", "Failed to refresh organisations:", error);
2442
- setSwitchError("Failed to refresh organisations");
2443
- } finally {
2444
- setIsLoading(false);
2445
- }
2446
- }, [refreshOrganisations]);
2447
- if (orgLoading) {
2448
- return /* @__PURE__ */ jsxs15("div", { className: `flex items-center gap-2 ${className}`, children: [
2449
- /* @__PURE__ */ jsx21(LoadingSpinner, { size: "sm" }),
2450
- /* @__PURE__ */ jsx21("span", { className: "text-sm text-muted-foreground", children: compact ? "Loading..." : "Loading organisations..." })
2451
- ] });
2452
- }
2453
- if (orgError) {
2454
- return /* @__PURE__ */ jsxs15("div", { className: `space-y-2 ${className}`, children: [
2455
- /* @__PURE__ */ jsxs15(Alert, { variant: "destructive", children: [
2456
- /* @__PURE__ */ jsx21(AlertCircle2, { className: "h-4 w-4" }),
2457
- /* @__PURE__ */ jsxs15(AlertDescription, { children: [
2458
- "Failed to load organisations: ",
2459
- orgError.message
2460
- ] })
2461
- ] }),
2462
- showRetryButton && /* @__PURE__ */ jsxs15(
2463
- Button,
2464
- {
2465
- variant: "outline",
2466
- size: "sm",
2467
- onClick: handleRetry,
2468
- disabled: isLoading,
2469
- className: "w-full",
2470
- children: [
2471
- /* @__PURE__ */ jsx21(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
2472
- "Retry"
2473
- ]
2474
- }
2475
- )
2476
- ] });
2477
- }
2478
- if (organisations.length === 0) {
2479
- if (showNoOrganisationsMessage) {
2480
- return /* @__PURE__ */ jsxs15("div", { className: `space-y-2 ${className}`, children: [
2481
- /* @__PURE__ */ jsxs15(Alert, { children: [
2482
- /* @__PURE__ */ jsx21(Building2, { className: "h-4 w-4" }),
2483
- /* @__PURE__ */ jsx21(AlertDescription, { children: "No organisations available. Please contact your administrator to be added to an organisation." })
2484
- ] }),
2485
- showRetryButton && /* @__PURE__ */ jsxs15(
2486
- Button,
2487
- {
2488
- variant: "outline",
2489
- size: "sm",
2490
- onClick: handleRetry,
2491
- disabled: isLoading,
2492
- className: "w-full",
2493
- children: [
2494
- /* @__PURE__ */ jsx21(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
2495
- "Check Again"
2496
- ]
2497
- }
2498
- )
2499
- ] });
2500
- }
2501
- return null;
2502
- }
2503
- const switchErrorDisplay = switchError && /* @__PURE__ */ jsxs15(Alert, { variant: "destructive", className: "mt-2", children: [
2504
- /* @__PURE__ */ jsx21(AlertCircle2, { className: "h-4 w-4" }),
2505
- /* @__PURE__ */ jsx21(AlertDescription, { children: switchError })
2506
- ] });
2507
- return /* @__PURE__ */ jsxs15("div", { className: `space-y-2 ${className}`, children: [
2508
- /* @__PURE__ */ jsxs15(
2509
- Select,
2510
- {
2511
- value: selectedOrganisation?.id || "",
2512
- onValueChange: handleOrganisationChange,
2513
- disabled: disabled || isLoading || !selectedOrganisation,
2514
- children: [
2515
- /* @__PURE__ */ jsx21(SelectTrigger, { className: `${isLoading ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
2516
- isLoading ? /* @__PURE__ */ jsx21(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx21(Building2, { className: "h-4 w-4 text-muted-foreground" }),
2517
- /* @__PURE__ */ jsx21(SelectValue, { placeholder })
2518
- ] }) }),
2519
- /* @__PURE__ */ jsx21(SelectContent, { children: organisations.map((org) => {
2520
- const userRole = getUserRole(org.id);
2521
- const hasAccess = validateOrganisationAccess(org.id);
2522
- return /* @__PURE__ */ jsx21(
2523
- SelectItem,
2524
- {
2525
- value: org.id,
2526
- disabled: !hasAccess,
2527
- className: !hasAccess ? "opacity-50" : "",
2528
- children: /* @__PURE__ */ jsxs15("div", { className: "flex items-center justify-between w-full", children: [
2529
- /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-2", children: [
2530
- /* @__PURE__ */ jsx21(Building2, { className: "h-4 w-4" }),
2531
- /* @__PURE__ */ jsxs15("div", { className: "flex flex-col", children: [
2532
- /* @__PURE__ */ jsx21("span", { className: "font-medium", children: org.display_name }),
2533
- !compact && org.description && /* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground truncate max-w-40", children: org.description })
2534
- ] })
2535
- ] }),
2536
- showRole && /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1 ml-4", children: [
2537
- /* @__PURE__ */ jsx21(Shield, { className: "h-3 w-3 text-muted-foreground" }),
2538
- /* @__PURE__ */ jsx21("span", { className: "text-xs text-muted-foreground capitalize", children: userRole?.replace("_", " ") || "No Role" })
2539
- ] })
2540
- ] })
2541
- },
2542
- org.id
2543
- );
2544
- }) })
2545
- ]
2546
- }
2547
- ),
2548
- switchErrorDisplay
2549
- ] });
2641
+ return /* @__PURE__ */ jsx21(Outlet2, {});
2550
2642
  }
2551
2643
 
2552
2644
  // src/hooks/useFileReference.ts
2553
- import { useState as useState8, useCallback as useCallback5, useEffect as useEffect5, useRef as useRef3, useMemo as useMemo7 } from "react";
2645
+ import { useState as useState9, useCallback as useCallback5, useEffect as useEffect6, useRef as useRef4, useMemo as useMemo7 } from "react";
2554
2646
  var log = createLogger("useFileReference");
2555
2647
  function useFileReference(supabase) {
2556
- const [isLoading, setIsLoading] = useState8(false);
2557
- const [error, setError] = useState8(null);
2648
+ const [isLoading, setIsLoading] = useState9(false);
2649
+ const [error, setError] = useState9(null);
2558
2650
  const service = useMemo7(() => createFileReferenceService(supabase), [supabase]);
2559
2651
  const uploadFile = useCallback5(async (options, file) => {
2560
2652
  setIsLoading(true);
@@ -2718,11 +2810,11 @@ function useFileReferenceForRecord(supabase, table_name, record_id, organisation
2718
2810
  getFileCount,
2719
2811
  clearError
2720
2812
  } = useFileReference(supabase);
2721
- const [fileUrl, setFileUrl] = useState8(null);
2722
- const [fileReference, setFileReference] = useState8(null);
2723
- const [fileReferences, setFileReferences] = useState8([]);
2724
- const [fileCount, setFileCount] = useState8(0);
2725
- const urlRefreshIntervalRef = useRef3(null);
2813
+ const [fileUrl, setFileUrl] = useState9(null);
2814
+ const [fileReference, setFileReference] = useState9(null);
2815
+ const [fileReferences, setFileReferences] = useState9([]);
2816
+ const [fileCount, setFileCount] = useState9(0);
2817
+ const urlRefreshIntervalRef = useRef4(null);
2726
2818
  const loadFileReference = useCallback5(async () => {
2727
2819
  const reference = await getFileReference(table_name, record_id, organisation_id);
2728
2820
  setFileReference(reference);
@@ -2752,7 +2844,7 @@ function useFileReferenceForRecord(supabase, table_name, record_id, organisation
2752
2844
  }
2753
2845
  return success;
2754
2846
  }, [deleteFileReference, table_name, record_id, organisation_id, loadFileCount]);
2755
- useEffect5(() => {
2847
+ useEffect6(() => {
2756
2848
  if (!fileReference || fileReference.is_public) {
2757
2849
  if (urlRefreshIntervalRef.current) {
2758
2850
  clearInterval(urlRefreshIntervalRef.current);
@@ -2793,8 +2885,8 @@ function useFileReferenceById(supabase, fileReferenceId, organisationId) {
2793
2885
  getFileReferenceById,
2794
2886
  clearError
2795
2887
  } = useFileReference(supabase);
2796
- const [fileReference, setFileReference] = useState8(null);
2797
- const [fileUrl, setFileUrl] = useState8(null);
2888
+ const [fileReference, setFileReference] = useState9(null);
2889
+ const [fileUrl, setFileUrl] = useState9(null);
2798
2890
  const loadFileReference = useCallback5(async () => {
2799
2891
  if (!fileReferenceId || !organisationId) {
2800
2892
  setFileReference(null);
@@ -2805,10 +2897,10 @@ function useFileReferenceById(supabase, fileReferenceId, organisationId) {
2805
2897
  setFileReference(reference);
2806
2898
  return reference;
2807
2899
  }, [getFileReferenceById, fileReferenceId, organisationId]);
2808
- useEffect5(() => {
2900
+ useEffect6(() => {
2809
2901
  loadFileReference();
2810
2902
  }, [loadFileReference]);
2811
- useEffect5(() => {
2903
+ useEffect6(() => {
2812
2904
  if (!fileReference || !fileReferenceId || !organisationId) {
2813
2905
  setFileUrl(null);
2814
2906
  return;
@@ -2840,8 +2932,8 @@ function useFilesByCategory(supabase, table_name, record_id, category, organisat
2840
2932
  getFilesByCategory,
2841
2933
  clearError
2842
2934
  } = useFileReference(supabase);
2843
- const [fileReferences, setFileReferences] = useState8([]);
2844
- const [fileUrls, setFileUrls] = useState8(/* @__PURE__ */ new Map());
2935
+ const [fileReferences, setFileReferences] = useState9([]);
2936
+ const [fileUrls, setFileUrls] = useState9(/* @__PURE__ */ new Map());
2845
2937
  const loadFiles = useCallback5(async () => {
2846
2938
  if (!category || !organisation_id) {
2847
2939
  setFileReferences([]);
@@ -2874,7 +2966,7 @@ function useFilesByCategory(supabase, table_name, record_id, category, organisat
2874
2966
  setFileUrls(urlMap);
2875
2967
  return files;
2876
2968
  }, [table_name, record_id, category, organisation_id, supabase, getFilesByCategory]);
2877
- useEffect5(() => {
2969
+ useEffect6(() => {
2878
2970
  loadFiles();
2879
2971
  }, [loadFiles]);
2880
2972
  return {
@@ -2888,7 +2980,7 @@ function useFilesByCategory(supabase, table_name, record_id, category, organisat
2888
2980
  }
2889
2981
 
2890
2982
  // src/components/FileUpload/FileUpload.tsx
2891
- import { useState as useState9, useCallback as useCallback6, useRef as useRef4, useEffect as useEffect6, useMemo as useMemo8 } from "react";
2983
+ import { useState as useState10, useCallback as useCallback6, useRef as useRef5, useEffect as useEffect7, useMemo as useMemo8 } from "react";
2892
2984
  import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
2893
2985
  function FileUpload({
2894
2986
  supabase,
@@ -2897,6 +2989,9 @@ function FileUpload({
2897
2989
  organisation_id,
2898
2990
  app_id,
2899
2991
  category,
2992
+ folder,
2993
+ pageContext,
2994
+ event_id,
2900
2995
  accept = "*/*",
2901
2996
  maxSize = 10 * 1024 * 1024,
2902
2997
  // 10MB default
@@ -2911,14 +3006,14 @@ function FileUpload({
2911
3006
  onProgress,
2912
3007
  children
2913
3008
  }) {
2914
- const [isDragging, setIsDragging] = useState9(false);
2915
- const [uploadStates, setUploadStates] = useState9(/* @__PURE__ */ new Map());
2916
- const [resolvedAppId, setResolvedAppId] = useState9(app_id || null);
2917
- const [isResolvingAppId, setIsResolvingAppId] = useState9(!app_id);
2918
- const [appIdError, setAppIdError] = useState9(null);
2919
- const fileInputRef = useRef4(null);
3009
+ const [isDragging, setIsDragging] = useState10(false);
3010
+ const [uploadStates, setUploadStates] = useState10(/* @__PURE__ */ new Map());
3011
+ const [resolvedAppId, setResolvedAppId] = useState10(app_id || null);
3012
+ const [isResolvingAppId, setIsResolvingAppId] = useState10(!app_id);
3013
+ const [appIdError, setAppIdError] = useState10(null);
3014
+ const fileInputRef = useRef5(null);
2920
3015
  const { uploadFile, isLoading, error } = useFileReference(supabase);
2921
- useEffect6(() => {
3016
+ useEffect7(() => {
2922
3017
  if (app_id) {
2923
3018
  setResolvedAppId(app_id);
2924
3019
  setIsResolvingAppId(false);
@@ -3084,6 +3179,9 @@ function FileUpload({
3084
3179
  organisation_id,
3085
3180
  app_id: resolvedAppId ? assertAppId(resolvedAppId) : assertAppId(""),
3086
3181
  category,
3182
+ folder,
3183
+ pageContext,
3184
+ event_id,
3087
3185
  is_public: isPublic
3088
3186
  }, file);
3089
3187
  clearInterval(progressInterval);
@@ -3170,7 +3268,7 @@ function FileUpload({
3170
3268
  onUploadError?.(errorMessage, file);
3171
3269
  }
3172
3270
  }
3173
- }, [uploadFile, table_name, record_id, organisation_id, resolvedAppId, category, isPublic, maxSize, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError]);
3271
+ }, [uploadFile, table_name, record_id, organisation_id, resolvedAppId, category, folder, isPublic, maxSize, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError]);
3174
3272
  const handleDragOver = useCallback6((e) => {
3175
3273
  e.preventDefault();
3176
3274
  e.stopPropagation();
@@ -3351,17 +3449,17 @@ function FileUpload({
3351
3449
  }
3352
3450
 
3353
3451
  // src/components/FileDisplay/FileDisplay.tsx
3354
- import { useState as useState11, useEffect as useEffect8, useRef as useRef6, useContext as useContext2, useMemo as useMemo9 } from "react";
3452
+ import { useState as useState12, useEffect as useEffect9, useRef as useRef7, useContext as useContext2, useMemo as useMemo9 } from "react";
3355
3453
 
3356
3454
  // src/hooks/useFileUrl.ts
3357
- import { useState as useState10, useEffect as useEffect7, useCallback as useCallback7, useRef as useRef5 } from "react";
3455
+ import { useState as useState11, useEffect as useEffect8, useCallback as useCallback7, useRef as useRef6 } from "react";
3358
3456
  var log2 = createLogger("useFileUrl");
3359
3457
  function useFileUrl(fileReference, options) {
3360
3458
  const { organisation_id, supabase, autoLoad = true } = options;
3361
- const [url, setUrl] = useState10(null);
3362
- const [isLoading, setIsLoading] = useState10(false);
3363
- const [error, setError] = useState10(null);
3364
- const fileReferenceIdRef = useRef5(null);
3459
+ const [url, setUrl] = useState11(null);
3460
+ const [isLoading, setIsLoading] = useState11(false);
3461
+ const [error, setError] = useState11(null);
3462
+ const fileReferenceIdRef = useRef6(null);
3365
3463
  const loadUrl = useCallback7(async () => {
3366
3464
  if (!fileReference) {
3367
3465
  setUrl(null);
@@ -3404,7 +3502,7 @@ function useFileUrl(fileReference, options) {
3404
3502
  setIsLoading(false);
3405
3503
  fileReferenceIdRef.current = null;
3406
3504
  }, []);
3407
- useEffect7(() => {
3505
+ useEffect8(() => {
3408
3506
  if (autoLoad) {
3409
3507
  if (fileReferenceIdRef.current !== fileReference?.id) {
3410
3508
  setUrl(null);
@@ -3464,10 +3562,10 @@ function FileDisplayContent({
3464
3562
  fallbackText,
3465
3563
  fallbackSize = "md"
3466
3564
  }) {
3467
- const [imageError, setImageError] = useState11(false);
3468
- const [internalFileUrls, setInternalFileUrls] = useState11(new Map(fileUrls));
3469
- const [deleteDialogOpen, setDeleteDialogOpen] = useState11(false);
3470
- const fileReferencesRef = useRef6([]);
3565
+ const [imageError, setImageError] = useState12(false);
3566
+ const [internalFileUrls, setInternalFileUrls] = useState12(new Map(fileUrls));
3567
+ const [deleteDialogOpen, setDeleteDialogOpen] = useState12(false);
3568
+ const fileReferencesRef = useRef7([]);
3471
3569
  const computedFallbackText = useMemo9(() => {
3472
3570
  if (fallbackText) return fallbackText;
3473
3571
  const fileName = fileReference?.file_metadata?.fileName;
@@ -3478,7 +3576,7 @@ function FileDisplayContent({
3478
3576
  const baseClasses = "flex items-center justify-center bg-sec-100 text-sec-600 font-semibold rounded";
3479
3577
  return `${baseClasses} ${sizeClass} ${className}`.trim();
3480
3578
  }, [fallbackSize, className]);
3481
- useEffect8(() => {
3579
+ useEffect9(() => {
3482
3580
  const currentIds = fileReferences.map((f) => f.id).join(",");
3483
3581
  const prevIds = fileReferencesRef.current.map((f) => f.id).join(",");
3484
3582
  if (currentIds !== prevIds) {
@@ -3868,7 +3966,7 @@ function FileDisplayAuthenticated({
3868
3966
  category,
3869
3967
  { supabase }
3870
3968
  );
3871
- const [displayOnlyFileReference, setDisplayOnlyFileReference] = useState11(null);
3969
+ const [displayOnlyFileReference, setDisplayOnlyFileReference] = useState12(null);
3872
3970
  const displayOnlyFileUrlFromMap = displayOnlyFileReference ? fileUrls.get(displayOnlyFileReference.id) : null;
3873
3971
  const displayOnlyFileUrlHook = useFileUrl(
3874
3972
  displayOnlyFileReference && !displayOnlyFileUrlFromMap ? displayOnlyFileReference : null,
@@ -3879,7 +3977,7 @@ function FileDisplayAuthenticated({
3879
3977
  }
3880
3978
  );
3881
3979
  const displayOnlyFileUrl = displayOnlyFileUrlFromMap || displayOnlyFileUrlHook.url;
3882
- useEffect8(() => {
3980
+ useEffect9(() => {
3883
3981
  if (displayOnly && !category && fileReferences.length > 0) {
3884
3982
  const imageFiles = fileReferences.filter(
3885
3983
  (f) => f.file_metadata.fileType?.startsWith("image/")
@@ -4231,6 +4329,7 @@ export {
4231
4329
  FormField,
4232
4330
  LoginForm,
4233
4331
  EventSelector,
4332
+ OrganisationSelector,
4234
4333
  PasswordChangeForm,
4235
4334
  UserMenu,
4236
4335
  NavigationMenu,
@@ -4240,7 +4339,6 @@ export {
4240
4339
  PaceLoginPage,
4241
4340
  SessionRestorationLoader,
4242
4341
  ProtectedRoute,
4243
- OrganisationSelector,
4244
4342
  useFileReference,
4245
4343
  useFileReferenceForRecord,
4246
4344
  useFileReferenceById,
@@ -4259,4 +4357,4 @@ export {
4259
4357
  PublicPageFooter,
4260
4358
  PublicPageLayout
4261
4359
  };
4262
- //# sourceMappingURL=chunk-NQPMQGS2.js.map
4360
+ //# sourceMappingURL=chunk-HDCUMOOI.js.map