@jmruthers/pace-core 0.5.87 → 0.5.89

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 (243) hide show
  1. package/dist/{AuthService-Df3IozMG.d.ts → AuthService-DcTI5Ov4.d.ts} +9 -0
  2. package/dist/{DataTable-FA6EUX5M.js → DataTable-PWBMKMOG.js} +7 -7
  3. package/dist/{PublicLoadingSpinner-DecuJBX0.d.ts → PublicLoadingSpinner-BQXD1fbO.d.ts} +160 -130
  4. package/dist/{UnifiedAuthProvider-K2IZAY5F.js → UnifiedAuthProvider-5D3HEQND.js} +4 -4
  5. package/dist/{UnifiedAuthProvider-B391Aqum.d.ts → UnifiedAuthProvider-BVKmQd9u.d.ts} +4 -0
  6. package/dist/auth-DReDSLq9.d.ts +16 -0
  7. package/dist/{chunk-CBSD3BZ3.js → chunk-3RZBKQ5Y.js} +2 -6
  8. package/dist/{chunk-CBSD3BZ3.js.map → chunk-3RZBKQ5Y.js.map} +1 -1
  9. package/dist/{chunk-NTW3KGS4.js → chunk-6UHXQH7P.js} +5 -5
  10. package/dist/{chunk-ZFLOV3OM.js → chunk-7VJDS5QD.js} +401 -16
  11. package/dist/chunk-7VJDS5QD.js.map +1 -0
  12. package/dist/{chunk-YVUZWLQG.js → chunk-AQGF5OG7.js} +3 -3
  13. package/dist/{chunk-CVMVPYAL.js → chunk-BDZUMRBD.js} +3 -5
  14. package/dist/chunk-BDZUMRBD.js.map +1 -0
  15. package/dist/{chunk-KAY3K5TP.js → chunk-BNXBJOGL.js} +4 -4
  16. package/dist/{chunk-S3JKDMD5.js → chunk-CXKMRKRF.js} +4 -4
  17. package/dist/{chunk-5BN3YGNK.js → chunk-DP5X5ORK.js} +217 -27
  18. package/dist/chunk-DP5X5ORK.js.map +1 -0
  19. package/dist/{chunk-RIXPZJUB.js → chunk-KTPG5VCH.js} +2 -2
  20. package/dist/{chunk-2FQEQUJT.js → chunk-KWICIQVK.js} +4 -4
  21. package/dist/{chunk-WUXCWRL6.js → chunk-XJ2HZOBU.js} +6 -1
  22. package/dist/chunk-XJ2HZOBU.js.map +1 -0
  23. package/dist/{chunk-I7O3RSMN.js → chunk-YWAFPVJA.js} +1298 -769
  24. package/dist/chunk-YWAFPVJA.js.map +1 -0
  25. package/dist/{chunk-I2VVV5PQ.js → chunk-YY4YYM3E.js} +2 -2
  26. package/dist/components.d.ts +6 -55
  27. package/dist/components.js +24 -205
  28. package/dist/components.js.map +1 -1
  29. package/dist/{file-reference-9xUOnwyt.d.ts → file-reference-C9isKNPn.d.ts} +67 -2
  30. package/dist/hooks.js +9 -8
  31. package/dist/hooks.js.map +1 -1
  32. package/dist/index.d.ts +152 -26
  33. package/dist/index.js +64 -194
  34. package/dist/index.js.map +1 -1
  35. package/dist/providers.d.ts +5 -3
  36. package/dist/providers.js +3 -3
  37. package/dist/rbac/index.js +8 -8
  38. package/dist/types.d.ts +2 -1
  39. package/dist/types.js +3 -3
  40. package/dist/utils.js +2 -2
  41. package/docs/DOCUMENTATION_AUDIT.md +6 -6
  42. package/docs/DOCUMENTATION_STANDARD.md +137 -0
  43. package/docs/README.md +1 -1
  44. package/docs/api/classes/ColumnFactory.md +1 -1
  45. package/docs/api/classes/ErrorBoundary.md +1 -1
  46. package/docs/api/classes/InvalidScopeError.md +1 -1
  47. package/docs/api/classes/MissingUserContextError.md +1 -1
  48. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  49. package/docs/api/classes/PermissionDeniedError.md +1 -1
  50. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  51. package/docs/api/classes/RBACAuditManager.md +1 -1
  52. package/docs/api/classes/RBACCache.md +1 -1
  53. package/docs/api/classes/RBACEngine.md +1 -1
  54. package/docs/api/classes/RBACError.md +1 -1
  55. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  56. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  57. package/docs/api/classes/StorageUtils.md +83 -40
  58. package/docs/api/enums/FileCategory.md +56 -1
  59. package/docs/api/interfaces/AggregateConfig.md +1 -1
  60. package/docs/api/interfaces/ButtonProps.md +1 -1
  61. package/docs/api/interfaces/CardProps.md +1 -1
  62. package/docs/api/interfaces/ColorPalette.md +1 -1
  63. package/docs/api/interfaces/ColorShade.md +1 -1
  64. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  65. package/docs/api/interfaces/DataRecord.md +1 -1
  66. package/docs/api/interfaces/DataTableAction.md +1 -1
  67. package/docs/api/interfaces/DataTableColumn.md +1 -1
  68. package/docs/api/interfaces/DataTableProps.md +1 -1
  69. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  70. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  71. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  72. package/docs/api/interfaces/EventLogoProps.md +11 -11
  73. package/docs/api/interfaces/FileDisplayProps.md +10 -10
  74. package/docs/api/interfaces/FileMetadata.md +1 -1
  75. package/docs/api/interfaces/FileReference.md +1 -1
  76. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  77. package/docs/api/interfaces/FileUploadOptions.md +8 -8
  78. package/docs/api/interfaces/FileUploadProps.md +137 -42
  79. package/docs/api/interfaces/FooterProps.md +1 -1
  80. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  81. package/docs/api/interfaces/InputProps.md +1 -1
  82. package/docs/api/interfaces/LabelProps.md +1 -1
  83. package/docs/api/interfaces/LoginFormProps.md +1 -1
  84. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  85. package/docs/api/interfaces/NavigationContextType.md +1 -1
  86. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  87. package/docs/api/interfaces/NavigationItem.md +1 -1
  88. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  89. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  90. package/docs/api/interfaces/Organisation.md +1 -1
  91. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  92. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  93. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  94. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  95. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  96. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  97. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  98. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  99. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  100. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  101. package/docs/api/interfaces/PaletteData.md +1 -1
  102. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  103. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  104. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  105. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  106. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  107. package/docs/api/interfaces/PublicPageHeaderProps.md +1 -1
  108. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  109. package/docs/api/interfaces/RBACConfig.md +1 -1
  110. package/docs/api/interfaces/RBACLogger.md +1 -1
  111. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  112. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  113. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  114. package/docs/api/interfaces/RouteConfig.md +1 -1
  115. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  116. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  117. package/docs/api/interfaces/StorageConfig.md +1 -1
  118. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  119. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  120. package/docs/api/interfaces/StorageListOptions.md +1 -1
  121. package/docs/api/interfaces/StorageListResult.md +1 -1
  122. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  123. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  124. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  125. package/docs/api/interfaces/StyleImport.md +1 -1
  126. package/docs/api/interfaces/SwitchProps.md +1 -1
  127. package/docs/api/interfaces/ToastActionElement.md +1 -1
  128. package/docs/api/interfaces/ToastProps.md +1 -1
  129. package/docs/api/interfaces/UnifiedAuthContextType.md +83 -50
  130. package/docs/api/interfaces/UnifiedAuthProviderProps.md +13 -13
  131. package/docs/api/interfaces/UseEventLogoOptions.md +74 -0
  132. package/docs/api/interfaces/UseEventLogoReturn.md +81 -0
  133. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  134. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  135. package/docs/api/interfaces/UsePublicEventLogoOptions.md +6 -6
  136. package/docs/api/interfaces/UsePublicEventLogoReturn.md +6 -6
  137. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  138. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  139. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  140. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  141. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  142. package/docs/api/interfaces/UserEventAccess.md +11 -11
  143. package/docs/api/interfaces/UserMenuProps.md +1 -1
  144. package/docs/api/interfaces/UserProfile.md +1 -1
  145. package/docs/api/modules.md +290 -95
  146. package/docs/api-reference/components.md +1 -18
  147. package/docs/api-reference/hooks.md +1 -4
  148. package/docs/best-practices/testing.md +2 -0
  149. package/docs/documentation-index.md +1 -1
  150. package/docs/getting-started/faq.md +1 -1
  151. package/docs/implementation-guides/file-reference-system.md +592 -58
  152. package/docs/implementation-guides/file-upload-storage.md +137 -73
  153. package/docs/implementation-guides/public-pages-advanced.md +10 -0
  154. package/docs/rbac/super-admin-guide.md +18 -70
  155. package/docs/testing/README.md +2 -0
  156. package/package.json +1 -1
  157. package/src/__tests__/TEST_STANDARD.md +674 -0
  158. package/src/__tests__/helpers/test-utils.tsx +3 -2
  159. package/src/components/DataTable/__tests__/{DataTable.comprehensive.test.tsx.skip → DataTable.comprehensive.test.tsx} +17 -18
  160. package/src/components/DataTable/__tests__/{DataTable.test.tsx.skip → DataTable.test.tsx} +14 -22
  161. package/src/components/DataTable/__tests__/{ssr.strict-mode.test.tsx.skip → ssr.strict-mode.test.tsx} +42 -47
  162. package/src/components/DataTable/components/__tests__/COVERAGE_NOTE.md +1 -1
  163. package/src/components/DataTable/examples/__tests__/PerformanceExample.test.tsx +13 -4
  164. package/src/components/DataTable/utils/__tests__/COVERAGE_NOTE.md +1 -1
  165. package/src/components/DataTable/utils/__tests__/performanceUtils.test.ts +10 -6
  166. package/src/components/FileDisplay/FileDisplay.test.tsx +257 -0
  167. package/src/components/{FileDisplay.tsx → FileDisplay/FileDisplay.tsx} +111 -10
  168. package/src/components/FileDisplay/index.tsx +4 -0
  169. package/src/components/FileUpload/FileUpload.test.tsx +171 -621
  170. package/src/components/FileUpload/FileUpload.tsx +512 -168
  171. package/src/components/FileUpload/index.tsx +4 -0
  172. package/src/components/Progress/Progress.test.tsx +38 -0
  173. package/src/components/PublicLayout/EventLogo.tsx +6 -4
  174. package/src/components/Select/Select.test.tsx +1 -1
  175. package/src/components/SessionRestorationLoader.tsx +48 -0
  176. package/src/components/Toast/Toast.tsx +13 -8
  177. package/src/components/index.ts +16 -16
  178. package/src/hooks/__tests__/ServiceHooks.test.tsx +615 -0
  179. package/src/hooks/public/usePublicEventLogo.ts +16 -20
  180. package/src/hooks/useEventLogo.ts +316 -0
  181. package/src/hooks/useEvents.ts +0 -5
  182. package/src/hooks/useFileReference.test.ts +659 -0
  183. package/src/hooks/useFileReference.ts +207 -3
  184. package/src/hooks/useSessionRestoration.ts +64 -0
  185. package/src/index.ts +17 -5
  186. package/src/providers/{UnifiedAuthProvider.test.simple.tsx → UnifiedAuthProvider.smoke.test.tsx} +81 -60
  187. package/src/providers/services/AuthServiceProvider.tsx +27 -3
  188. package/src/providers/services/UnifiedAuthProvider.tsx +34 -5
  189. package/src/rbac/{engine.test.simple.ts → RBACEngine.smoke.test.ts} +17 -12
  190. package/src/services/AuthService.ts +142 -20
  191. package/src/services/EventService.ts +0 -4
  192. package/src/types/auth.ts +15 -0
  193. package/src/types/file-reference.ts +73 -1
  194. package/src/types/index.ts +1 -0
  195. package/src/utils/__tests__/organisationContext.unit.test.ts +2 -4
  196. package/src/utils/appNameResolver.simple.test.ts +99 -29
  197. package/src/utils/file-reference.test.ts +535 -0
  198. package/src/utils/file-reference.ts +200 -30
  199. package/src/utils/organisationContext.test.ts +5 -19
  200. package/src/utils/organisationContext.ts +3 -5
  201. package/src/utils/storage/README.md +269 -262
  202. package/src/utils/storage/config.ts +9 -0
  203. package/src/utils/storage/helpers.test.ts +735 -0
  204. package/src/utils/storage/helpers.ts +189 -16
  205. package/src/utils/storage/index.ts +3 -0
  206. package/src/validation/__tests__/sanitization.unit.test.ts +1 -1
  207. package/src/validation/__tests__/schemaUtils.unit.test.ts +1 -1
  208. package/src/validation/__tests__/user.unit.test.ts +1 -1
  209. package/dist/chunk-5BN3YGNK.js.map +0 -1
  210. package/dist/chunk-CVMVPYAL.js.map +0 -1
  211. package/dist/chunk-I7O3RSMN.js.map +0 -1
  212. package/dist/chunk-WUXCWRL6.js.map +0 -1
  213. package/dist/chunk-ZFLOV3OM.js.map +0 -1
  214. package/docs/CONTENT_AUDIT_REPORT.md +0 -253
  215. package/docs/STYLE_GUIDE.md +0 -37
  216. package/examples/RBAC/__tests__/PermissionExample.test.tsx +0 -150
  217. package/examples/public-pages/__tests__/PublicPageUsageExample.test.tsx +0 -159
  218. package/src/__tests__/TEST_GUIDE_CURSOR.md +0 -1605
  219. package/src/__tests__/TEST_GUIDE_HUMAN.md +0 -103
  220. package/src/components/FileUpload/FileUpload.example.tsx +0 -218
  221. package/src/components/FileUpload/index.ts +0 -6
  222. package/src/components/FileUpload.tsx +0 -176
  223. package/src/components/Progress/index.ts +0 -3
  224. package/src/components/PublicLayout/__tests__/EventLogo.test.tsx +0 -666
  225. package/src/components/SuperAdminGuard.tsx +0 -116
  226. package/src/components/__tests__/FileDisplay.test.tsx +0 -575
  227. package/src/components/__tests__/FileUpload.test.tsx +0 -446
  228. package/src/components/__tests__/SuperAdminGuard.test.tsx +0 -627
  229. package/src/components/examples/PermissionExample.tsx +0 -173
  230. package/src/hooks/__tests__/usePublicEvent.unit.test.ts +0 -583
  231. package/src/hooks/__tests__/usePublicEventLogo.unit.test.ts +0 -640
  232. package/src/types/__tests__/file-reference.test.ts +0 -447
  233. package/src/utils/__tests__/file-reference.test.ts +0 -383
  234. /package/dist/{DataTable-FA6EUX5M.js.map → DataTable-PWBMKMOG.js.map} +0 -0
  235. /package/dist/{UnifiedAuthProvider-K2IZAY5F.js.map → UnifiedAuthProvider-5D3HEQND.js.map} +0 -0
  236. /package/dist/{chunk-NTW3KGS4.js.map → chunk-6UHXQH7P.js.map} +0 -0
  237. /package/dist/{chunk-YVUZWLQG.js.map → chunk-AQGF5OG7.js.map} +0 -0
  238. /package/dist/{chunk-KAY3K5TP.js.map → chunk-BNXBJOGL.js.map} +0 -0
  239. /package/dist/{chunk-S3JKDMD5.js.map → chunk-CXKMRKRF.js.map} +0 -0
  240. /package/dist/{chunk-RIXPZJUB.js.map → chunk-KTPG5VCH.js.map} +0 -0
  241. /package/dist/{chunk-2FQEQUJT.js.map → chunk-KWICIQVK.js.map} +0 -0
  242. /package/dist/{chunk-I2VVV5PQ.js.map → chunk-YY4YYM3E.js.map} +0 -0
  243. /package/src/providers/{OrganisationProvider.test.simple.tsx → OrganisationProvider.context.test.tsx} +0 -0
@@ -22,7 +22,7 @@ import {
22
22
  SelectSeparator,
23
23
  SelectTrigger,
24
24
  SelectValue
25
- } from "./chunk-KAY3K5TP.js";
25
+ } from "./chunk-BNXBJOGL.js";
26
26
  import {
27
27
  isPermitted,
28
28
  isSuperAdmin
@@ -31,23 +31,28 @@ import {
31
31
  OrganisationProvider_exports,
32
32
  PublicErrorBoundary,
33
33
  PublicPageContext,
34
+ deleteFile,
35
+ extractFileMetadata,
36
+ getPublicUrl,
37
+ getSignedUrl,
34
38
  init_OrganisationProvider,
39
+ uploadFile,
35
40
  useAppConfig,
36
41
  useIsPublicPage,
37
42
  usePublicEventLogo,
38
43
  usePublicPageContext
39
- } from "./chunk-ZFLOV3OM.js";
44
+ } from "./chunk-7VJDS5QD.js";
40
45
  import {
41
46
  useToast
42
47
  } from "./chunk-QPCAGLUS.js";
43
48
  import {
44
49
  useEvents,
45
50
  useOrganisations
46
- } from "./chunk-CBSD3BZ3.js";
51
+ } from "./chunk-3RZBKQ5Y.js";
47
52
  import {
48
53
  UnifiedAuthProvider_exports,
49
54
  init_UnifiedAuthProvider as init_UnifiedAuthProvider2
50
- } from "./chunk-RIXPZJUB.js";
55
+ } from "./chunk-KTPG5VCH.js";
51
56
  import {
52
57
  EventServiceContext,
53
58
  EventServiceProvider,
@@ -55,16 +60,23 @@ import {
55
60
  init_UnifiedAuthProvider,
56
61
  useEventService,
57
62
  useUnifiedAuth
58
- } from "./chunk-5BN3YGNK.js";
63
+ } from "./chunk-DP5X5ORK.js";
59
64
  import {
60
65
  LoadingSpinner
61
66
  } from "./chunk-CDQ3PX7L.js";
62
67
  import {
63
68
  cn
64
69
  } from "./chunk-PYUXFQJ3.js";
70
+ import {
71
+ getCurrentAppName
72
+ } from "./chunk-JCQZ6LA7.js";
65
73
  import {
66
74
  performanceBudgetMonitor
67
75
  } from "./chunk-O3NWNXDY.js";
76
+ import {
77
+ init_organisationContext,
78
+ setOrganisationContext
79
+ } from "./chunk-BDZUMRBD.js";
68
80
  import {
69
81
  __esm,
70
82
  __export,
@@ -350,12 +362,15 @@ function Toaster() {
350
362
  const { toasts } = useToast();
351
363
  return /* @__PURE__ */ jsxs2(ToastProvider, { "data-testid": "toast-provider", children: [
352
364
  /* @__PURE__ */ jsx5(ToastViewport, {}),
353
- toasts.map((toast) => /* @__PURE__ */ jsxs2(Toast, { ...toast, children: [
354
- toast.title && /* @__PURE__ */ jsx5(ToastTitle, { children: toast.title }),
355
- toast.description && /* @__PURE__ */ jsx5(ToastDescription, { children: toast.description }),
356
- toast.action && toast.action,
357
- /* @__PURE__ */ jsx5(ToastClose, { onClick: toast.dismiss })
358
- ] }, toast.id))
365
+ toasts.map((toast) => {
366
+ const { id, title, description, action, dismiss, ...toastProps } = toast;
367
+ return /* @__PURE__ */ jsxs2(Toast, { ...toastProps, children: [
368
+ title && /* @__PURE__ */ jsx5(ToastTitle, { children: title }),
369
+ description && /* @__PURE__ */ jsx5(ToastDescription, { children: description }),
370
+ action && action,
371
+ /* @__PURE__ */ jsx5(ToastClose, { onClick: dismiss })
372
+ ] }, id);
373
+ })
359
374
  ] });
360
375
  }
361
376
 
@@ -1401,7 +1416,7 @@ function PaceAppLayout({
1401
1416
  }
1402
1417
  }
1403
1418
  if (hasAccess && currentRoute.roles && currentRoute.roles.length > 0 && user?.id) {
1404
- const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-K2IZAY5F.js");
1419
+ const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-5D3HEQND.js");
1405
1420
  hasAccess = true;
1406
1421
  }
1407
1422
  if (!isMounted) return;
@@ -1785,11 +1800,48 @@ var ErrorBoundary = class extends Component {
1785
1800
  }
1786
1801
  };
1787
1802
 
1803
+ // src/components/SessionRestorationLoader.tsx
1804
+ import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
1805
+ var SessionRestorationLoader = ({
1806
+ message = "Restoring session..."
1807
+ }) => {
1808
+ return /* @__PURE__ */ jsxs13(
1809
+ "div",
1810
+ {
1811
+ style: {
1812
+ display: "flex",
1813
+ flexDirection: "column",
1814
+ alignItems: "center",
1815
+ justifyContent: "center",
1816
+ height: "100vh",
1817
+ width: "100%",
1818
+ gap: "1rem",
1819
+ textAlign: "center",
1820
+ padding: "1rem",
1821
+ background: "var(--background, transparent)"
1822
+ },
1823
+ children: [
1824
+ /* @__PURE__ */ jsx17(LoadingSpinner, { size: "lg" }),
1825
+ /* @__PURE__ */ jsx17(
1826
+ "div",
1827
+ {
1828
+ style: {
1829
+ fontSize: "0.95rem",
1830
+ color: "var(--muted-foreground, #6b7280)"
1831
+ },
1832
+ children: message
1833
+ }
1834
+ )
1835
+ ]
1836
+ }
1837
+ );
1838
+ };
1839
+
1788
1840
  // src/components/OrganisationSelector/OrganisationSelector.tsx
1789
1841
  import { useState as useState7, useCallback as useCallback4 } from "react";
1790
1842
  init_OrganisationProvider();
1791
1843
  import { RefreshCw as RefreshCw2, AlertCircle as AlertCircle2, Building2, Shield } from "lucide-react";
1792
- import { jsx as jsx17, jsxs as jsxs13 } from "react/jsx-runtime";
1844
+ import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
1793
1845
  function OrganisationSelector({
1794
1846
  placeholder = "Select organisation",
1795
1847
  className,
@@ -1853,21 +1905,21 @@ function OrganisationSelector({
1853
1905
  }
1854
1906
  }, [refreshOrganisations]);
1855
1907
  if (orgLoading) {
1856
- return /* @__PURE__ */ jsxs13("div", { className: `flex items-center gap-2 ${className}`, children: [
1857
- /* @__PURE__ */ jsx17(LoadingSpinner, { size: "sm" }),
1858
- /* @__PURE__ */ jsx17("span", { className: "text-sm text-muted-foreground", children: compact ? "Loading..." : "Loading organisations..." })
1908
+ return /* @__PURE__ */ jsxs14("div", { className: `flex items-center gap-2 ${className}`, children: [
1909
+ /* @__PURE__ */ jsx18(LoadingSpinner, { size: "sm" }),
1910
+ /* @__PURE__ */ jsx18("span", { className: "text-sm text-muted-foreground", children: compact ? "Loading..." : "Loading organisations..." })
1859
1911
  ] });
1860
1912
  }
1861
1913
  if (orgError) {
1862
- return /* @__PURE__ */ jsxs13("div", { className: `space-y-2 ${className}`, children: [
1863
- /* @__PURE__ */ jsxs13(Alert, { variant: "destructive", children: [
1864
- /* @__PURE__ */ jsx17(AlertCircle2, { className: "h-4 w-4" }),
1865
- /* @__PURE__ */ jsxs13(AlertDescription, { children: [
1914
+ return /* @__PURE__ */ jsxs14("div", { className: `space-y-2 ${className}`, children: [
1915
+ /* @__PURE__ */ jsxs14(Alert, { variant: "destructive", children: [
1916
+ /* @__PURE__ */ jsx18(AlertCircle2, { className: "h-4 w-4" }),
1917
+ /* @__PURE__ */ jsxs14(AlertDescription, { children: [
1866
1918
  "Failed to load organisations: ",
1867
1919
  orgError.message
1868
1920
  ] })
1869
1921
  ] }),
1870
- showRetryButton && /* @__PURE__ */ jsxs13(
1922
+ showRetryButton && /* @__PURE__ */ jsxs14(
1871
1923
  Button,
1872
1924
  {
1873
1925
  variant: "outline",
@@ -1876,7 +1928,7 @@ function OrganisationSelector({
1876
1928
  disabled: isLoading,
1877
1929
  className: "w-full",
1878
1930
  children: [
1879
- /* @__PURE__ */ jsx17(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
1931
+ /* @__PURE__ */ jsx18(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
1880
1932
  "Retry"
1881
1933
  ]
1882
1934
  }
@@ -1885,12 +1937,12 @@ function OrganisationSelector({
1885
1937
  }
1886
1938
  if (organisations.length === 0) {
1887
1939
  if (showNoOrganisationsMessage) {
1888
- return /* @__PURE__ */ jsxs13("div", { className: `space-y-2 ${className}`, children: [
1889
- /* @__PURE__ */ jsxs13(Alert, { children: [
1890
- /* @__PURE__ */ jsx17(Building2, { className: "h-4 w-4" }),
1891
- /* @__PURE__ */ jsx17(AlertDescription, { children: "No organisations available. Please contact your administrator to be added to an organisation." })
1940
+ return /* @__PURE__ */ jsxs14("div", { className: `space-y-2 ${className}`, children: [
1941
+ /* @__PURE__ */ jsxs14(Alert, { children: [
1942
+ /* @__PURE__ */ jsx18(Building2, { className: "h-4 w-4" }),
1943
+ /* @__PURE__ */ jsx18(AlertDescription, { children: "No organisations available. Please contact your administrator to be added to an organisation." })
1892
1944
  ] }),
1893
- showRetryButton && /* @__PURE__ */ jsxs13(
1945
+ showRetryButton && /* @__PURE__ */ jsxs14(
1894
1946
  Button,
1895
1947
  {
1896
1948
  variant: "outline",
@@ -1899,7 +1951,7 @@ function OrganisationSelector({
1899
1951
  disabled: isLoading,
1900
1952
  className: "w-full",
1901
1953
  children: [
1902
- /* @__PURE__ */ jsx17(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
1954
+ /* @__PURE__ */ jsx18(RefreshCw2, { className: `h-4 w-4 mr-2 ${isLoading ? "animate-spin" : ""}` }),
1903
1955
  "Check Again"
1904
1956
  ]
1905
1957
  }
@@ -1908,42 +1960,42 @@ function OrganisationSelector({
1908
1960
  }
1909
1961
  return null;
1910
1962
  }
1911
- const switchErrorDisplay = switchError && /* @__PURE__ */ jsxs13(Alert, { variant: "destructive", className: "mt-2", children: [
1912
- /* @__PURE__ */ jsx17(AlertCircle2, { className: "h-4 w-4" }),
1913
- /* @__PURE__ */ jsx17(AlertDescription, { children: switchError })
1963
+ const switchErrorDisplay = switchError && /* @__PURE__ */ jsxs14(Alert, { variant: "destructive", className: "mt-2", children: [
1964
+ /* @__PURE__ */ jsx18(AlertCircle2, { className: "h-4 w-4" }),
1965
+ /* @__PURE__ */ jsx18(AlertDescription, { children: switchError })
1914
1966
  ] });
1915
- return /* @__PURE__ */ jsxs13("div", { className: `space-y-2 ${className}`, children: [
1916
- /* @__PURE__ */ jsxs13(
1967
+ return /* @__PURE__ */ jsxs14("div", { className: `space-y-2 ${className}`, children: [
1968
+ /* @__PURE__ */ jsxs14(
1917
1969
  Select,
1918
1970
  {
1919
1971
  value: selectedOrganisation?.id || "",
1920
1972
  onValueChange: handleOrganisationChange,
1921
1973
  disabled: disabled || isLoading || !selectedOrganisation,
1922
1974
  children: [
1923
- /* @__PURE__ */ jsx17(SelectTrigger, { className: `${isLoading ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
1924
- isLoading ? /* @__PURE__ */ jsx17(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx17(Building2, { className: "h-4 w-4 text-muted-foreground" }),
1925
- /* @__PURE__ */ jsx17(SelectValue, { placeholder })
1975
+ /* @__PURE__ */ jsx18(SelectTrigger, { className: `${isLoading ? "opacity-50" : ""}`, children: /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
1976
+ isLoading ? /* @__PURE__ */ jsx18(LoadingSpinner, { size: "sm" }) : /* @__PURE__ */ jsx18(Building2, { className: "h-4 w-4 text-muted-foreground" }),
1977
+ /* @__PURE__ */ jsx18(SelectValue, { placeholder })
1926
1978
  ] }) }),
1927
- /* @__PURE__ */ jsx17(SelectContent, { children: organisations.map((org) => {
1979
+ /* @__PURE__ */ jsx18(SelectContent, { children: organisations.map((org) => {
1928
1980
  const userRole = getUserRole(org.id);
1929
1981
  const hasAccess = validateOrganisationAccess(org.id);
1930
- return /* @__PURE__ */ jsx17(
1982
+ return /* @__PURE__ */ jsx18(
1931
1983
  SelectItem,
1932
1984
  {
1933
1985
  value: org.id,
1934
1986
  disabled: !hasAccess,
1935
1987
  className: !hasAccess ? "opacity-50" : "",
1936
- children: /* @__PURE__ */ jsxs13("div", { className: "flex items-center justify-between w-full", children: [
1937
- /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
1938
- /* @__PURE__ */ jsx17(Building2, { className: "h-4 w-4" }),
1939
- /* @__PURE__ */ jsxs13("div", { className: "flex flex-col", children: [
1940
- /* @__PURE__ */ jsx17("span", { className: "font-medium", children: org.display_name }),
1941
- !compact && org.description && /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground truncate max-w-40", children: org.description })
1988
+ children: /* @__PURE__ */ jsxs14("div", { className: "flex items-center justify-between w-full", children: [
1989
+ /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-2", children: [
1990
+ /* @__PURE__ */ jsx18(Building2, { className: "h-4 w-4" }),
1991
+ /* @__PURE__ */ jsxs14("div", { className: "flex flex-col", children: [
1992
+ /* @__PURE__ */ jsx18("span", { className: "font-medium", children: org.display_name }),
1993
+ !compact && org.description && /* @__PURE__ */ jsx18("span", { className: "text-xs text-muted-foreground truncate max-w-40", children: org.description })
1942
1994
  ] })
1943
1995
  ] }),
1944
- showRole && /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1 ml-4", children: [
1945
- /* @__PURE__ */ jsx17(Shield, { className: "h-3 w-3 text-muted-foreground" }),
1946
- /* @__PURE__ */ jsx17("span", { className: "text-xs text-muted-foreground capitalize", children: userRole?.replace("_", " ") || "No Role" })
1996
+ showRole && /* @__PURE__ */ jsxs14("div", { className: "flex items-center gap-1 ml-4", children: [
1997
+ /* @__PURE__ */ jsx18(Shield, { className: "h-3 w-3 text-muted-foreground" }),
1998
+ /* @__PURE__ */ jsx18("span", { className: "text-xs text-muted-foreground capitalize", children: userRole?.replace("_", " ") || "No Role" })
1947
1999
  ] })
1948
2000
  ] })
1949
2001
  },
@@ -1960,7 +2012,7 @@ function OrganisationSelector({
1960
2012
  // src/components/PasswordReset/PasswordResetForm.tsx
1961
2013
  import { useState as useState8 } from "react";
1962
2014
  init_UnifiedAuthProvider2();
1963
- import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
2015
+ import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
1964
2016
  function PasswordResetForm({
1965
2017
  onSuccess,
1966
2018
  onError,
@@ -2001,13 +2053,13 @@ function PasswordResetForm({
2001
2053
  setError(null);
2002
2054
  };
2003
2055
  if (isSuccess) {
2004
- return /* @__PURE__ */ jsx18("div", { className: cn("", className), role: "form", children: /* @__PURE__ */ jsxs14("div", { className: "space-y-4 text-center", children: [
2005
- /* @__PURE__ */ jsx18("h2", { children: "Check your email" }),
2006
- /* @__PURE__ */ jsxs14("p", { className: "text-sec-600", children: [
2056
+ return /* @__PURE__ */ jsx19("div", { className: cn("", className), role: "form", children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4 text-center", children: [
2057
+ /* @__PURE__ */ jsx19("h2", { children: "Check your email" }),
2058
+ /* @__PURE__ */ jsxs15("p", { className: "text-sec-600", children: [
2007
2059
  "We have sent a password reset link to ",
2008
2060
  email
2009
2061
  ] }),
2010
- /* @__PURE__ */ jsx18(
2062
+ /* @__PURE__ */ jsx19(
2011
2063
  Button,
2012
2064
  {
2013
2065
  variant: "outline",
@@ -2018,15 +2070,15 @@ function PasswordResetForm({
2018
2070
  )
2019
2071
  ] }) });
2020
2072
  }
2021
- return /* @__PURE__ */ jsx18("div", { className: cn("", className), role: "form", children: /* @__PURE__ */ jsxs14("div", { className: "space-y-4", children: [
2022
- /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
2023
- /* @__PURE__ */ jsx18("h2", { children: "Reset Password" }),
2024
- /* @__PURE__ */ jsx18("p", { className: "text-sec-600", children: "Enter your email address and we'll send you a reset link." })
2073
+ return /* @__PURE__ */ jsx19("div", { className: cn("", className), role: "form", children: /* @__PURE__ */ jsxs15("div", { className: "space-y-4", children: [
2074
+ /* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
2075
+ /* @__PURE__ */ jsx19("h2", { children: "Reset Password" }),
2076
+ /* @__PURE__ */ jsx19("p", { className: "text-sec-600", children: "Enter your email address and we'll send you a reset link." })
2025
2077
  ] }),
2026
- /* @__PURE__ */ jsxs14("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
2027
- /* @__PURE__ */ jsxs14("div", { className: "space-y-2", children: [
2028
- /* @__PURE__ */ jsx18(Label, { htmlFor: "email", children: "Email Address" }),
2029
- /* @__PURE__ */ jsx18(
2078
+ /* @__PURE__ */ jsxs15("form", { onSubmit: handleSubmit, className: "space-y-4", children: [
2079
+ /* @__PURE__ */ jsxs15("div", { className: "space-y-2", children: [
2080
+ /* @__PURE__ */ jsx19(Label, { htmlFor: "email", children: "Email Address" }),
2081
+ /* @__PURE__ */ jsx19(
2030
2082
  Input,
2031
2083
  {
2032
2084
  id: "email",
@@ -2039,8 +2091,8 @@ function PasswordResetForm({
2039
2091
  }
2040
2092
  )
2041
2093
  ] }),
2042
- error && /* @__PURE__ */ jsx18("div", { className: "text-sm text-destructive", role: "alert", children: error }),
2043
- /* @__PURE__ */ jsx18(
2094
+ error && /* @__PURE__ */ jsx19("div", { className: "text-sm text-destructive", role: "alert", children: error }),
2095
+ /* @__PURE__ */ jsx19(
2044
2096
  Button,
2045
2097
  {
2046
2098
  type: "submit",
@@ -2053,513 +2105,47 @@ function PasswordResetForm({
2053
2105
  ] }) });
2054
2106
  }
2055
2107
 
2056
- // src/utils/storage/config.ts
2057
- var FILE_SIZE_LIMITS = {
2058
- // Images
2059
- "image/jpeg": 5 * 1024 * 1024,
2060
- // 5MB
2061
- "image/png": 5 * 1024 * 1024,
2062
- // 5MB
2063
- "image/gif": 10 * 1024 * 1024,
2064
- // 10MB (for animations)
2065
- "image/webp": 5 * 1024 * 1024,
2066
- // 5MB
2067
- "image/svg+xml": 1 * 1024 * 1024,
2068
- // 1MB (vector graphics)
2069
- // Documents
2070
- "application/pdf": 50 * 1024 * 1024,
2071
- // 50MB
2072
- "application/msword": 25 * 1024 * 1024,
2073
- // 25MB
2074
- "application/vnd.openxmlformats-officedocument.wordprocessingml.document": 25 * 1024 * 1024,
2075
- // 25MB
2076
- "application/vnd.ms-excel": 25 * 1024 * 1024,
2077
- // 25MB
2078
- "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": 25 * 1024 * 1024,
2079
- // 25MB
2080
- // Archives
2081
- "application/zip": 100 * 1024 * 1024,
2082
- // 100MB
2083
- "application/x-rar-compressed": 100 * 1024 * 1024,
2084
- // 100MB
2085
- // Text files
2086
- "text/plain": 1 * 1024 * 1024,
2087
- // 1MB
2088
- "text/csv": 10 * 1024 * 1024,
2089
- // 10MB
2090
- "application/json": 10 * 1024 * 1024
2091
- // 10MB
2092
- };
2093
- var DEFAULT_FILE_SIZE_LIMIT = 10 * 1024 * 1024;
2094
- var APP_PATH_MAPPING = {
2095
- "PACE": "event_logos",
2096
- "TRAC": "trac_accommodation",
2097
- // Default category for TRAC files
2098
- "MEDI": "documents",
2099
- "CAKE": "documents"
2100
- };
2101
- var STORAGE_CONFIG = {
2102
- bucketName: "files",
2103
- fileSizeLimits: FILE_SIZE_LIMITS,
2104
- defaultFileSizeLimit: DEFAULT_FILE_SIZE_LIMIT
2105
- };
2106
- function getFileSizeLimit(mimeType) {
2107
- return STORAGE_CONFIG.fileSizeLimits[mimeType] || STORAGE_CONFIG.defaultFileSizeLimit;
2108
- }
2109
- function validateFileSize(file) {
2110
- const limit = getFileSizeLimit(file.type);
2111
- if (file.size > limit) {
2112
- const limitMB = Math.round(limit / (1024 * 1024));
2113
- const fileMB = Math.round(file.size / (1024 * 1024));
2114
- return {
2115
- isValid: false,
2116
- error: `File size (${fileMB}MB) exceeds limit (${limitMB}MB) for ${file.type}`
2117
- };
2118
- }
2119
- return { isValid: true };
2120
- }
2121
- function formatFileSize(bytes) {
2122
- if (bytes === 0) return "0 Bytes";
2123
- if (bytes < 0) return `${bytes} Bytes`;
2124
- const k = 1024;
2125
- const sizes = ["Bytes", "KB", "MB", "GB", "TB"];
2126
- const i = Math.floor(Math.log(bytes) / Math.log(k));
2127
- const sizeIndex = Math.min(Math.max(i, 0), sizes.length - 1);
2128
- return parseFloat((bytes / Math.pow(k, sizeIndex)).toFixed(2)) + " " + sizes[sizeIndex];
2129
- }
2130
-
2131
- // src/utils/storage/helpers.ts
2132
- function generateFilePath(options, fileName) {
2133
- const { orgId, isPublic = false, customPath } = options;
2134
- if (isPublic) {
2135
- if (customPath) {
2136
- return `${orgId}/${customPath}/${fileName}`;
2137
- }
2138
- return `${orgId}/public/${fileName}`;
2139
- }
2140
- if (customPath) {
2141
- return `${orgId}/${customPath}/${fileName}`;
2142
- }
2143
- const pathCategory = customPath || "files";
2144
- return `${orgId}/${pathCategory}/${fileName}`;
2145
- }
2146
- function generateUniqueFileName(originalName) {
2147
- const timestamp = Date.now();
2148
- const uuid = crypto.randomUUID();
2149
- const extension = originalName.split(".").pop() || "";
2150
- const baseName = originalName.replace(/\.[^/.]+$/, "");
2151
- if (!extension || extension === originalName) {
2152
- return `${timestamp}-${uuid}-${baseName}`;
2153
- }
2154
- return `${timestamp}-${uuid}-${baseName}.${extension}`;
2155
- }
2156
- async function extractFileMetadata(file, options, uploadedBy) {
2157
- const metadata = {
2158
- mimeType: file.type,
2159
- size: file.size,
2160
- orgId: options.orgId,
2161
- appName: options.appName || "pace-core",
2162
- uploadedBy,
2163
- uploadedAt: (/* @__PURE__ */ new Date()).toISOString(),
2164
- tags: options.tags || [],
2165
- isPublic: options.isPublic || false,
2166
- customMetadata: options.metadata || {}
2167
- };
2168
- if (file.type.startsWith("image/")) {
2169
- try {
2170
- const dimensions = await getImageDimensions(file);
2171
- metadata.width = dimensions.width;
2172
- metadata.height = dimensions.height;
2173
- } catch (error) {
2174
- console.warn("Could not extract image dimensions:", error);
2175
- }
2176
- }
2177
- try {
2178
- metadata.hash = await generateFileHash(file);
2179
- } catch (error) {
2180
- console.warn("Could not generate file hash:", error);
2181
- }
2182
- return metadata;
2183
- }
2184
- async function getImageDimensions(file) {
2185
- return new Promise((resolve, reject) => {
2186
- const img = new Image();
2187
- const url = URL.createObjectURL(file);
2188
- img.onload = () => {
2189
- URL.revokeObjectURL(url);
2190
- resolve({ width: img.width, height: img.height });
2191
- };
2192
- img.onerror = () => {
2193
- URL.revokeObjectURL(url);
2194
- reject(new Error("Could not load image"));
2195
- };
2196
- img.src = url;
2197
- });
2198
- }
2199
- async function generateFileHash(file) {
2200
- const buffer = await file.arrayBuffer();
2201
- const hashBuffer = await crypto.subtle.digest("SHA-256", buffer);
2202
- const hashArray = Array.from(new Uint8Array(hashBuffer));
2203
- const hashHex = hashArray.map((b) => b.toString(16).padStart(2, "0")).join("");
2204
- return `sha256:${hashHex}`;
2205
- }
2206
- async function uploadFile(supabase, file, options) {
2207
- try {
2208
- const sizeValidation = validateFileSize(file);
2209
- if (!sizeValidation.isValid) {
2210
- return {
2211
- success: false,
2212
- error: sizeValidation.error
2213
- };
2214
- }
2215
- const uniqueFileName = generateUniqueFileName(file.name);
2216
- const filePath = generateFilePath(options, uniqueFileName);
2217
- const metadata = await extractFileMetadata(file, options, "current-user");
2218
- const { data, error } = await supabase.storage.from(STORAGE_CONFIG.bucketName).upload(filePath, file, {
2219
- cacheControl: "3600",
2220
- upsert: false,
2221
- contentType: file.type
2222
- });
2223
- if (error) {
2224
- return {
2225
- success: false,
2226
- error: `Upload failed: ${error.message}`
2227
- };
2228
- }
2229
- let publicUrl;
2230
- if (options.isPublic) {
2231
- const { data: urlData } = supabase.storage.from(STORAGE_CONFIG.bucketName).getPublicUrl(filePath);
2232
- publicUrl = urlData.publicUrl;
2233
- }
2234
- return {
2235
- success: true,
2236
- path: filePath,
2237
- publicUrl,
2238
- metadata
2239
- };
2240
- } catch (error) {
2241
- return {
2242
- success: false,
2243
- error: `Upload failed: ${error instanceof Error ? error.message : "Unknown error"}`
2244
- };
2245
- }
2246
- }
2247
- function getPublicUrl(supabase, path) {
2248
- const { data } = supabase.storage.from(STORAGE_CONFIG.bucketName).getPublicUrl(path);
2249
- return data.publicUrl;
2250
- }
2251
- async function getSignedUrl(supabase, path, options) {
2252
- try {
2253
- const { data, error } = await supabase.storage.from(STORAGE_CONFIG.bucketName).createSignedUrl(path, options.expiresIn || 3600);
2254
- if (error) {
2255
- console.error("Failed to create signed URL:", error);
2256
- return null;
2257
- }
2258
- return {
2259
- url: data.signedUrl,
2260
- expiresAt: new Date(Date.now() + (options.expiresIn || 3600) * 1e3).toISOString()
2261
- };
2262
- } catch (error) {
2263
- console.error("Failed to create signed URL:", error);
2264
- return null;
2265
- }
2266
- }
2267
- async function deleteFile(supabase, path) {
2268
- try {
2269
- const { error } = await supabase.storage.from(STORAGE_CONFIG.bucketName).remove([path]);
2270
- if (error) {
2271
- return {
2272
- success: false,
2273
- error: `Delete failed: ${error.message}`
2274
- };
2275
- }
2276
- return { success: true };
2277
- } catch (error) {
2278
- return {
2279
- success: false,
2280
- error: `Delete failed: ${error instanceof Error ? error.message : "Unknown error"}`
2281
- };
2282
- }
2283
- }
2284
- async function listFiles(supabase, options) {
2285
- try {
2286
- const pathPrefix = `${options.orgId}/`;
2287
- const searchPath = options.pathPrefix ? `${pathPrefix}${options.pathPrefix}` : pathPrefix;
2288
- const { data, error } = await supabase.storage.from(STORAGE_CONFIG.bucketName).list(searchPath, {
2289
- limit: options.limit || 100,
2290
- offset: options.offset || 0,
2291
- sortBy: { column: "created_at", order: "desc" }
2292
- });
2293
- if (error) {
2294
- console.error("Failed to list files:", error);
2295
- return { files: [], totalCount: 0, hasMore: false };
2296
- }
2297
- const files = (data || []).map((item) => ({
2298
- name: item.name,
2299
- path: `${searchPath}${item.name}`,
2300
- size: item.metadata?.size || 0,
2301
- mimeType: item.metadata?.mimetype || "application/octet-stream",
2302
- lastModified: item.updated_at || item.created_at || (/* @__PURE__ */ new Date()).toISOString(),
2303
- metadata: {
2304
- mimeType: item.metadata?.mimetype || "application/octet-stream",
2305
- size: item.metadata?.size || 0,
2306
- orgId: options.orgId,
2307
- appName: options.appName,
2308
- uploadedBy: "unknown",
2309
- uploadedAt: item.created_at || (/* @__PURE__ */ new Date()).toISOString(),
2310
- isPublic: false
2311
- }
2312
- }));
2313
- return {
2314
- files,
2315
- totalCount: files.length,
2316
- hasMore: files.length >= (options.limit || 100)
2317
- };
2318
- } catch (error) {
2319
- console.error("Failed to list files:", error);
2320
- return { files: [], totalCount: 0, hasMore: false };
2321
- }
2322
- }
2323
- async function archiveFile(supabase, path, options) {
2324
- try {
2325
- const archivedPath = path.replace(`${options.orgId}/`, `archived/${options.orgId}/`);
2326
- const { error: copyError } = await supabase.storage.from(STORAGE_CONFIG.bucketName).copy(path, archivedPath);
2327
- if (copyError) {
2328
- return {
2329
- success: false,
2330
- error: `Archive failed: ${copyError.message}`
2331
- };
2332
- }
2333
- const deleteResult = await deleteFile(supabase, path);
2334
- if (!deleteResult.success) {
2335
- return deleteResult;
2336
- }
2337
- return { success: true };
2338
- } catch (error) {
2339
- return {
2340
- success: false,
2341
- error: `Archive failed: ${error instanceof Error ? error.message : "Unknown error"}`
2342
- };
2343
- }
2344
- }
2345
-
2346
- // src/utils/storage/index.ts
2347
- var StorageUtils = class {
2348
- };
2349
- StorageUtils.generateFilePath = generateFilePath;
2350
- StorageUtils.generateUniqueFileName = generateUniqueFileName;
2351
- StorageUtils.extractFileMetadata = extractFileMetadata;
2352
- StorageUtils.uploadFile = uploadFile;
2353
- StorageUtils.getPublicUrl = getPublicUrl;
2354
- StorageUtils.getSignedUrl = getSignedUrl;
2355
- StorageUtils.deleteFile = deleteFile;
2356
- StorageUtils.listFiles = listFiles;
2357
- StorageUtils.archiveFile = archiveFile;
2358
-
2359
- // src/hooks/useStorage.ts
2360
- import { useState as useState9, useCallback as useCallback5 } from "react";
2361
- function useStorage({ supabase, appName, orgId }) {
2362
- const [isUploading, setIsUploading] = useState9(false);
2363
- const [uploadError, setUploadError] = useState9(null);
2364
- const [isListing, setIsListing] = useState9(false);
2365
- const [listError, setListError] = useState9(null);
2366
- const [files, setFiles] = useState9([]);
2367
- const handleUploadFile = useCallback5(async (file, options = {}) => {
2368
- setIsUploading(true);
2369
- setUploadError(null);
2370
- try {
2371
- const uploadOptions = {
2372
- appName,
2373
- orgId,
2374
- isPublic: false,
2375
- ...options
2376
- };
2377
- const result = await uploadFile(supabase, file, uploadOptions);
2378
- if (result.success) {
2379
- await refreshFiles();
2380
- } else {
2381
- setUploadError(result.error || "Upload failed");
2382
- }
2383
- return result;
2384
- } catch (error) {
2385
- const errorMessage = error instanceof Error ? error.message : "Upload failed";
2386
- setUploadError(errorMessage);
2387
- return {
2388
- success: false,
2389
- error: errorMessage
2390
- };
2391
- } finally {
2392
- setIsUploading(false);
2393
- }
2394
- }, [supabase, appName, orgId]);
2395
- const handleGetPublicUrl = useCallback5((path) => {
2396
- return getPublicUrl(supabase, path);
2397
- }, [supabase]);
2398
- const handleGetSignedUrl = useCallback5(async (path, expiresIn) => {
2399
- try {
2400
- const result = await getSignedUrl(supabase, path, {
2401
- appName,
2402
- orgId,
2403
- expiresIn
2404
- });
2405
- return result?.url || null;
2406
- } catch (error) {
2407
- console.error("Failed to get signed URL:", error);
2408
- return null;
2409
- }
2410
- }, [supabase, appName, orgId]);
2411
- const handleDeleteFile = useCallback5(async (path) => {
2412
- try {
2413
- const result = await deleteFile(supabase, path);
2414
- if (result.success) {
2415
- await refreshFiles();
2416
- }
2417
- return result;
2418
- } catch (error) {
2419
- return {
2420
- success: false,
2421
- error: error instanceof Error ? error.message : "Delete failed"
2422
- };
2423
- }
2424
- }, [supabase]);
2425
- const handleArchiveFile = useCallback5(async (path) => {
2426
- try {
2427
- const result = await archiveFile(supabase, path, { appName, orgId });
2428
- if (result.success) {
2429
- await refreshFiles();
2430
- }
2431
- return result;
2432
- } catch (error) {
2433
- return {
2434
- success: false,
2435
- error: error instanceof Error ? error.message : "Archive failed"
2436
- };
2437
- }
2438
- }, [supabase, appName, orgId]);
2439
- const handleListFiles = useCallback5(async (options = {}) => {
2440
- setIsListing(true);
2441
- setListError(null);
2442
- try {
2443
- const listOptions = {
2444
- appName,
2445
- orgId,
2446
- ...options
2447
- };
2448
- const result = await listFiles(supabase, listOptions);
2449
- setFiles(result.files);
2450
- return result;
2451
- } catch (error) {
2452
- const errorMessage = error instanceof Error ? error.message : "List failed";
2453
- setListError(errorMessage);
2454
- return { files: [], totalCount: 0, hasMore: false };
2455
- } finally {
2456
- setIsListing(false);
2457
- }
2458
- }, [supabase, appName, orgId]);
2459
- const refreshFiles = useCallback5(async () => {
2460
- await handleListFiles();
2461
- }, [handleListFiles]);
2462
- return {
2463
- // Upload
2464
- uploadFile: handleUploadFile,
2465
- isUploading,
2466
- uploadError,
2467
- // URLs
2468
- getPublicUrl: handleGetPublicUrl,
2469
- getSignedUrl: handleGetSignedUrl,
2470
- getFileUrl: handleGetPublicUrl,
2471
- // Alias for getPublicUrl
2472
- // File management
2473
- deleteFile: handleDeleteFile,
2474
- archiveFile: handleArchiveFile,
2475
- // Listing
2476
- listFiles: handleListFiles,
2477
- isListing,
2478
- listError,
2479
- isLoading: isListing,
2480
- // Alias for isListing
2481
- error: listError,
2482
- // Alias for listError
2483
- // State
2484
- files,
2485
- refreshFiles
2486
- };
2487
- }
2488
- function useFileUpload({ supabase, appName, orgId }) {
2489
- const [uploadProgress, setUploadProgress] = useState9(0);
2490
- const [isUploading, setIsUploading] = useState9(false);
2491
- const [uploadError, setUploadError] = useState9(null);
2492
- const uploadWithProgress = useCallback5(async (file, options = {}) => {
2493
- setIsUploading(true);
2494
- setUploadProgress(0);
2495
- setUploadError(null);
2496
- try {
2497
- const progressInterval = setInterval(() => {
2498
- setUploadProgress((prev) => Math.min(prev + 10, 90));
2499
- }, 100);
2500
- const uploadOptions = {
2501
- appName,
2502
- orgId,
2503
- isPublic: false,
2504
- ...options
2505
- };
2506
- const result = await uploadFile(supabase, file, uploadOptions);
2507
- clearInterval(progressInterval);
2508
- setUploadProgress(100);
2509
- if (!result.success) {
2510
- setUploadError(result.error || "Upload failed");
2511
- }
2512
- return result;
2513
- } catch (error) {
2514
- const errorMessage = error instanceof Error ? error.message : "Upload failed";
2515
- setUploadError(errorMessage);
2516
- return {
2517
- success: false,
2518
- error: errorMessage
2519
- };
2520
- } finally {
2521
- setIsUploading(false);
2522
- setTimeout(() => setUploadProgress(0), 1e3);
2523
- }
2524
- }, [supabase, appName, orgId]);
2525
- return {
2526
- uploadWithProgress,
2527
- uploadProgress,
2528
- isUploading,
2529
- uploadError
2530
- };
2531
- }
2532
-
2533
2108
  // src/hooks/useFileReference.ts
2534
- import { useState as useState10, useCallback as useCallback6 } from "react";
2109
+ import { useState as useState9, useCallback as useCallback5, useEffect as useEffect5, useRef as useRef2, useMemo as useMemo6 } from "react";
2535
2110
 
2536
2111
  // src/utils/file-reference.ts
2112
+ init_organisationContext();
2537
2113
  var FileReferenceServiceImpl = class {
2538
2114
  constructor(supabase) {
2539
2115
  this.supabase = supabase;
2540
2116
  }
2541
2117
  async createFileReference(options, file) {
2542
2118
  try {
2543
- const filePath = generateFilePath({
2544
- appName: "file-reference",
2545
- orgId: options.organisation_id,
2546
- isPublic: options.is_public || false
2547
- }, file.name);
2119
+ if (!options.organisation_id) {
2120
+ throw new Error("organisation_id is required for file upload");
2121
+ }
2122
+ if (!options.table_name) {
2123
+ throw new Error("table_name is required for file upload");
2124
+ }
2125
+ if (!options.record_id) {
2126
+ throw new Error("record_id is required for file upload");
2127
+ }
2548
2128
  const uploadResult = await uploadFile(this.supabase, file, {
2549
2129
  appName: "file-reference",
2550
2130
  orgId: options.organisation_id,
2551
2131
  isPublic: options.is_public || false,
2552
- customPath: filePath
2132
+ customPath: options.category
2133
+ // Use category as the custom path
2553
2134
  });
2554
2135
  if (!uploadResult.success) {
2555
2136
  throw new Error(`Failed to upload file: ${uploadResult.error}`);
2556
2137
  }
2138
+ if (!uploadResult.path) {
2139
+ throw new Error("File upload did not return a path");
2140
+ }
2141
+ const filePath = uploadResult.path;
2557
2142
  const metadata = await extractFileMetadata(file, {
2558
2143
  appName: "file-reference",
2559
2144
  orgId: options.organisation_id,
2560
2145
  isPublic: options.is_public || false
2561
2146
  }, "system");
2562
- const { data, error } = await this.supabase.rpc("insert_file_reference", {
2147
+ await setOrganisationContext(this.supabase, options.organisation_id);
2148
+ const { data, error } = await this.supabase.rpc("data_file_reference_create", {
2563
2149
  p_table_name: options.table_name,
2564
2150
  p_record_id: options.record_id,
2565
2151
  p_file_path: filePath,
@@ -2576,7 +2162,7 @@ var FileReferenceServiceImpl = class {
2576
2162
  p_is_public: options.is_public || false
2577
2163
  });
2578
2164
  if (error) {
2579
- await deleteFile(this.supabase, filePath);
2165
+ await deleteFile(this.supabase, filePath, options.is_public || false);
2580
2166
  throw new Error(`Failed to create file reference: ${error.message}`);
2581
2167
  }
2582
2168
  const { data: fileRef, error: fetchError } = await this.supabase.from("file_references").select("*").eq("id", data).single();
@@ -2606,15 +2192,23 @@ var FileReferenceServiceImpl = class {
2606
2192
  }
2607
2193
  async getFileUrl(table_name, record_id, organisation_id) {
2608
2194
  try {
2609
- const { data, error } = await this.supabase.rpc("get_file_url", {
2610
- p_table_name: table_name,
2611
- p_record_id: record_id,
2612
- p_organisation_id: organisation_id
2613
- });
2614
- if (error) {
2615
- throw new Error(`Failed to get file URL: ${error.message}`);
2195
+ const fileRef = await this.getFileReference(table_name, record_id, organisation_id);
2196
+ if (!fileRef) {
2197
+ return null;
2198
+ }
2199
+ if (fileRef.is_public) {
2200
+ const { data: pathData } = await this.supabase.rpc("data_file_reference_url_get", {
2201
+ p_table_name: table_name,
2202
+ p_record_id: record_id,
2203
+ p_organisation_id: organisation_id
2204
+ });
2205
+ if (!pathData) {
2206
+ return null;
2207
+ }
2208
+ return getPublicUrl(this.supabase, pathData, true);
2209
+ } else {
2210
+ return await this.getSignedUrl(table_name, record_id, organisation_id);
2616
2211
  }
2617
- return data;
2618
2212
  } catch (error) {
2619
2213
  console.error("Error getting file URL:", error);
2620
2214
  throw error;
@@ -2622,7 +2216,7 @@ var FileReferenceServiceImpl = class {
2622
2216
  }
2623
2217
  async getSignedUrl(table_name, record_id, organisation_id, expires_in = 3600) {
2624
2218
  try {
2625
- const { data, error } = await this.supabase.rpc("get_file_signed_url", {
2219
+ const { data: filePath, error } = await this.supabase.rpc("data_file_reference_signed_url_get", {
2626
2220
  p_table_name: table_name,
2627
2221
  p_record_id: record_id,
2628
2222
  p_organisation_id: organisation_id,
@@ -2631,7 +2225,15 @@ var FileReferenceServiceImpl = class {
2631
2225
  if (error) {
2632
2226
  throw new Error(`Failed to get signed URL: ${error.message}`);
2633
2227
  }
2634
- return data;
2228
+ if (!filePath) {
2229
+ return null;
2230
+ }
2231
+ const signedUrlResult = await getSignedUrl(this.supabase, filePath, {
2232
+ appName: "file-reference",
2233
+ orgId: organisation_id,
2234
+ expiresIn: expires_in
2235
+ });
2236
+ return signedUrlResult?.url || null;
2635
2237
  } catch (error) {
2636
2238
  console.error("Error getting signed URL:", error);
2637
2239
  throw error;
@@ -2651,7 +2253,8 @@ var FileReferenceServiceImpl = class {
2651
2253
  }
2652
2254
  async deleteFileReference(table_name, record_id, organisation_id, delete_file = false) {
2653
2255
  try {
2654
- const { error } = await this.supabase.rpc("delete_file_reference", {
2256
+ const fileRef = await this.getFileReference(table_name, record_id, organisation_id);
2257
+ const { error } = await this.supabase.rpc("data_file_reference_delete", {
2655
2258
  p_table_name: table_name,
2656
2259
  p_record_id: record_id,
2657
2260
  p_organisation_id: organisation_id,
@@ -2660,6 +2263,9 @@ var FileReferenceServiceImpl = class {
2660
2263
  if (error) {
2661
2264
  throw new Error(`Failed to delete file reference: ${error.message}`);
2662
2265
  }
2266
+ if (delete_file && fileRef) {
2267
+ await deleteFile(this.supabase, fileRef.file_path, fileRef.is_public || false);
2268
+ }
2663
2269
  return true;
2664
2270
  } catch (error) {
2665
2271
  console.error("Error deleting file reference:", error);
@@ -2668,7 +2274,7 @@ var FileReferenceServiceImpl = class {
2668
2274
  }
2669
2275
  async listFileReferences(table_name, record_id, organisation_id) {
2670
2276
  try {
2671
- const { data, error } = await this.supabase.rpc("get_record_files", {
2277
+ const { data, error } = await this.supabase.rpc("data_file_reference_list", {
2672
2278
  p_table_name: table_name,
2673
2279
  p_record_id: record_id,
2674
2280
  p_organisation_id: organisation_id
@@ -2676,7 +2282,15 @@ var FileReferenceServiceImpl = class {
2676
2282
  if (error) {
2677
2283
  throw new Error(`Failed to list file references: ${error.message}`);
2678
2284
  }
2679
- return data;
2285
+ if (!data || data.length === 0) {
2286
+ return [];
2287
+ }
2288
+ const ids = data.map((item) => item.id);
2289
+ const { data: fullData, error: fetchError } = await this.supabase.from("file_references").select("*").in("id", ids);
2290
+ if (fetchError) {
2291
+ throw new Error(`Failed to fetch file references: ${fetchError.message}`);
2292
+ }
2293
+ return fullData || [];
2680
2294
  } catch (error) {
2681
2295
  console.error("Error listing file references:", error);
2682
2296
  throw error;
@@ -2684,7 +2298,7 @@ var FileReferenceServiceImpl = class {
2684
2298
  }
2685
2299
  async getFileCount(table_name, record_id, organisation_id) {
2686
2300
  try {
2687
- const { data, error } = await this.supabase.rpc("get_record_file_count", {
2301
+ const { data, error } = await this.supabase.rpc("data_file_reference_count_get", {
2688
2302
  p_table_name: table_name,
2689
2303
  p_record_id: record_id,
2690
2304
  p_organisation_id: organisation_id
@@ -2698,6 +2312,78 @@ var FileReferenceServiceImpl = class {
2698
2312
  throw error;
2699
2313
  }
2700
2314
  }
2315
+ async getFileReferenceById(id, organisation_id) {
2316
+ try {
2317
+ const { data, error } = await this.supabase.rpc("data_file_reference_get", {
2318
+ p_file_reference_id: id,
2319
+ p_organisation_id: organisation_id
2320
+ });
2321
+ if (error) {
2322
+ throw new Error(`Failed to get file reference by ID: ${error.message}`);
2323
+ }
2324
+ if (!data || data.length === 0) {
2325
+ return null;
2326
+ }
2327
+ return data[0];
2328
+ } catch (error) {
2329
+ console.error("Error getting file reference by ID:", error);
2330
+ throw error;
2331
+ }
2332
+ }
2333
+ async getFilesByCategory(table_name, record_id, category, organisation_id) {
2334
+ try {
2335
+ const { data, error } = await this.supabase.rpc("data_file_reference_by_category_list", {
2336
+ p_table_name: table_name,
2337
+ p_record_id: record_id,
2338
+ p_category: category,
2339
+ p_organisation_id: organisation_id
2340
+ });
2341
+ if (error) {
2342
+ throw new Error(`Failed to get files by category: ${error.message}`);
2343
+ }
2344
+ if (!data || data.length === 0) {
2345
+ return [];
2346
+ }
2347
+ const ids = data.map((item) => item.id);
2348
+ const { data: fullData, error: fetchError } = await this.supabase.from("file_references").select("*").in("id", ids);
2349
+ if (fetchError) {
2350
+ throw new Error(`Failed to fetch file references: ${fetchError.message}`);
2351
+ }
2352
+ return fullData || [];
2353
+ } catch (error) {
2354
+ console.error("Error getting files by category:", error);
2355
+ throw error;
2356
+ }
2357
+ }
2358
+ async uploadMultipleFiles(options, files) {
2359
+ const success = [];
2360
+ const failed = [];
2361
+ const results = [];
2362
+ for (const file of files) {
2363
+ try {
2364
+ const fileReference = await this.createFileReference(options, file);
2365
+ success.push(fileReference);
2366
+ results.push({
2367
+ file,
2368
+ result: {
2369
+ file_reference: fileReference,
2370
+ file_url: fileReference.is_public ? getPublicUrl(this.supabase, fileReference.file_path, true) : ""
2371
+ }
2372
+ });
2373
+ } catch (error) {
2374
+ const message = error instanceof Error ? error.message : "Unknown error";
2375
+ failed.push({ file, error: message });
2376
+ results.push({ file, result: null, error: message });
2377
+ }
2378
+ }
2379
+ return {
2380
+ success,
2381
+ failed,
2382
+ total: results.length,
2383
+ successful: success.length,
2384
+ results
2385
+ };
2386
+ }
2701
2387
  };
2702
2388
  function createFileReferenceService(supabase) {
2703
2389
  return new FileReferenceServiceImpl(supabase);
@@ -2705,7 +2391,7 @@ function createFileReferenceService(supabase) {
2705
2391
  async function uploadFileWithReference(supabase, options, file) {
2706
2392
  const service = createFileReferenceService(supabase);
2707
2393
  const fileReference = await service.createFileReference(options, file);
2708
- const fileUrl = options.is_public ? getPublicUrl(supabase, fileReference.file_path) : await getSignedUrl(supabase, fileReference.file_path, {
2394
+ const fileUrl = options.is_public ? getPublicUrl(supabase, fileReference.file_path, true) : await getSignedUrl(supabase, fileReference.file_path, {
2709
2395
  appName: "file-reference",
2710
2396
  orgId: options.organisation_id,
2711
2397
  expiresIn: 3600
@@ -2720,10 +2406,10 @@ async function uploadFileWithReference(supabase, options, file) {
2720
2406
 
2721
2407
  // src/hooks/useFileReference.ts
2722
2408
  function useFileReference(supabase) {
2723
- const [isLoading, setIsLoading] = useState10(false);
2724
- const [error, setError] = useState10(null);
2725
- const service = createFileReferenceService(supabase);
2726
- const uploadFile2 = useCallback6(async (options, file) => {
2409
+ const [isLoading, setIsLoading] = useState9(false);
2410
+ const [error, setError] = useState9(null);
2411
+ const service = useMemo6(() => createFileReferenceService(supabase), [supabase]);
2412
+ const uploadFile2 = useCallback5(async (options, file) => {
2727
2413
  setIsLoading(true);
2728
2414
  setError(null);
2729
2415
  try {
@@ -2737,7 +2423,7 @@ function useFileReference(supabase) {
2737
2423
  setIsLoading(false);
2738
2424
  }
2739
2425
  }, [supabase]);
2740
- const getFileReference = useCallback6(async (table_name, record_id, organisation_id) => {
2426
+ const getFileReference = useCallback5(async (table_name, record_id, organisation_id) => {
2741
2427
  setIsLoading(true);
2742
2428
  setError(null);
2743
2429
  try {
@@ -2750,7 +2436,7 @@ function useFileReference(supabase) {
2750
2436
  setIsLoading(false);
2751
2437
  }
2752
2438
  }, [service]);
2753
- const getFileUrl = useCallback6(async (table_name, record_id, organisation_id) => {
2439
+ const getFileUrl = useCallback5(async (table_name, record_id, organisation_id) => {
2754
2440
  setIsLoading(true);
2755
2441
  setError(null);
2756
2442
  try {
@@ -2763,7 +2449,7 @@ function useFileReference(supabase) {
2763
2449
  setIsLoading(false);
2764
2450
  }
2765
2451
  }, [service]);
2766
- const getSignedUrl2 = useCallback6(async (table_name, record_id, organisation_id, expires_in) => {
2452
+ const getSignedUrl2 = useCallback5(async (table_name, record_id, organisation_id, expires_in) => {
2767
2453
  setIsLoading(true);
2768
2454
  setError(null);
2769
2455
  try {
@@ -2776,7 +2462,7 @@ function useFileReference(supabase) {
2776
2462
  setIsLoading(false);
2777
2463
  }
2778
2464
  }, [service]);
2779
- const updateFileReference = useCallback6(async (id, updates) => {
2465
+ const updateFileReference = useCallback5(async (id, updates) => {
2780
2466
  setIsLoading(true);
2781
2467
  setError(null);
2782
2468
  try {
@@ -2789,7 +2475,7 @@ function useFileReference(supabase) {
2789
2475
  setIsLoading(false);
2790
2476
  }
2791
2477
  }, [service]);
2792
- const deleteFileReference = useCallback6(async (table_name, record_id, organisation_id, delete_file) => {
2478
+ const deleteFileReference = useCallback5(async (table_name, record_id, organisation_id, delete_file) => {
2793
2479
  setIsLoading(true);
2794
2480
  setError(null);
2795
2481
  try {
@@ -2802,7 +2488,7 @@ function useFileReference(supabase) {
2802
2488
  setIsLoading(false);
2803
2489
  }
2804
2490
  }, [service]);
2805
- const listFileReferences = useCallback6(async (table_name, record_id, organisation_id) => {
2491
+ const listFileReferences = useCallback5(async (table_name, record_id, organisation_id) => {
2806
2492
  setIsLoading(true);
2807
2493
  setError(null);
2808
2494
  try {
@@ -2815,7 +2501,7 @@ function useFileReference(supabase) {
2815
2501
  setIsLoading(false);
2816
2502
  }
2817
2503
  }, [service]);
2818
- const getFileCount = useCallback6(async (table_name, record_id, organisation_id) => {
2504
+ const getFileCount = useCallback5(async (table_name, record_id, organisation_id) => {
2819
2505
  setIsLoading(true);
2820
2506
  setError(null);
2821
2507
  try {
@@ -2828,7 +2514,33 @@ function useFileReference(supabase) {
2828
2514
  setIsLoading(false);
2829
2515
  }
2830
2516
  }, [service]);
2831
- const clearError = useCallback6(() => {
2517
+ const getFileReferenceById = useCallback5(async (id, organisation_id) => {
2518
+ setIsLoading(true);
2519
+ setError(null);
2520
+ try {
2521
+ return await service.getFileReferenceById(id, organisation_id);
2522
+ } catch (err) {
2523
+ const errorMessage = err instanceof Error ? err.message : "Failed to get file reference by ID";
2524
+ setError(errorMessage);
2525
+ return null;
2526
+ } finally {
2527
+ setIsLoading(false);
2528
+ }
2529
+ }, [service]);
2530
+ const getFilesByCategory = useCallback5(async (table_name, record_id, category, organisation_id) => {
2531
+ setIsLoading(true);
2532
+ setError(null);
2533
+ try {
2534
+ return await service.getFilesByCategory(table_name, record_id, category, organisation_id);
2535
+ } catch (err) {
2536
+ const errorMessage = err instanceof Error ? err.message : "Failed to get files by category";
2537
+ setError(errorMessage);
2538
+ return [];
2539
+ } finally {
2540
+ setIsLoading(false);
2541
+ }
2542
+ }, [service]);
2543
+ const clearError = useCallback5(() => {
2832
2544
  setError(null);
2833
2545
  }, []);
2834
2546
  return {
@@ -2836,11 +2548,13 @@ function useFileReference(supabase) {
2836
2548
  error,
2837
2549
  uploadFile: uploadFile2,
2838
2550
  getFileReference,
2551
+ getFileReferenceById,
2839
2552
  getFileUrl,
2840
2553
  getSignedUrl: getSignedUrl2,
2841
2554
  updateFileReference,
2842
2555
  deleteFileReference,
2843
2556
  listFileReferences,
2557
+ getFilesByCategory,
2844
2558
  getFileCount,
2845
2559
  clearError
2846
2560
  };
@@ -2857,31 +2571,32 @@ function useFileReferenceForRecord(supabase, table_name, record_id, organisation
2857
2571
  getFileCount,
2858
2572
  clearError
2859
2573
  } = useFileReference(supabase);
2860
- const [fileUrl, setFileUrl] = useState10(null);
2861
- const [fileReference, setFileReference] = useState10(null);
2862
- const [fileReferences, setFileReferences] = useState10([]);
2863
- const [fileCount, setFileCount] = useState10(0);
2864
- const loadFileReference = useCallback6(async () => {
2574
+ const [fileUrl, setFileUrl] = useState9(null);
2575
+ const [fileReference, setFileReference] = useState9(null);
2576
+ const [fileReferences, setFileReferences] = useState9([]);
2577
+ const [fileCount, setFileCount] = useState9(0);
2578
+ const urlRefreshIntervalRef = useRef2(null);
2579
+ const loadFileReference = useCallback5(async () => {
2865
2580
  const reference = await getFileReference(table_name, record_id, organisation_id);
2866
2581
  setFileReference(reference);
2867
2582
  return reference;
2868
2583
  }, [getFileReference, table_name, record_id, organisation_id]);
2869
- const loadFileUrl = useCallback6(async () => {
2584
+ const loadFileUrl = useCallback5(async () => {
2870
2585
  const url = await getFileUrl(table_name, record_id, organisation_id);
2871
2586
  setFileUrl(url);
2872
2587
  return url;
2873
2588
  }, [getFileUrl, table_name, record_id, organisation_id]);
2874
- const loadFileReferences = useCallback6(async () => {
2589
+ const loadFileReferences = useCallback5(async () => {
2875
2590
  const references = await listFileReferences(table_name, record_id, organisation_id);
2876
2591
  setFileReferences(references);
2877
2592
  return references;
2878
2593
  }, [listFileReferences, table_name, record_id, organisation_id]);
2879
- const loadFileCount = useCallback6(async () => {
2594
+ const loadFileCount = useCallback5(async () => {
2880
2595
  const count = await getFileCount(table_name, record_id, organisation_id);
2881
2596
  setFileCount(count);
2882
2597
  return count;
2883
2598
  }, [getFileCount, table_name, record_id, organisation_id]);
2884
- const deleteFile2 = useCallback6(async (delete_file) => {
2599
+ const deleteFile2 = useCallback5(async (delete_file) => {
2885
2600
  const success = await deleteFileReference(table_name, record_id, organisation_id, delete_file);
2886
2601
  if (success) {
2887
2602
  setFileReference(null);
@@ -2890,6 +2605,24 @@ function useFileReferenceForRecord(supabase, table_name, record_id, organisation
2890
2605
  }
2891
2606
  return success;
2892
2607
  }, [deleteFileReference, table_name, record_id, organisation_id, loadFileCount]);
2608
+ useEffect5(() => {
2609
+ if (!fileReference || fileReference.is_public) {
2610
+ if (urlRefreshIntervalRef.current) {
2611
+ clearInterval(urlRefreshIntervalRef.current);
2612
+ urlRefreshIntervalRef.current = null;
2613
+ }
2614
+ return;
2615
+ }
2616
+ urlRefreshIntervalRef.current = setInterval(() => {
2617
+ loadFileUrl();
2618
+ }, 55 * 60 * 1e3);
2619
+ return () => {
2620
+ if (urlRefreshIntervalRef.current) {
2621
+ clearInterval(urlRefreshIntervalRef.current);
2622
+ urlRefreshIntervalRef.current = null;
2623
+ }
2624
+ };
2625
+ }, [fileReference, loadFileUrl]);
2893
2626
  return {
2894
2627
  isLoading,
2895
2628
  error,
@@ -2906,11 +2639,579 @@ function useFileReferenceForRecord(supabase, table_name, record_id, organisation
2906
2639
  clearError
2907
2640
  };
2908
2641
  }
2909
-
2910
- // src/components/FileDisplay.tsx
2911
- import { useState as useState11, useEffect as useEffect5 } from "react";
2912
- import { jsx as jsx19, jsxs as jsxs15 } from "react/jsx-runtime";
2913
- function FileDisplay({
2642
+ function useFileReferenceById(supabase, fileReferenceId, organisationId) {
2643
+ const {
2644
+ isLoading,
2645
+ error,
2646
+ getFileReferenceById,
2647
+ clearError
2648
+ } = useFileReference(supabase);
2649
+ const [fileReference, setFileReference] = useState9(null);
2650
+ const [fileUrl, setFileUrl] = useState9(null);
2651
+ const loadFileReference = useCallback5(async () => {
2652
+ if (!fileReferenceId || !organisationId) {
2653
+ setFileReference(null);
2654
+ setFileUrl(null);
2655
+ return null;
2656
+ }
2657
+ const reference = await getFileReferenceById(fileReferenceId, organisationId);
2658
+ setFileReference(reference);
2659
+ return reference;
2660
+ }, [getFileReferenceById, fileReferenceId, organisationId]);
2661
+ useEffect5(() => {
2662
+ loadFileReference();
2663
+ }, [loadFileReference]);
2664
+ useEffect5(() => {
2665
+ if (!fileReference || !fileReferenceId || !organisationId) {
2666
+ setFileUrl(null);
2667
+ return;
2668
+ }
2669
+ const loadUrl = async () => {
2670
+ const service = createFileReferenceService(supabase);
2671
+ const url = await service.getFileUrl(
2672
+ fileReference.table_name,
2673
+ fileReference.record_id,
2674
+ organisationId
2675
+ );
2676
+ setFileUrl(url);
2677
+ };
2678
+ loadUrl();
2679
+ }, [fileReference, fileReferenceId, organisationId, supabase]);
2680
+ return {
2681
+ isLoading,
2682
+ error,
2683
+ fileReference,
2684
+ fileUrl,
2685
+ loadFileReference,
2686
+ clearError
2687
+ };
2688
+ }
2689
+ function useFilesByCategory(supabase, table_name, record_id, category, organisation_id) {
2690
+ const {
2691
+ isLoading,
2692
+ error,
2693
+ getFilesByCategory,
2694
+ clearError
2695
+ } = useFileReference(supabase);
2696
+ const [fileReferences, setFileReferences] = useState9([]);
2697
+ const [fileUrls, setFileUrls] = useState9(/* @__PURE__ */ new Map());
2698
+ const loadFiles = useCallback5(async () => {
2699
+ if (!category || !organisation_id) {
2700
+ setFileReferences([]);
2701
+ setFileUrls(/* @__PURE__ */ new Map());
2702
+ return [];
2703
+ }
2704
+ const files = await getFilesByCategory(table_name, record_id, category, organisation_id);
2705
+ setFileReferences(files);
2706
+ const urlMap = /* @__PURE__ */ new Map();
2707
+ for (const fileRef of files) {
2708
+ try {
2709
+ let url = null;
2710
+ if (fileRef.is_public) {
2711
+ url = getPublicUrl(supabase, fileRef.file_path, true);
2712
+ } else {
2713
+ const signedUrlResult = await getSignedUrl(supabase, fileRef.file_path, {
2714
+ appName: "file-reference",
2715
+ orgId: organisation_id,
2716
+ expiresIn: 3600
2717
+ });
2718
+ url = signedUrlResult?.url || null;
2719
+ }
2720
+ if (url) {
2721
+ urlMap.set(fileRef.id, url);
2722
+ }
2723
+ } catch (err) {
2724
+ console.error(`Failed to load URL for file ${fileRef.id}:`, err);
2725
+ }
2726
+ }
2727
+ setFileUrls(urlMap);
2728
+ return files;
2729
+ }, [table_name, record_id, category, organisation_id, supabase, getFilesByCategory]);
2730
+ useEffect5(() => {
2731
+ loadFiles();
2732
+ }, [loadFiles]);
2733
+ return {
2734
+ isLoading,
2735
+ error,
2736
+ fileReferences,
2737
+ fileUrls,
2738
+ loadFiles,
2739
+ clearError
2740
+ };
2741
+ }
2742
+
2743
+ // src/components/FileUpload/FileUpload.tsx
2744
+ import { useState as useState10, useCallback as useCallback6, useRef as useRef3, useEffect as useEffect6, useMemo as useMemo7 } from "react";
2745
+
2746
+ // src/utils/appIdResolver.ts
2747
+ async function getAppId(supabase, appName) {
2748
+ try {
2749
+ const { data, error } = await supabase.from("rbac_apps").select("id").ilike("name", appName).eq("is_active", true).single();
2750
+ if (error) {
2751
+ console.error("Failed to resolve app ID for app name:", appName, error);
2752
+ return null;
2753
+ }
2754
+ return data?.id || null;
2755
+ } catch (error) {
2756
+ console.error("Error resolving app ID for app name:", appName, error);
2757
+ return null;
2758
+ }
2759
+ }
2760
+ var CachedAppIdResolver = class {
2761
+ constructor() {
2762
+ this.cache = /* @__PURE__ */ new Map();
2763
+ this.ttl = 5 * 60 * 1e3;
2764
+ }
2765
+ // 5 minutes
2766
+ async getAppId(supabase, appName) {
2767
+ const now = Date.now();
2768
+ const cached = this.cache.get(appName);
2769
+ if (cached && cached.expires > now) {
2770
+ return cached.id;
2771
+ }
2772
+ const id = await getAppId(supabase, appName);
2773
+ this.cache.set(appName, { id, expires: now + this.ttl });
2774
+ return id;
2775
+ }
2776
+ clearCache() {
2777
+ this.cache.clear();
2778
+ }
2779
+ clearCacheForApp(appName) {
2780
+ this.cache.delete(appName);
2781
+ }
2782
+ };
2783
+ var cachedAppIdResolver = new CachedAppIdResolver();
2784
+
2785
+ // src/components/FileUpload/FileUpload.tsx
2786
+ import { Fragment as Fragment5, jsx as jsx20, jsxs as jsxs16 } from "react/jsx-runtime";
2787
+ function FileUpload({
2788
+ supabase,
2789
+ table_name,
2790
+ record_id,
2791
+ organisation_id,
2792
+ app_id,
2793
+ category,
2794
+ accept = "*/*",
2795
+ maxSize = 10 * 1024 * 1024,
2796
+ // 10MB default
2797
+ multiple = false,
2798
+ disabled = false,
2799
+ isPublic = false,
2800
+ className = "",
2801
+ showPreview = true,
2802
+ showProgress = true,
2803
+ onUploadSuccess,
2804
+ onUploadError,
2805
+ onProgress,
2806
+ children
2807
+ }) {
2808
+ const [isDragging, setIsDragging] = useState10(false);
2809
+ const [uploadStates, setUploadStates] = useState10(/* @__PURE__ */ new Map());
2810
+ const [resolvedAppId, setResolvedAppId] = useState10(app_id || null);
2811
+ const [isResolvingAppId, setIsResolvingAppId] = useState10(!app_id);
2812
+ const [appIdError, setAppIdError] = useState10(null);
2813
+ const fileInputRef = useRef3(null);
2814
+ const { uploadFile: uploadFile2, isLoading, error } = useFileReference(supabase);
2815
+ useEffect6(() => {
2816
+ if (app_id) {
2817
+ setResolvedAppId(app_id);
2818
+ setIsResolvingAppId(false);
2819
+ setAppIdError(null);
2820
+ return;
2821
+ }
2822
+ const resolveAppId = async () => {
2823
+ setIsResolvingAppId(true);
2824
+ setAppIdError(null);
2825
+ try {
2826
+ const appName = getCurrentAppName();
2827
+ if (!appName) {
2828
+ const errorMsg = "App ID is required. Either provide app_id prop or set app name via setRBACAppName()";
2829
+ setAppIdError(errorMsg);
2830
+ setIsResolvingAppId(false);
2831
+ return;
2832
+ }
2833
+ const resolvedId = await getAppId(supabase, appName);
2834
+ if (!resolvedId) {
2835
+ const errorMsg = `Failed to resolve app ID for app name "${appName}". Make sure the app is registered in rbac_apps table.`;
2836
+ setAppIdError(errorMsg);
2837
+ setIsResolvingAppId(false);
2838
+ return;
2839
+ }
2840
+ setResolvedAppId(resolvedId);
2841
+ setIsResolvingAppId(false);
2842
+ } catch (err) {
2843
+ const errorMessage = err instanceof Error ? err.message : "Failed to resolve app ID";
2844
+ setAppIdError(errorMessage);
2845
+ setIsResolvingAppId(false);
2846
+ }
2847
+ };
2848
+ resolveAppId();
2849
+ }, [app_id, supabase]);
2850
+ const isUploading = useMemo7(() => {
2851
+ return uploadStates.size > 0 && Array.from(uploadStates.values()).some(
2852
+ (state) => state.progress.status === "uploading" || state.progress.status === "processing"
2853
+ );
2854
+ }, [uploadStates]);
2855
+ const isDisabled = useMemo7(() => {
2856
+ return disabled || isUploading || isResolvingAppId || !resolvedAppId;
2857
+ }, [disabled, isUploading, isResolvingAppId, resolvedAppId]);
2858
+ const generatePreview = useCallback6((file) => {
2859
+ return new Promise((resolve) => {
2860
+ if (!file.type.startsWith("image/")) {
2861
+ resolve(null);
2862
+ return;
2863
+ }
2864
+ const reader = new FileReader();
2865
+ reader.onload = (e) => {
2866
+ resolve(e.target?.result || null);
2867
+ };
2868
+ reader.onerror = () => resolve(null);
2869
+ reader.readAsDataURL(file);
2870
+ });
2871
+ }, []);
2872
+ const validateFile = useCallback6((file) => {
2873
+ if (file.size > maxSize) {
2874
+ return `File "${file.name}" exceeds maximum size of ${Math.round(maxSize / 1024 / 1024)}MB`;
2875
+ }
2876
+ if (accept !== "*/*") {
2877
+ const acceptedTypes = accept.split(",").map((type) => type.trim());
2878
+ const fileExtension = "." + file.name.split(".").pop()?.toLowerCase();
2879
+ const fileMimeType = file.type;
2880
+ const isAccepted = acceptedTypes.some((accepted) => {
2881
+ if (accepted.startsWith(".")) {
2882
+ return accepted === fileExtension;
2883
+ } else if (accepted.includes("/*")) {
2884
+ const baseType = accepted.split("/")[0];
2885
+ return fileMimeType.startsWith(baseType + "/");
2886
+ } else {
2887
+ return accepted === fileMimeType;
2888
+ }
2889
+ });
2890
+ if (!isAccepted) {
2891
+ return `File "${file.name}" is not an accepted format. Accepted: ${accept}`;
2892
+ }
2893
+ }
2894
+ return null;
2895
+ }, [accept, maxSize]);
2896
+ const handleFileSelect = useCallback6(async (files) => {
2897
+ if (!files || files.length === 0) return;
2898
+ const fileArray = Array.from(files);
2899
+ const validationErrors = [];
2900
+ const validFiles = [];
2901
+ for (const file of fileArray) {
2902
+ const error2 = validateFile(file);
2903
+ if (error2) {
2904
+ validationErrors.push(error2);
2905
+ onUploadError?.(error2, file);
2906
+ } else {
2907
+ validFiles.push(file);
2908
+ }
2909
+ }
2910
+ if (validFiles.length === 0) {
2911
+ return;
2912
+ }
2913
+ const newUploadStates = /* @__PURE__ */ new Map();
2914
+ for (const file of validFiles) {
2915
+ const fileId = `${file.name}-${file.size}-${Date.now()}`;
2916
+ const preview = showPreview ? await generatePreview(file) || void 0 : void 0;
2917
+ const progress = {
2918
+ loaded: 0,
2919
+ total: file.size,
2920
+ percentage: 0,
2921
+ fileName: file.name,
2922
+ status: "idle"
2923
+ };
2924
+ newUploadStates.set(fileId, {
2925
+ file,
2926
+ progress,
2927
+ preview
2928
+ });
2929
+ }
2930
+ setUploadStates(newUploadStates);
2931
+ for (const [fileId, uploadState] of newUploadStates.entries()) {
2932
+ const { file } = uploadState;
2933
+ setUploadStates((prev) => {
2934
+ const updated = new Map(prev);
2935
+ const state = updated.get(fileId);
2936
+ if (state) {
2937
+ updated.set(fileId, {
2938
+ ...state,
2939
+ progress: {
2940
+ ...state.progress,
2941
+ status: "uploading"
2942
+ }
2943
+ });
2944
+ }
2945
+ return updated;
2946
+ });
2947
+ try {
2948
+ const progressInterval = setInterval(() => {
2949
+ setUploadStates((prev) => {
2950
+ const updated = new Map(prev);
2951
+ const state = updated.get(fileId);
2952
+ if (state && state.progress.status === "uploading") {
2953
+ const estimatedProgress = Math.min(
2954
+ state.progress.percentage + 10,
2955
+ 90
2956
+ );
2957
+ const newProgress = {
2958
+ ...state.progress,
2959
+ percentage: estimatedProgress,
2960
+ loaded: Math.floor(estimatedProgress / 100 * file.size)
2961
+ };
2962
+ onProgress?.(newProgress);
2963
+ updated.set(fileId, {
2964
+ ...state,
2965
+ progress: newProgress
2966
+ });
2967
+ }
2968
+ return updated;
2969
+ });
2970
+ }, 200);
2971
+ if (!resolvedAppId) {
2972
+ const errorMsg = appIdError || "App ID not available. Please provide app_id prop or set app name.";
2973
+ throw new Error(errorMsg);
2974
+ }
2975
+ const result = await uploadFile2({
2976
+ table_name,
2977
+ record_id,
2978
+ organisation_id,
2979
+ app_id: resolvedAppId,
2980
+ category,
2981
+ is_public: isPublic
2982
+ }, file);
2983
+ clearInterval(progressInterval);
2984
+ if (result) {
2985
+ setUploadStates((prev) => {
2986
+ const updated = new Map(prev);
2987
+ const state = updated.get(fileId);
2988
+ if (state) {
2989
+ updated.set(fileId, {
2990
+ ...state,
2991
+ progress: {
2992
+ ...state.progress,
2993
+ status: "completed",
2994
+ percentage: 100,
2995
+ loaded: file.size
2996
+ },
2997
+ result
2998
+ });
2999
+ }
3000
+ return updated;
3001
+ });
3002
+ const finalProgress = {
3003
+ loaded: file.size,
3004
+ total: file.size,
3005
+ percentage: 100,
3006
+ fileName: file.name,
3007
+ status: "completed"
3008
+ };
3009
+ onProgress?.(finalProgress);
3010
+ onUploadSuccess?.(result);
3011
+ setTimeout(() => {
3012
+ setUploadStates((prev) => {
3013
+ const updated = new Map(prev);
3014
+ updated.delete(fileId);
3015
+ return updated;
3016
+ });
3017
+ }, 3e3);
3018
+ } else {
3019
+ setUploadStates((prev) => {
3020
+ const updated = new Map(prev);
3021
+ const state = updated.get(fileId);
3022
+ if (state) {
3023
+ updated.set(fileId, {
3024
+ ...state,
3025
+ progress: {
3026
+ ...state.progress,
3027
+ status: "error",
3028
+ error: "Upload failed"
3029
+ }
3030
+ });
3031
+ }
3032
+ return updated;
3033
+ });
3034
+ const errorProgress = {
3035
+ loaded: 0,
3036
+ total: file.size,
3037
+ percentage: 0,
3038
+ fileName: file.name,
3039
+ status: "error",
3040
+ error: "Upload failed"
3041
+ };
3042
+ onProgress?.(errorProgress);
3043
+ onUploadError?.("Upload failed", file);
3044
+ }
3045
+ } catch (err) {
3046
+ const errorMessage = err instanceof Error ? err.message : "Upload failed";
3047
+ setUploadStates((prev) => {
3048
+ const updated = new Map(prev);
3049
+ const state = updated.get(fileId);
3050
+ if (state) {
3051
+ updated.set(fileId, {
3052
+ ...state,
3053
+ progress: {
3054
+ ...state.progress,
3055
+ status: "error",
3056
+ error: errorMessage
3057
+ }
3058
+ });
3059
+ }
3060
+ return updated;
3061
+ });
3062
+ const errorProgress = {
3063
+ loaded: 0,
3064
+ total: file.size,
3065
+ percentage: 0,
3066
+ fileName: file.name,
3067
+ status: "error",
3068
+ error: errorMessage
3069
+ };
3070
+ onProgress?.(errorProgress);
3071
+ onUploadError?.(errorMessage, file);
3072
+ }
3073
+ }
3074
+ }, [uploadFile2, table_name, record_id, organisation_id, resolvedAppId, category, isPublic, maxSize, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError]);
3075
+ const handleDragOver = useCallback6((e) => {
3076
+ e.preventDefault();
3077
+ e.stopPropagation();
3078
+ if (!isDisabled) {
3079
+ setIsDragging(true);
3080
+ }
3081
+ }, [isDisabled]);
3082
+ const handleDragLeave = useCallback6((e) => {
3083
+ e.preventDefault();
3084
+ e.stopPropagation();
3085
+ setIsDragging(false);
3086
+ }, []);
3087
+ const handleDrop = useCallback6((e) => {
3088
+ e.preventDefault();
3089
+ e.stopPropagation();
3090
+ setIsDragging(false);
3091
+ if (isDisabled) return;
3092
+ const files = e.dataTransfer.files;
3093
+ handleFileSelect(files);
3094
+ }, [isDisabled, handleFileSelect]);
3095
+ const handleFileInputChange = useCallback6((e) => {
3096
+ handleFileSelect(e.target.files);
3097
+ if (e.target) {
3098
+ e.target.value = "";
3099
+ }
3100
+ }, [handleFileSelect]);
3101
+ const handleClick = useCallback6(() => {
3102
+ if (!isDisabled && fileInputRef.current) {
3103
+ fileInputRef.current.click();
3104
+ }
3105
+ }, [isDisabled]);
3106
+ const formatFileSize = (bytes) => {
3107
+ if (bytes === 0) return "0 Bytes";
3108
+ const k = 1024;
3109
+ const sizes = ["Bytes", "KB", "MB", "GB"];
3110
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
3111
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
3112
+ };
3113
+ const dragClasses = isDragging ? "border-main-500 bg-main-50" : "border-sec-300 hover:border-sec-400";
3114
+ const disabledClasses = isDisabled ? "opacity-50 cursor-not-allowed" : "cursor-pointer hover:bg-sec-50";
3115
+ return /* @__PURE__ */ jsxs16("div", { className: `space-y-4 ${className}`, children: [
3116
+ /* @__PURE__ */ jsxs16(
3117
+ "div",
3118
+ {
3119
+ className: `relative border-2 border-dashed rounded-lg p-6 text-center transition-colors ${dragClasses} ${disabledClasses}`,
3120
+ onDragOver: handleDragOver,
3121
+ onDragLeave: handleDragLeave,
3122
+ onDrop: handleDrop,
3123
+ onClick: !isDisabled ? handleClick : void 0,
3124
+ children: [
3125
+ children || /* @__PURE__ */ jsxs16("div", { className: "space-y-2", children: [
3126
+ /* @__PURE__ */ jsx20(
3127
+ "input",
3128
+ {
3129
+ ref: fileInputRef,
3130
+ type: "file",
3131
+ accept,
3132
+ multiple,
3133
+ onChange: handleFileInputChange,
3134
+ className: "hidden",
3135
+ disabled: isDisabled,
3136
+ "data-testid": "file-input"
3137
+ }
3138
+ ),
3139
+ /* @__PURE__ */ jsx20("div", { className: "text-sec-600", children: isResolvingAppId ? "Resolving app configuration..." : isDragging ? "Drop files here..." : /* @__PURE__ */ jsxs16(Fragment5, { children: [
3140
+ /* @__PURE__ */ jsx20("span", { className: "font-medium", children: "Click to upload" }),
3141
+ " ",
3142
+ "or drag and drop"
3143
+ ] }) }),
3144
+ /* @__PURE__ */ jsxs16("div", { className: "text-sm text-sec-500", children: [
3145
+ !isResolvingAppId && accept !== "*/*" && `Accepted formats: ${accept}`,
3146
+ !isResolvingAppId && maxSize && ` \u2022 Max size: ${Math.round(maxSize / 1024 / 1024)}MB`,
3147
+ !isResolvingAppId && multiple && " \u2022 Multiple files allowed"
3148
+ ] })
3149
+ ] }),
3150
+ isUploading && !showProgress && /* @__PURE__ */ jsx20("div", { className: "absolute inset-0 bg-white bg-opacity-75 flex items-center justify-center", children: /* @__PURE__ */ jsx20("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-main-500" }) })
3151
+ ]
3152
+ }
3153
+ ),
3154
+ showProgress && uploadStates.size > 0 && /* @__PURE__ */ jsx20("div", { className: "space-y-2", children: Array.from(uploadStates.entries()).map(([fileId, uploadState]) => {
3155
+ const { file, progress, preview, result } = uploadState;
3156
+ const isError = progress.status === "error";
3157
+ const isCompleted = progress.status === "completed";
3158
+ const isUploading2 = progress.status === "uploading" || progress.status === "processing";
3159
+ return /* @__PURE__ */ jsxs16(
3160
+ "div",
3161
+ {
3162
+ className: `flex items-center space-x-3 p-3 rounded-lg border ${isError ? "bg-acc-50 border-acc-200" : isCompleted ? "bg-success-50 border-success-200" : "bg-sec-50 border-sec-200"}`,
3163
+ children: [
3164
+ /* @__PURE__ */ jsx20("div", { className: "flex-shrink-0", children: preview ? /* @__PURE__ */ jsx20(
3165
+ "img",
3166
+ {
3167
+ src: preview,
3168
+ alt: file.name,
3169
+ className: "w-12 h-12 object-cover rounded"
3170
+ }
3171
+ ) : /* @__PURE__ */ jsx20("div", { className: "w-12 h-12 flex items-center justify-center bg-sec-200 rounded", children: /* @__PURE__ */ jsx20("span", { className: "text-2xl", children: "\u{1F4C4}" }) }) }),
3172
+ /* @__PURE__ */ jsxs16("div", { className: "flex-1 min-w-0", children: [
3173
+ /* @__PURE__ */ jsx20("div", { className: "font-medium text-sec-900 truncate", children: file.name }),
3174
+ /* @__PURE__ */ jsxs16("div", { className: "text-sm text-sec-500", children: [
3175
+ formatFileSize(file.size),
3176
+ isCompleted && result && " \u2022 Uploaded",
3177
+ isError && progress.error && ` \u2022 ${progress.error}`
3178
+ ] }),
3179
+ showProgress && (isUploading2 || isError) && /* @__PURE__ */ jsxs16("div", { className: "mt-2", children: [
3180
+ /* @__PURE__ */ jsx20("div", { className: "w-full bg-sec-200 rounded-full h-2", children: /* @__PURE__ */ jsx20(
3181
+ "div",
3182
+ {
3183
+ className: `h-2 rounded-full transition-all duration-300 ${isError ? "bg-acc-500" : "bg-main-500"}`,
3184
+ style: { width: `${progress.percentage}%` }
3185
+ }
3186
+ ) }),
3187
+ isUploading2 && /* @__PURE__ */ jsxs16("div", { className: "text-xs text-sec-500 mt-1", children: [
3188
+ progress.percentage,
3189
+ "% \u2022 ",
3190
+ formatFileSize(progress.loaded),
3191
+ " / ",
3192
+ formatFileSize(progress.total)
3193
+ ] })
3194
+ ] })
3195
+ ] }),
3196
+ /* @__PURE__ */ jsxs16("div", { className: "flex-shrink-0", children: [
3197
+ isCompleted && /* @__PURE__ */ jsx20("span", { className: "text-success-500 text-xl", children: "\u2713" }),
3198
+ isError && /* @__PURE__ */ jsx20("span", { className: "text-acc-500 text-xl", children: "\u2715" }),
3199
+ isUploading2 && /* @__PURE__ */ jsx20("div", { className: "animate-spin rounded-full h-5 w-5 border-b-2 border-main-500" })
3200
+ ] })
3201
+ ]
3202
+ },
3203
+ fileId
3204
+ );
3205
+ }) }),
3206
+ appIdError && /* @__PURE__ */ jsx20("div", { className: "p-3 bg-acc-50 border border-acc-200 rounded-lg text-sm text-acc-600", children: appIdError }),
3207
+ error && /* @__PURE__ */ jsx20("div", { className: "p-3 bg-acc-50 border border-acc-200 rounded-lg text-sm text-acc-600", children: error })
3208
+ ] });
3209
+ }
3210
+
3211
+ // src/components/FileDisplay/FileDisplay.tsx
3212
+ import { useState as useState11, useEffect as useEffect7, useRef as useRef4 } from "react";
3213
+ import { jsx as jsx21, jsxs as jsxs17 } from "react/jsx-runtime";
3214
+ function FileDisplay({
2914
3215
  supabase,
2915
3216
  table_name,
2916
3217
  record_id,
@@ -2936,7 +3237,22 @@ function FileDisplay({
2936
3237
  clearError
2937
3238
  } = useFileReferenceForRecord(supabase, table_name, record_id, organisation_id);
2938
3239
  const [imageError, setImageError] = useState11(false);
2939
- useEffect5(() => {
3240
+ const [fileUrls, setFileUrls] = useState11(/* @__PURE__ */ new Map());
3241
+ const [loadingUrls, setLoadingUrls] = useState11(/* @__PURE__ */ new Set());
3242
+ const loadedFilesRef = useRef4(/* @__PURE__ */ new Set());
3243
+ const loadingUrlsRef = useRef4(/* @__PURE__ */ new Set());
3244
+ const fileReferencesRef = useRef4([]);
3245
+ useEffect7(() => {
3246
+ const currentIds = fileReferences.map((f) => f.id).join(",");
3247
+ const prevIds = fileReferencesRef.current.map((f) => f.id).join(",");
3248
+ if (currentIds !== prevIds) {
3249
+ fileReferencesRef.current = fileReferences;
3250
+ loadedFilesRef.current.clear();
3251
+ setFileUrls(/* @__PURE__ */ new Map());
3252
+ setLoadingUrls(/* @__PURE__ */ new Set());
3253
+ }
3254
+ }, [fileReferences]);
3255
+ useEffect7(() => {
2940
3256
  loadFileCount();
2941
3257
  if (category) {
2942
3258
  loadFileReference();
@@ -2944,11 +3260,61 @@ function FileDisplay({
2944
3260
  loadFileReferences();
2945
3261
  }
2946
3262
  }, [loadFileCount, loadFileReference, loadFileReferences, category]);
2947
- useEffect5(() => {
3263
+ useEffect7(() => {
2948
3264
  if (fileReference) {
2949
3265
  loadFileUrl();
2950
3266
  }
2951
3267
  }, [fileReference, loadFileUrl]);
3268
+ useEffect7(() => {
3269
+ if (category || fileReferences.length === 0) return;
3270
+ const loadFileUrls = async () => {
3271
+ const urlsToLoad = fileReferences.filter((fileRef) => {
3272
+ return !loadedFilesRef.current.has(fileRef.id) && !loadingUrlsRef.current.has(fileRef.id);
3273
+ });
3274
+ if (urlsToLoad.length === 0) return;
3275
+ setLoadingUrls((prev) => {
3276
+ const updated = new Set(prev);
3277
+ urlsToLoad.forEach((fileRef) => {
3278
+ updated.add(fileRef.id);
3279
+ loadingUrlsRef.current.add(fileRef.id);
3280
+ });
3281
+ return updated;
3282
+ });
3283
+ for (const fileRef of urlsToLoad) {
3284
+ try {
3285
+ let url = null;
3286
+ if (fileRef.is_public) {
3287
+ url = getPublicUrl(supabase, fileRef.file_path, true);
3288
+ } else {
3289
+ const signedUrlResult = await getSignedUrl(supabase, fileRef.file_path, {
3290
+ appName: "file-reference",
3291
+ orgId: organisation_id,
3292
+ expiresIn: 3600
3293
+ });
3294
+ url = signedUrlResult?.url || null;
3295
+ }
3296
+ if (url) {
3297
+ setFileUrls((prev) => {
3298
+ const updated = new Map(prev);
3299
+ updated.set(fileRef.id, url);
3300
+ return updated;
3301
+ });
3302
+ loadedFilesRef.current.add(fileRef.id);
3303
+ }
3304
+ } catch (error2) {
3305
+ console.error(`Failed to load URL for file ${fileRef.id}:`, error2);
3306
+ } finally {
3307
+ setLoadingUrls((prev) => {
3308
+ const updated = new Set(prev);
3309
+ updated.delete(fileRef.id);
3310
+ loadingUrlsRef.current.delete(fileRef.id);
3311
+ return updated;
3312
+ });
3313
+ }
3314
+ }
3315
+ };
3316
+ loadFileUrls();
3317
+ }, [category, fileReferences.map((f) => f.id).join(","), supabase, organisation_id]);
2952
3318
  const handleDelete = async () => {
2953
3319
  if (window.confirm("Are you sure you want to delete this file?")) {
2954
3320
  const success = await deleteFile2(true);
@@ -2970,7 +3336,7 @@ function FileDisplay({
2970
3336
  if (fileType.includes("powerpoint") || fileType.includes("presentation")) return "\u{1F4CA}";
2971
3337
  return "\u{1F4C1}";
2972
3338
  };
2973
- const formatFileSize2 = (bytes) => {
3339
+ const formatFileSize = (bytes) => {
2974
3340
  if (bytes === 0) return "0 Bytes";
2975
3341
  const k = 1024;
2976
3342
  const sizes = ["Bytes", "KB", "MB", "GB"];
@@ -2978,15 +3344,15 @@ function FileDisplay({
2978
3344
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + " " + sizes[i];
2979
3345
  };
2980
3346
  if (isLoading) {
2981
- return /* @__PURE__ */ jsx19("div", { className: `flex items-center justify-center p-4 ${className}`, children: /* @__PURE__ */ jsx19("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-main-500" }) });
3347
+ return /* @__PURE__ */ jsx21("div", { className: `flex items-center justify-center p-4 ${className}`, children: /* @__PURE__ */ jsx21("div", { className: "animate-spin rounded-full h-8 w-8 border-b-2 border-main-500" }) });
2982
3348
  }
2983
3349
  if (error) {
2984
- return /* @__PURE__ */ jsxs15("div", { className: `p-4 bg-acc-50 border border-acc-200 rounded-lg ${className}`, children: [
2985
- /* @__PURE__ */ jsxs15("div", { className: "text-acc-600", children: [
3350
+ return /* @__PURE__ */ jsxs17("div", { className: `p-4 bg-acc-50 border border-acc-200 rounded-lg ${className}`, children: [
3351
+ /* @__PURE__ */ jsxs17("div", { className: "text-acc-600", children: [
2986
3352
  "Error loading file: ",
2987
3353
  error
2988
3354
  ] }),
2989
- /* @__PURE__ */ jsx19(
3355
+ /* @__PURE__ */ jsx21(
2990
3356
  "button",
2991
3357
  {
2992
3358
  onClick: clearError,
@@ -2997,16 +3363,16 @@ function FileDisplay({
2997
3363
  ] });
2998
3364
  }
2999
3365
  if (fileCount === 0) {
3000
- return /* @__PURE__ */ jsxs15("div", { className: `text-sec-500 text-center p-4 ${className}`, children: [
3366
+ return /* @__PURE__ */ jsxs17("div", { className: `text-sec-500 text-center p-4 ${className}`, children: [
3001
3367
  "No files found",
3002
3368
  children
3003
3369
  ] });
3004
3370
  }
3005
3371
  if (category && fileReference) {
3006
3372
  const isImage = fileReference.file_metadata.fileType?.startsWith("image/");
3007
- return /* @__PURE__ */ jsxs15("div", { className: `space-y-2 ${className}`, children: [
3008
- isImage && fileUrl && !imageError ? /* @__PURE__ */ jsxs15("div", { className: "relative", children: [
3009
- /* @__PURE__ */ jsx19(
3373
+ return /* @__PURE__ */ jsxs17("div", { className: `space-y-2 ${className}`, children: [
3374
+ isImage && fileUrl && !imageError ? /* @__PURE__ */ jsxs17("div", { className: "relative", children: [
3375
+ /* @__PURE__ */ jsx21(
3010
3376
  "img",
3011
3377
  {
3012
3378
  src: fileUrl,
@@ -3015,30 +3381,32 @@ function FileDisplay({
3015
3381
  onError: handleImageError
3016
3382
  }
3017
3383
  ),
3018
- showDelete && /* @__PURE__ */ jsx19(
3384
+ showDelete && /* @__PURE__ */ jsx21(
3019
3385
  "button",
3020
3386
  {
3021
3387
  onClick: handleDelete,
3022
3388
  className: "absolute top-2 right-2 bg-acc-500 text-white rounded-full w-6 h-6 flex items-center justify-center text-sm hover:bg-acc-600",
3023
3389
  title: "Delete file",
3390
+ "aria-label": "Delete file",
3024
3391
  children: "\xD7"
3025
3392
  }
3026
3393
  )
3027
- ] }) : /* @__PURE__ */ jsxs15("div", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
3028
- /* @__PURE__ */ jsx19("span", { className: "text-2xl", children: getFileIcon(fileReference.file_metadata.fileType || "") }),
3029
- /* @__PURE__ */ jsxs15("div", { className: "flex-1 min-w-0", children: [
3030
- /* @__PURE__ */ jsx19("div", { className: "font-medium text-sec-900 truncate", children: fileReference.file_metadata.fileName || "Unknown file" }),
3031
- /* @__PURE__ */ jsxs15("div", { className: "text-sm text-sec-500", children: [
3032
- fileReference.file_metadata.fileSize && formatFileSize2(fileReference.file_metadata.fileSize),
3394
+ ] }) : /* @__PURE__ */ jsxs17("div", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
3395
+ /* @__PURE__ */ jsx21("span", { className: "text-2xl", children: getFileIcon(fileReference.file_metadata.fileType || "") }),
3396
+ /* @__PURE__ */ jsxs17("div", { className: "flex-1 min-w-0", children: [
3397
+ /* @__PURE__ */ jsx21("div", { className: "font-medium text-sec-900 truncate", children: fileReference.file_metadata.fileName || "Unknown file" }),
3398
+ /* @__PURE__ */ jsxs17("div", { className: "text-sm text-sec-500", children: [
3399
+ fileReference.file_metadata.fileSize && formatFileSize(fileReference.file_metadata.fileSize),
3033
3400
  fileReference.file_metadata.fileType && ` \u2022 ${fileReference.file_metadata.fileType}`
3034
3401
  ] })
3035
3402
  ] }),
3036
- showDelete && /* @__PURE__ */ jsx19(
3403
+ showDelete && /* @__PURE__ */ jsx21(
3037
3404
  "button",
3038
3405
  {
3039
3406
  onClick: handleDelete,
3040
3407
  className: "text-acc-500 hover:text-acc-700 p-1",
3041
3408
  title: "Delete file",
3409
+ "aria-label": "Delete file",
3042
3410
  children: "\xD7"
3043
3411
  }
3044
3412
  )
@@ -3046,12 +3414,14 @@ function FileDisplay({
3046
3414
  children
3047
3415
  ] });
3048
3416
  }
3049
- return /* @__PURE__ */ jsxs15("div", { className: `space-y-2 ${className}`, children: [
3417
+ return /* @__PURE__ */ jsxs17("div", { className: `space-y-2 ${className}`, children: [
3050
3418
  fileReferences.map((fileRef) => {
3051
3419
  const isImage = fileRef.file_metadata.fileType?.startsWith("image/");
3052
- const fileUrl2 = fileRef.is_public ? `https://your-supabase-url.supabase.co/storage/v1/object/public/files/${fileRef.file_path}` : null;
3053
- return /* @__PURE__ */ jsxs15("div", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
3054
- isImage && fileUrl2 ? /* @__PURE__ */ jsx19(
3420
+ const fileUrl2 = fileUrls.get(fileRef.id) || null;
3421
+ const isLoadingUrl = loadingUrls.has(fileRef.id);
3422
+ const canDownload = !isImage && fileUrl2;
3423
+ return /* @__PURE__ */ jsxs17("div", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
3424
+ isLoadingUrl ? /* @__PURE__ */ jsx21("div", { className: "w-12 h-12 flex items-center justify-center", children: /* @__PURE__ */ jsx21("div", { className: "animate-spin rounded-full h-6 w-6 border-b-2 border-main-500" }) }) : isImage && fileUrl2 ? /* @__PURE__ */ jsx21(
3055
3425
  "img",
3056
3426
  {
3057
3427
  src: fileUrl2,
@@ -3059,34 +3429,206 @@ function FileDisplay({
3059
3429
  className: "w-12 h-12 object-cover rounded",
3060
3430
  onError: handleImageError
3061
3431
  }
3062
- ) : /* @__PURE__ */ jsx19("span", { className: "text-2xl", children: getFileIcon(fileRef.file_metadata.fileType || "") }),
3063
- /* @__PURE__ */ jsxs15("div", { className: "flex-1 min-w-0", children: [
3064
- /* @__PURE__ */ jsx19("div", { className: "font-medium text-sec-900 truncate", children: fileRef.file_metadata.fileName || "Unknown file" }),
3065
- /* @__PURE__ */ jsxs15("div", { className: "text-sm text-sec-500", children: [
3066
- fileRef.file_metadata.fileSize && formatFileSize2(fileRef.file_metadata.fileSize),
3432
+ ) : /* @__PURE__ */ jsx21("span", { className: "text-2xl", children: getFileIcon(fileRef.file_metadata.fileType || "") }),
3433
+ /* @__PURE__ */ jsxs17("div", { className: "flex-1 min-w-0", children: [
3434
+ /* @__PURE__ */ jsx21("div", { className: "font-medium text-sec-900 truncate", children: fileRef.file_metadata.fileName || "Unknown file" }),
3435
+ /* @__PURE__ */ jsxs17("div", { className: "text-sm text-sec-500", children: [
3436
+ fileRef.file_metadata.fileSize && formatFileSize(fileRef.file_metadata.fileSize),
3067
3437
  fileRef.file_metadata.fileType && ` \u2022 ${fileRef.file_metadata.fileType}`,
3068
3438
  fileRef.file_metadata.category && ` \u2022 ${fileRef.file_metadata.category}`
3069
3439
  ] })
3070
3440
  ] }),
3071
- showDelete && /* @__PURE__ */ jsx19(
3072
- "button",
3073
- {
3074
- onClick: () => deleteFile2(true),
3075
- className: "text-acc-500 hover:text-acc-700 p-1",
3076
- title: "Delete file",
3077
- children: "\xD7"
3078
- }
3079
- )
3441
+ /* @__PURE__ */ jsxs17("div", { className: "flex items-center space-x-2", children: [
3442
+ canDownload && /* @__PURE__ */ jsx21(
3443
+ "a",
3444
+ {
3445
+ href: fileRef.file_path,
3446
+ download: fileRef.file_metadata.fileName || "download",
3447
+ className: "text-main-500 hover:text-main-700 p-1",
3448
+ title: "Download file",
3449
+ children: "\u2193"
3450
+ }
3451
+ ),
3452
+ showDelete && /* @__PURE__ */ jsx21(
3453
+ "button",
3454
+ {
3455
+ onClick: () => deleteFile2(true),
3456
+ className: "text-acc-500 hover:text-acc-700 p-1",
3457
+ title: "Delete file",
3458
+ children: "\xD7"
3459
+ }
3460
+ )
3461
+ ] })
3080
3462
  ] }, fileRef.id);
3081
3463
  }),
3082
3464
  children
3083
3465
  ] });
3084
3466
  }
3085
3467
 
3468
+ // src/hooks/useEventLogo.ts
3469
+ import { useState as useState12, useEffect as useEffect8, useCallback as useCallback8, useMemo as useMemo8 } from "react";
3470
+ function defaultGenerateFallbackText(eventName) {
3471
+ if (!eventName) return "EV";
3472
+ return eventName.split(" ").map((word) => word.charAt(0).toUpperCase()).join("").substring(0, 3);
3473
+ }
3474
+ var authenticatedLogoCache = /* @__PURE__ */ new Map();
3475
+ var MAX_CACHE_SIZE = 100;
3476
+ function cleanupCache() {
3477
+ const now = Date.now();
3478
+ const entries = Array.from(authenticatedLogoCache.entries());
3479
+ entries.forEach(([key, value]) => {
3480
+ if (now - value.timestamp > value.ttl) {
3481
+ authenticatedLogoCache.delete(key);
3482
+ }
3483
+ });
3484
+ if (authenticatedLogoCache.size > MAX_CACHE_SIZE) {
3485
+ const sortedEntries = Array.from(authenticatedLogoCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
3486
+ const toRemove = sortedEntries.slice(0, authenticatedLogoCache.size - MAX_CACHE_SIZE);
3487
+ toRemove.forEach(([key]) => authenticatedLogoCache.delete(key));
3488
+ }
3489
+ }
3490
+ function useEventLogo(supabase, eventId, eventName, organisationId, options = {}) {
3491
+ const {
3492
+ cacheTtl = 30 * 60 * 1e3,
3493
+ // 30 minutes
3494
+ enableCache = true,
3495
+ validateImage = true,
3496
+ generateFallbackText = defaultGenerateFallbackText
3497
+ } = options;
3498
+ const [logoUrl, setLogoUrl] = useState12(null);
3499
+ const [isLoading, setIsLoading] = useState12(false);
3500
+ const [error, setError] = useState12(null);
3501
+ const fallbackText = useMemo8(() => {
3502
+ return eventName ? generateFallbackText(eventName) : "EV";
3503
+ }, [eventName, generateFallbackText]);
3504
+ const fetchLogo = useCallback8(async () => {
3505
+ if (!eventId || !organisationId || !supabase) {
3506
+ setLogoUrl(null);
3507
+ setIsLoading(false);
3508
+ return;
3509
+ }
3510
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3511
+ if (!uuidRegex.test(organisationId)) {
3512
+ console.warn("[useEventLogo] Invalid organisationId format (not a valid UUID):", organisationId);
3513
+ }
3514
+ const cacheKey = `event_logo_${eventId}_${organisationId}`;
3515
+ if (enableCache) {
3516
+ const cached = authenticatedLogoCache.get(cacheKey);
3517
+ if (cached && Date.now() - cached.timestamp < cached.ttl) {
3518
+ setLogoUrl(cached.data);
3519
+ setIsLoading(false);
3520
+ setError(null);
3521
+ return;
3522
+ }
3523
+ }
3524
+ try {
3525
+ setIsLoading(true);
3526
+ setError(null);
3527
+ const service = createFileReferenceService(supabase);
3528
+ const files = await service.getFilesByCategory(
3529
+ "event",
3530
+ eventId,
3531
+ "event_logos" /* EVENT_LOGOS */,
3532
+ organisationId
3533
+ );
3534
+ if (!files || files.length === 0) {
3535
+ setLogoUrl(null);
3536
+ return;
3537
+ }
3538
+ const logoFileRef = files[0];
3539
+ const logoPath = logoFileRef.file_path;
3540
+ const isPublic = logoFileRef.is_public ?? true;
3541
+ let url = null;
3542
+ if (isPublic) {
3543
+ url = getPublicUrl(supabase, logoPath, true);
3544
+ } else {
3545
+ const signedUrlResult = await getSignedUrl(supabase, logoPath, {
3546
+ appName: "pace-core",
3547
+ orgId: organisationId,
3548
+ expiresIn: 3600
3549
+ });
3550
+ url = signedUrlResult?.url || null;
3551
+ }
3552
+ if (!url) {
3553
+ setLogoUrl(null);
3554
+ return;
3555
+ }
3556
+ if (validateImage) {
3557
+ try {
3558
+ const response = await fetch(url, { method: "HEAD" });
3559
+ if (!response.ok) {
3560
+ console.warn("[useEventLogo] Logo URL not accessible:", url);
3561
+ setLogoUrl(null);
3562
+ return;
3563
+ }
3564
+ } catch (fetchError) {
3565
+ console.warn("[useEventLogo] Error validating logo URL:", fetchError);
3566
+ setLogoUrl(null);
3567
+ return;
3568
+ }
3569
+ }
3570
+ setLogoUrl(url);
3571
+ if (enableCache) {
3572
+ authenticatedLogoCache.set(cacheKey, {
3573
+ data: url,
3574
+ timestamp: Date.now(),
3575
+ ttl: cacheTtl
3576
+ });
3577
+ cleanupCache();
3578
+ }
3579
+ } catch (err) {
3580
+ console.error("[useEventLogo] Error fetching logo:", err);
3581
+ const error2 = err instanceof Error ? err : new Error("Unknown error occurred");
3582
+ setError(error2);
3583
+ setLogoUrl(null);
3584
+ } finally {
3585
+ setIsLoading(false);
3586
+ }
3587
+ }, [eventId, organisationId, supabase, cacheTtl, enableCache, validateImage, generateFallbackText]);
3588
+ useEffect8(() => {
3589
+ if (eventId && organisationId && supabase) {
3590
+ fetchLogo();
3591
+ } else {
3592
+ setLogoUrl(null);
3593
+ setIsLoading(false);
3594
+ setError(null);
3595
+ }
3596
+ }, [eventId, organisationId, supabase, cacheTtl, enableCache, validateImage, generateFallbackText]);
3597
+ const refetch = useCallback8(async () => {
3598
+ if (!eventId || !organisationId || !supabase) return;
3599
+ if (enableCache) {
3600
+ const cacheKey = `event_logo_${eventId}_${organisationId}`;
3601
+ authenticatedLogoCache.delete(cacheKey);
3602
+ }
3603
+ await fetchLogo();
3604
+ }, [fetchLogo, eventId, organisationId, supabase, enableCache]);
3605
+ return {
3606
+ logoUrl,
3607
+ fallbackText,
3608
+ isLoading,
3609
+ error,
3610
+ refetch
3611
+ };
3612
+ }
3613
+ function clearEventLogoCache() {
3614
+ for (const [key] of authenticatedLogoCache) {
3615
+ if (key.startsWith("event_logo_")) {
3616
+ authenticatedLogoCache.delete(key);
3617
+ }
3618
+ }
3619
+ }
3620
+ function getEventLogoCacheStats() {
3621
+ const keys = Array.from(authenticatedLogoCache.keys()).filter((key) => key.startsWith("event_logo_"));
3622
+ return {
3623
+ size: keys.length,
3624
+ keys
3625
+ };
3626
+ }
3627
+
3086
3628
  // src/components/Table/Table.tsx
3087
- import * as React17 from "react";
3088
- import { jsx as jsx20 } from "react/jsx-runtime";
3089
- var Table = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
3629
+ import * as React18 from "react";
3630
+ import { jsx as jsx22 } from "react/jsx-runtime";
3631
+ var Table = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3090
3632
  "table",
3091
3633
  {
3092
3634
  ref,
@@ -3095,9 +3637,9 @@ var Table = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */
3095
3637
  }
3096
3638
  ));
3097
3639
  Table.displayName = "Table";
3098
- var TableHeader = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
3640
+ var TableHeader = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22("thead", { ref, className: cn("[&_tr]:border-b", className), ...props }));
3099
3641
  TableHeader.displayName = "TableHeader";
3100
- var TableBody = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
3642
+ var TableBody = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3101
3643
  "tbody",
3102
3644
  {
3103
3645
  ref,
@@ -3106,7 +3648,7 @@ var TableBody = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE_
3106
3648
  }
3107
3649
  ));
3108
3650
  TableBody.displayName = "TableBody";
3109
- var TableFooter = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
3651
+ var TableFooter = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3110
3652
  "tfoot",
3111
3653
  {
3112
3654
  ref,
@@ -3118,7 +3660,7 @@ var TableFooter = React17.forwardRef(({ className, ...props }, ref) => /* @__PUR
3118
3660
  }
3119
3661
  ));
3120
3662
  TableFooter.displayName = "TableFooter";
3121
- var TableRow = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
3663
+ var TableRow = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3122
3664
  "tr",
3123
3665
  {
3124
3666
  ref,
@@ -3130,7 +3672,7 @@ var TableRow = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__
3130
3672
  }
3131
3673
  ));
3132
3674
  TableRow.displayName = "TableRow";
3133
- var TableHead = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
3675
+ var TableHead = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3134
3676
  "th",
3135
3677
  {
3136
3678
  ref,
@@ -3142,7 +3684,7 @@ var TableHead = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE_
3142
3684
  }
3143
3685
  ));
3144
3686
  TableHead.displayName = "TableHead";
3145
- var TableCell = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
3687
+ var TableCell = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3146
3688
  "td",
3147
3689
  {
3148
3690
  ref,
@@ -3151,7 +3693,7 @@ var TableCell = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE_
3151
3693
  }
3152
3694
  ));
3153
3695
  TableCell.displayName = "TableCell";
3154
- var TableCaption = React17.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx20(
3696
+ var TableCaption = React18.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx22(
3155
3697
  "caption",
3156
3698
  {
3157
3699
  ref,
@@ -3162,9 +3704,9 @@ var TableCaption = React17.forwardRef(({ className, ...props }, ref) => /* @__PU
3162
3704
  TableCaption.displayName = "TableCaption";
3163
3705
 
3164
3706
  // src/components/PublicLayout/EventLogo.tsx
3165
- import { useMemo as useMemo6, useContext } from "react";
3707
+ import { useMemo as useMemo9, useContext } from "react";
3166
3708
  init_UnifiedAuthProvider();
3167
- import { jsx as jsx21 } from "react/jsx-runtime";
3709
+ import { jsx as jsx23 } from "react/jsx-runtime";
3168
3710
  var sizeClasses = {
3169
3711
  xs: "h-4 w-4 text-xs",
3170
3712
  sm: "h-6 w-6 text-sm",
@@ -3173,7 +3715,7 @@ var sizeClasses = {
3173
3715
  xl: "h-16 w-16 text-xl",
3174
3716
  "2xl": "h-20 w-20 text-2xl"
3175
3717
  };
3176
- function defaultGenerateFallbackText(eventName) {
3718
+ function defaultGenerateFallbackText2(eventName) {
3177
3719
  if (!eventName) return "EV";
3178
3720
  return eventName.split(" ").map((word) => word.charAt(0).toUpperCase()).join("").substring(0, 3);
3179
3721
  }
@@ -3195,7 +3737,7 @@ function EventLogoPublic({
3195
3737
  const hasValidOrganisationId = organisationId && uuidRegex.test(organisationId);
3196
3738
  if (!supabase) {
3197
3739
  const effectiveSize = size || "md";
3198
- return /* @__PURE__ */ jsx21("div", { className: `${sizeClasses[effectiveSize]} ${className}`.trim(), title: `${eventName} logo (Supabase not configured)`, children: eventName ? defaultGenerateFallbackText(eventName) : "EV" });
3740
+ return /* @__PURE__ */ jsx23("div", { className: `${sizeClasses[effectiveSize]} ${className}`.trim(), title: `${eventName} logo (Supabase not configured)`, children: eventName ? defaultGenerateFallbackText2(eventName) : "EV" });
3199
3741
  }
3200
3742
  const {
3201
3743
  logoUrl,
@@ -3213,36 +3755,36 @@ function EventLogoPublic({
3213
3755
  supabase
3214
3756
  }
3215
3757
  );
3216
- const sizeClass = useMemo6(() => sizeClasses[size || "md"], [size]);
3217
- const combinedClasses = useMemo6(() => {
3758
+ const sizeClass = useMemo9(() => sizeClasses[size || "md"], [size]);
3759
+ const combinedClasses = useMemo9(() => {
3218
3760
  const baseClasses = "flex items-center justify-center bg-gray-100 text-gray-600 font-semibold rounded";
3219
3761
  return `${baseClasses} ${sizeClass} ${className}`.trim();
3220
3762
  }, [sizeClass, className]);
3221
3763
  if (!hasValidOrganisationId && !isLoading && !logoUrl && showFallback) {
3222
- return /* @__PURE__ */ jsx21("div", { className: combinedClasses, title: `${eventName} logo (invalid organisation ID)`, children: fallbackText });
3764
+ return /* @__PURE__ */ jsx23("div", { className: combinedClasses, title: `${eventName} logo (invalid organisation ID)`, children: fallbackText });
3223
3765
  }
3224
3766
  if (isLoading) {
3225
3767
  if (LoadingComponent) {
3226
- return /* @__PURE__ */ jsx21(LoadingComponent, {});
3768
+ return /* @__PURE__ */ jsx23(LoadingComponent, {});
3227
3769
  }
3228
- return /* @__PURE__ */ jsx21("div", { className: `${combinedClasses} animate-pulse`, children: /* @__PURE__ */ jsx21("div", { className: "w-3/4 h-3/4 bg-gray-300 rounded" }) });
3770
+ return /* @__PURE__ */ jsx23("div", { className: `${combinedClasses} animate-pulse`, children: /* @__PURE__ */ jsx23("div", { className: "w-3/4 h-3/4 bg-gray-300 rounded" }) });
3229
3771
  }
3230
3772
  if (error) {
3231
3773
  if (ErrorComponent) {
3232
- return /* @__PURE__ */ jsx21(ErrorComponent, { error });
3774
+ return /* @__PURE__ */ jsx23(ErrorComponent, { error });
3233
3775
  }
3234
3776
  if (showFallback) {
3235
- return /* @__PURE__ */ jsx21("div", { className: combinedClasses, title: `${eventName} (logo unavailable)`, children: fallbackText });
3777
+ return /* @__PURE__ */ jsx23("div", { className: combinedClasses, title: `${eventName} (logo unavailable)`, children: fallbackText });
3236
3778
  }
3237
3779
  return null;
3238
3780
  }
3239
3781
  if (!logoUrl) {
3240
3782
  if (showFallback) {
3241
- return /* @__PURE__ */ jsx21("div", { className: combinedClasses, title: `${eventName} logo`, children: fallbackText });
3783
+ return /* @__PURE__ */ jsx23("div", { className: combinedClasses, title: `${eventName} logo`, children: fallbackText });
3242
3784
  }
3243
3785
  return null;
3244
3786
  }
3245
- return /* @__PURE__ */ jsx21(
3787
+ return /* @__PURE__ */ jsx23(
3246
3788
  "img",
3247
3789
  {
3248
3790
  src: logoUrl,
@@ -3277,54 +3819,53 @@ function EventLogoAuthenticated({
3277
3819
  const hasValidOrganisationId = organisationId && uuidRegex.test(organisationId);
3278
3820
  if (!supabase) {
3279
3821
  const effectiveSize = size || "md";
3280
- return /* @__PURE__ */ jsx21("div", { className: `${sizeClasses[effectiveSize]} ${className}`.trim(), title: `${eventName} logo (Supabase not configured)`, children: eventName ? defaultGenerateFallbackText(eventName) : "EV" });
3822
+ return /* @__PURE__ */ jsx23("div", { className: `${sizeClasses[effectiveSize]} ${className}`.trim(), title: `${eventName} logo (Supabase not configured)`, children: eventName ? defaultGenerateFallbackText2(eventName) : "EV" });
3281
3823
  }
3282
3824
  const {
3283
3825
  logoUrl,
3284
3826
  fallbackText,
3285
3827
  isLoading,
3286
3828
  error
3287
- } = usePublicEventLogo(
3829
+ } = useEventLogo(
3830
+ supabase,
3288
3831
  eventId,
3289
3832
  eventName,
3290
3833
  organisationId,
3291
- // Always pass organisationId, let the hook handle validation
3292
3834
  {
3293
3835
  validateImage,
3294
- generateFallbackText,
3295
- supabase
3836
+ generateFallbackText
3296
3837
  }
3297
3838
  );
3298
- const sizeClass = useMemo6(() => sizeClasses[size || "md"], [size]);
3299
- const combinedClasses = useMemo6(() => {
3839
+ const sizeClass = useMemo9(() => sizeClasses[size || "md"], [size]);
3840
+ const combinedClasses = useMemo9(() => {
3300
3841
  const baseClasses = "flex items-center justify-center bg-gray-100 text-gray-600 font-semibold rounded";
3301
3842
  return `${baseClasses} ${sizeClass} ${className}`.trim();
3302
3843
  }, [sizeClass, className]);
3303
3844
  if (!hasValidOrganisationId && !isLoading && !logoUrl && showFallback) {
3304
- return /* @__PURE__ */ jsx21("div", { className: combinedClasses, title: `${eventName} logo (invalid organisation ID)`, children: fallbackText });
3845
+ return /* @__PURE__ */ jsx23("div", { className: combinedClasses, title: `${eventName} logo (invalid organisation ID)`, children: fallbackText });
3305
3846
  }
3306
3847
  if (isLoading) {
3307
3848
  if (LoadingComponent) {
3308
- return /* @__PURE__ */ jsx21(LoadingComponent, {});
3849
+ return /* @__PURE__ */ jsx23(LoadingComponent, {});
3309
3850
  }
3310
- return /* @__PURE__ */ jsx21("div", { className: `${combinedClasses} animate-pulse`, children: /* @__PURE__ */ jsx21("div", { className: "w-3/4 h-3/4 bg-gray-300 rounded" }) });
3851
+ return /* @__PURE__ */ jsx23("div", { className: `${combinedClasses} animate-pulse`, children: /* @__PURE__ */ jsx23("div", { className: "w-3/4 h-3/4 bg-gray-300 rounded" }) });
3311
3852
  }
3312
3853
  if (error) {
3313
3854
  if (ErrorComponent) {
3314
- return /* @__PURE__ */ jsx21(ErrorComponent, { error });
3855
+ return /* @__PURE__ */ jsx23(ErrorComponent, { error });
3315
3856
  }
3316
3857
  if (showFallback) {
3317
- return /* @__PURE__ */ jsx21("div", { className: combinedClasses, title: `${eventName} (logo unavailable)`, children: fallbackText });
3858
+ return /* @__PURE__ */ jsx23("div", { className: combinedClasses, title: `${eventName} (logo unavailable)`, children: fallbackText });
3318
3859
  }
3319
3860
  return null;
3320
3861
  }
3321
3862
  if (!logoUrl) {
3322
3863
  if (showFallback) {
3323
- return /* @__PURE__ */ jsx21("div", { className: combinedClasses, title: `${eventName} logo`, children: fallbackText });
3864
+ return /* @__PURE__ */ jsx23("div", { className: combinedClasses, title: `${eventName} logo`, children: fallbackText });
3324
3865
  }
3325
3866
  return null;
3326
3867
  }
3327
- return /* @__PURE__ */ jsx21(
3868
+ return /* @__PURE__ */ jsx23(
3328
3869
  "img",
3329
3870
  {
3330
3871
  src: logoUrl,
@@ -3349,14 +3890,14 @@ function EventLogo({
3349
3890
  size = "md",
3350
3891
  className = "",
3351
3892
  showFallback = true,
3352
- generateFallbackText = defaultGenerateFallbackText,
3893
+ generateFallbackText = defaultGenerateFallbackText2,
3353
3894
  validateImage = true,
3354
3895
  loadingComponent: LoadingComponent,
3355
3896
  errorComponent: ErrorComponent
3356
3897
  }) {
3357
3898
  const isPublicPage = useIsPublicPage();
3358
3899
  if (isPublicPage) {
3359
- return /* @__PURE__ */ jsx21(
3900
+ return /* @__PURE__ */ jsx23(
3360
3901
  EventLogoPublic,
3361
3902
  {
3362
3903
  eventId,
@@ -3372,7 +3913,7 @@ function EventLogo({
3372
3913
  }
3373
3914
  );
3374
3915
  }
3375
- return /* @__PURE__ */ jsx21(
3916
+ return /* @__PURE__ */ jsx23(
3376
3917
  EventLogoAuthenticated,
3377
3918
  {
3378
3919
  eventId,
@@ -3389,7 +3930,7 @@ function EventLogo({
3389
3930
  );
3390
3931
  }
3391
3932
  function EventLogoCompact(props) {
3392
- return /* @__PURE__ */ jsx21(
3933
+ return /* @__PURE__ */ jsx23(
3393
3934
  EventLogo,
3394
3935
  {
3395
3936
  ...props,
@@ -3399,7 +3940,7 @@ function EventLogoCompact(props) {
3399
3940
  );
3400
3941
  }
3401
3942
  function EventLogoLarge(props) {
3402
- return /* @__PURE__ */ jsx21(
3943
+ return /* @__PURE__ */ jsx23(
3403
3944
  EventLogo,
3404
3945
  {
3405
3946
  ...props,
@@ -3410,7 +3951,7 @@ function EventLogoLarge(props) {
3410
3951
  }
3411
3952
 
3412
3953
  // src/components/PublicLayout/PublicPageHeader.tsx
3413
- import { Fragment as Fragment5, jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
3954
+ import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
3414
3955
  function PublicPageHeader({
3415
3956
  event,
3416
3957
  eventCode,
@@ -3425,10 +3966,10 @@ function PublicPageHeader({
3425
3966
  }) {
3426
3967
  const { appName } = useAppConfig();
3427
3968
  const headerClasses = `bg-white border-b border-gray-200 ${className}`.trim();
3428
- return /* @__PURE__ */ jsx22("header", { className: headerClasses, children: /* @__PURE__ */ jsxs16("div", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto", children: [
3429
- /* @__PURE__ */ jsxs16("div", { className: "flex items-center justify-between py-4", children: [
3430
- showAppLogo && /* @__PURE__ */ jsx22("div", { className: "flex-shrink-0", children: customAppLogo || /* @__PURE__ */ jsxs16("div", { className: "flex items-center", children: [
3431
- /* @__PURE__ */ jsx22(
3969
+ return /* @__PURE__ */ jsx24("header", { className: headerClasses, children: /* @__PURE__ */ jsxs18("div", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto", children: [
3970
+ /* @__PURE__ */ jsxs18("div", { className: "flex items-center justify-between py-4", children: [
3971
+ showAppLogo && /* @__PURE__ */ jsx24("div", { className: "flex-shrink-0", children: customAppLogo || /* @__PURE__ */ jsxs18("div", { className: "flex items-center", children: [
3972
+ /* @__PURE__ */ jsx24(
3432
3973
  "img",
3433
3974
  {
3434
3975
  className: "h-8 w-auto",
@@ -3436,9 +3977,9 @@ function PublicPageHeader({
3436
3977
  alt: appName
3437
3978
  }
3438
3979
  ),
3439
- /* @__PURE__ */ jsx22("span", { className: "ml-2 text-lg font-semibold text-gray-900", children: appName })
3980
+ /* @__PURE__ */ jsx24("span", { className: "ml-2 text-lg font-semibold text-gray-900", children: appName })
3440
3981
  ] }) }),
3441
- showEventLogo && event && /* @__PURE__ */ jsx22("div", { className: "flex-shrink-0", children: customEventLogo || /* @__PURE__ */ jsx22(
3982
+ showEventLogo && event && /* @__PURE__ */ jsx24("div", { className: "flex-shrink-0", children: customEventLogo || /* @__PURE__ */ jsx24(
3442
3983
  EventLogo,
3443
3984
  {
3444
3985
  eventId: event.event_id,
@@ -3449,22 +3990,22 @@ function PublicPageHeader({
3449
3990
  }
3450
3991
  ) })
3451
3992
  ] }),
3452
- /* @__PURE__ */ jsx22("div", { className: "pb-4", children: /* @__PURE__ */ jsxs16("div", { className: "text-center", children: [
3453
- event && /* @__PURE__ */ jsxs16(Fragment5, { children: [
3454
- /* @__PURE__ */ jsx22("h1", { className: "text-3xl font-bold text-gray-900 mb-2", children: event.event_name }),
3455
- event.event_venue && /* @__PURE__ */ jsx22("p", { className: "text-md text-gray-500 mb-4", children: event.event_venue })
3993
+ /* @__PURE__ */ jsx24("div", { className: "pb-4", children: /* @__PURE__ */ jsxs18("div", { className: "text-center", children: [
3994
+ event && /* @__PURE__ */ jsxs18(Fragment6, { children: [
3995
+ /* @__PURE__ */ jsx24("h1", { className: "text-3xl font-bold text-gray-900 mb-2", children: event.event_name }),
3996
+ event.event_venue && /* @__PURE__ */ jsx24("p", { className: "text-md text-gray-500 mb-4", children: event.event_venue })
3456
3997
  ] }),
3457
- title && /* @__PURE__ */ jsxs16("div", { className: "mt-6", children: [
3458
- /* @__PURE__ */ jsx22("h2", { className: "text-2xl font-semibold text-gray-800 mb-2", children: title }),
3459
- description && /* @__PURE__ */ jsx22("p", { className: "text-lg text-gray-600 max-w-3xl mx-auto", children: description })
3998
+ title && /* @__PURE__ */ jsxs18("div", { className: "mt-6", children: [
3999
+ /* @__PURE__ */ jsx24("h2", { className: "text-2xl font-semibold text-gray-800 mb-2", children: title }),
4000
+ description && /* @__PURE__ */ jsx24("p", { className: "text-lg text-gray-600 max-w-3xl mx-auto", children: description })
3460
4001
  ] }),
3461
- children && /* @__PURE__ */ jsx22("div", { className: "mt-4", children })
4002
+ children && /* @__PURE__ */ jsx24("div", { className: "mt-4", children })
3462
4003
  ] }) })
3463
4004
  ] }) });
3464
4005
  }
3465
4006
 
3466
4007
  // src/components/PublicLayout/PublicPageFooter.tsx
3467
- import { Fragment as Fragment6, jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
4008
+ import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
3468
4009
  function PublicPageFooter({
3469
4010
  event,
3470
4011
  companyName = "Solvera Solutions Pty Ltd",
@@ -3476,16 +4017,16 @@ function PublicPageFooter({
3476
4017
  children
3477
4018
  }) {
3478
4019
  const copyrightText = copyright || `\xA9 Copyright 2022\u2013${year} all rights reserved, ${companyName}.`;
3479
- return /* @__PURE__ */ jsx23("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs17("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
3480
- logo && /* @__PURE__ */ jsx23("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
3481
- children && /* @__PURE__ */ jsx23(Fragment6, { children }),
3482
- /* @__PURE__ */ jsx23("span", { className: "text-muted-foreground", children: copyrightText }),
3483
- links && links.length > 0 && /* @__PURE__ */ jsx23("ul", { className: "flex gap-4 mt-2 md:mt-0", children: links.map((link, index) => /* @__PURE__ */ jsx23("li", { children: /* @__PURE__ */ jsx23("a", { href: link.href, className: "text-muted-foreground hover:text-foreground", children: link.label }) }, index)) })
4020
+ return /* @__PURE__ */ jsx25("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs19("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
4021
+ logo && /* @__PURE__ */ jsx25("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
4022
+ children && /* @__PURE__ */ jsx25(Fragment7, { children }),
4023
+ /* @__PURE__ */ jsx25("span", { className: "text-muted-foreground", children: copyrightText }),
4024
+ links && links.length > 0 && /* @__PURE__ */ jsx25("ul", { className: "flex gap-4 mt-2 md:mt-0", children: links.map((link, index) => /* @__PURE__ */ jsx25("li", { children: /* @__PURE__ */ jsx25("a", { href: link.href, className: "text-muted-foreground hover:text-foreground", children: link.label }) }, index)) })
3484
4025
  ] }) });
3485
4026
  }
3486
4027
 
3487
4028
  // src/components/PublicLayout/PublicLoadingSpinner.tsx
3488
- import { jsx as jsx24, jsxs as jsxs18 } from "react/jsx-runtime";
4029
+ import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
3489
4030
  var sizeClasses2 = {
3490
4031
  sm: "h-4 w-4",
3491
4032
  md: "h-8 w-8",
@@ -3502,8 +4043,8 @@ function PublicLoadingSpinner({
3502
4043
  }) {
3503
4044
  const sizeClass = sizeClasses2[size];
3504
4045
  const displayMessage = customMessage || message;
3505
- const content = /* @__PURE__ */ jsxs18("div", { className: `flex flex-col items-center ${className}`, children: [
3506
- showLogo && /* @__PURE__ */ jsx24("div", { className: "mb-4", children: /* @__PURE__ */ jsx24(
4046
+ const content = /* @__PURE__ */ jsxs20("div", { className: `flex flex-col items-center ${className}`, children: [
4047
+ showLogo && /* @__PURE__ */ jsx26("div", { className: "mb-4", children: /* @__PURE__ */ jsx26(
3507
4048
  "img",
3508
4049
  {
3509
4050
  className: "h-8 w-auto",
@@ -3511,8 +4052,8 @@ function PublicLoadingSpinner({
3511
4052
  alt: "PACE Core"
3512
4053
  }
3513
4054
  ) }),
3514
- /* @__PURE__ */ jsxs18("div", { className: "relative", children: [
3515
- /* @__PURE__ */ jsx24(
4055
+ /* @__PURE__ */ jsxs20("div", { className: "relative", children: [
4056
+ /* @__PURE__ */ jsx26(
3516
4057
  "div",
3517
4058
  {
3518
4059
  className: `${sizeClass} border-2 border-gray-200 border-t-blue-600 rounded-full animate-spin`,
@@ -3520,12 +4061,12 @@ function PublicLoadingSpinner({
3520
4061
  "aria-label": "Loading"
3521
4062
  }
3522
4063
  ),
3523
- /* @__PURE__ */ jsx24("span", { className: "sr-only", children: displayMessage })
4064
+ /* @__PURE__ */ jsx26("span", { className: "sr-only", children: displayMessage })
3524
4065
  ] }),
3525
- displayMessage && /* @__PURE__ */ jsx24("p", { className: "mt-4 text-sm text-gray-600 text-center", children: displayMessage })
4066
+ displayMessage && /* @__PURE__ */ jsx26("p", { className: "mt-4 text-sm text-gray-600 text-center", children: displayMessage })
3526
4067
  ] });
3527
4068
  if (centered) {
3528
- return /* @__PURE__ */ jsx24("div", { className: "min-h-screen bg-white flex items-center justify-center", children: /* @__PURE__ */ jsx24("div", { className: "max-w-md mx-auto px-4", children: content }) });
4069
+ return /* @__PURE__ */ jsx26("div", { className: "min-h-screen bg-white flex items-center justify-center", children: /* @__PURE__ */ jsx26("div", { className: "max-w-md mx-auto px-4", children: content }) });
3529
4070
  }
3530
4071
  return content;
3531
4072
  }
@@ -3534,8 +4075,8 @@ function PublicLoadingSpinnerFullPage({
3534
4075
  eventName,
3535
4076
  className = ""
3536
4077
  }) {
3537
- return /* @__PURE__ */ jsx24("div", { className: `min-h-screen bg-white flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs18("div", { className: "max-w-md mx-auto text-center px-4", children: [
3538
- /* @__PURE__ */ jsx24("div", { className: "mb-8", children: /* @__PURE__ */ jsx24(
4078
+ return /* @__PURE__ */ jsx26("div", { className: `min-h-screen bg-white flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs20("div", { className: "max-w-md mx-auto text-center px-4", children: [
4079
+ /* @__PURE__ */ jsx26("div", { className: "mb-8", children: /* @__PURE__ */ jsx26(
3539
4080
  "img",
3540
4081
  {
3541
4082
  className: "h-12 w-auto mx-auto",
@@ -3543,8 +4084,8 @@ function PublicLoadingSpinnerFullPage({
3543
4084
  alt: "PACE Core"
3544
4085
  }
3545
4086
  ) }),
3546
- eventName && /* @__PURE__ */ jsx24("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: eventName }),
3547
- /* @__PURE__ */ jsx24("div", { className: "relative mb-6", children: /* @__PURE__ */ jsx24(
4087
+ eventName && /* @__PURE__ */ jsx26("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: eventName }),
4088
+ /* @__PURE__ */ jsx26("div", { className: "relative mb-6", children: /* @__PURE__ */ jsx26(
3548
4089
  "div",
3549
4090
  {
3550
4091
  className: "h-12 w-12 border-4 border-gray-200 border-t-blue-600 rounded-full animate-spin mx-auto",
@@ -3552,11 +4093,11 @@ function PublicLoadingSpinnerFullPage({
3552
4093
  "aria-label": "Loading"
3553
4094
  }
3554
4095
  ) }),
3555
- /* @__PURE__ */ jsx24("p", { className: "text-lg text-gray-600", children: message }),
3556
- /* @__PURE__ */ jsxs18("div", { className: "mt-4 flex justify-center space-x-1", children: [
3557
- /* @__PURE__ */ jsx24("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
3558
- /* @__PURE__ */ jsx24("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
3559
- /* @__PURE__ */ jsx24("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "300ms" } })
4096
+ /* @__PURE__ */ jsx26("p", { className: "text-lg text-gray-600", children: message }),
4097
+ /* @__PURE__ */ jsxs20("div", { className: "mt-4 flex justify-center space-x-1", children: [
4098
+ /* @__PURE__ */ jsx26("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
4099
+ /* @__PURE__ */ jsx26("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
4100
+ /* @__PURE__ */ jsx26("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "300ms" } })
3560
4101
  ] })
3561
4102
  ] }) });
3562
4103
  }
@@ -3564,7 +4105,7 @@ function PublicLoadingSkeleton({
3564
4105
  lines = 3,
3565
4106
  className = ""
3566
4107
  }) {
3567
- return /* @__PURE__ */ jsx24("div", { className: `animate-pulse ${className}`, children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ jsx24(
4108
+ return /* @__PURE__ */ jsx26("div", { className: `animate-pulse ${className}`, children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ jsx26(
3568
4109
  "div",
3569
4110
  {
3570
4111
  className: `h-4 bg-gray-200 rounded mb-2 ${index === lines - 1 ? "w-3/4" : "w-full"}`
@@ -3574,8 +4115,8 @@ function PublicLoadingSkeleton({
3574
4115
  }
3575
4116
 
3576
4117
  // src/components/PublicLayout/PublicPageLayout.tsx
3577
- import { useMemo as useMemo7 } from "react";
3578
- import { jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
4118
+ import { useMemo as useMemo10 } from "react";
4119
+ import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
3579
4120
  function PublicPageLayout({
3580
4121
  eventCode,
3581
4122
  children,
@@ -3592,22 +4133,22 @@ function PublicPageLayout({
3592
4133
  const error = null;
3593
4134
  const refetch = async () => {
3594
4135
  };
3595
- const layoutClasses = useMemo7(() => {
4136
+ const layoutClasses = useMemo10(() => {
3596
4137
  const baseClasses = "min-h-screen bg-white flex flex-col";
3597
4138
  return `${baseClasses} ${className}`.trim();
3598
4139
  }, [className]);
3599
4140
  if (isLoading) {
3600
- return /* @__PURE__ */ jsx25("div", { className: layoutClasses, children: /* @__PURE__ */ jsx25("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsx25(LoadingFallback, {}) }) });
4141
+ return /* @__PURE__ */ jsx27("div", { className: layoutClasses, children: /* @__PURE__ */ jsx27("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsx27(LoadingFallback, {}) }) });
3601
4142
  }
3602
4143
  if (error && showValidationErrors) {
3603
- return /* @__PURE__ */ jsx25("div", { className: layoutClasses, children: /* @__PURE__ */ jsx25("div", { className: "flex-1 flex items-center justify-center", children: ErrorFallback ? /* @__PURE__ */ jsx25(ErrorFallback, { error, retry: refetch }) : /* @__PURE__ */ jsxs19("div", { className: "text-center p-8", children: [
3604
- /* @__PURE__ */ jsx25("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Found" }),
3605
- /* @__PURE__ */ jsxs19("p", { className: "text-gray-600 mb-6", children: [
4144
+ return /* @__PURE__ */ jsx27("div", { className: layoutClasses, children: /* @__PURE__ */ jsx27("div", { className: "flex-1 flex items-center justify-center", children: ErrorFallback ? /* @__PURE__ */ jsx27(ErrorFallback, { error, retry: refetch }) : /* @__PURE__ */ jsxs21("div", { className: "text-center p-8", children: [
4145
+ /* @__PURE__ */ jsx27("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Found" }),
4146
+ /* @__PURE__ */ jsxs21("p", { className: "text-gray-600 mb-6", children: [
3606
4147
  'The event code "',
3607
4148
  eventCode,
3608
4149
  '" is invalid or the event is not available for public viewing.'
3609
4150
  ] }),
3610
- /* @__PURE__ */ jsx25(
4151
+ /* @__PURE__ */ jsx27(
3611
4152
  "button",
3612
4153
  {
3613
4154
  onClick: refetch,
@@ -3618,10 +4159,10 @@ function PublicPageLayout({
3618
4159
  ] }) }) });
3619
4160
  }
3620
4161
  if (!event) {
3621
- return /* @__PURE__ */ jsx25("div", { className: layoutClasses, children: /* @__PURE__ */ jsx25("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs19("div", { className: "text-center p-8", children: [
3622
- /* @__PURE__ */ jsx25("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Available" }),
3623
- /* @__PURE__ */ jsx25("p", { className: "text-gray-600 mb-6", children: "This event is not available for public viewing." }),
3624
- /* @__PURE__ */ jsx25(
4162
+ return /* @__PURE__ */ jsx27("div", { className: layoutClasses, children: /* @__PURE__ */ jsx27("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs21("div", { className: "text-center p-8", children: [
4163
+ /* @__PURE__ */ jsx27("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Available" }),
4164
+ /* @__PURE__ */ jsx27("p", { className: "text-gray-600 mb-6", children: "This event is not available for public viewing." }),
4165
+ /* @__PURE__ */ jsx27(
3625
4166
  "button",
3626
4167
  {
3627
4168
  onClick: refetch,
@@ -3631,16 +4172,16 @@ function PublicPageLayout({
3631
4172
  )
3632
4173
  ] }) }) });
3633
4174
  }
3634
- return /* @__PURE__ */ jsx25(PublicErrorBoundary, { children: /* @__PURE__ */ jsxs19("div", { className: layoutClasses, children: [
3635
- customHeader || /* @__PURE__ */ jsx25(
4175
+ return /* @__PURE__ */ jsx27(PublicErrorBoundary, { children: /* @__PURE__ */ jsxs21("div", { className: layoutClasses, children: [
4176
+ customHeader || /* @__PURE__ */ jsx27(
3636
4177
  PublicPageHeader,
3637
4178
  {
3638
4179
  event,
3639
4180
  eventCode
3640
4181
  }
3641
4182
  ),
3642
- /* @__PURE__ */ jsx25("main", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children }),
3643
- showFooter && (customFooter || /* @__PURE__ */ jsx25(PublicPageFooter, { event }))
4183
+ /* @__PURE__ */ jsx27("main", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children }),
4184
+ showFooter && (customFooter || /* @__PURE__ */ jsx27(PublicPageFooter, { event }))
3644
4185
  ] }) });
3645
4186
  }
3646
4187
  function usePublicPageContext2() {
@@ -3657,10 +4198,10 @@ function usePublicPageContext2() {
3657
4198
  }
3658
4199
 
3659
4200
  // src/components/PublicLayout/PublicPageDebugger.tsx
3660
- import { useEffect as useEffect6 } from "react";
3661
- import { jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
4201
+ import { useEffect as useEffect9 } from "react";
4202
+ import { jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
3662
4203
  function PublicPageDebugger({ enabled = true, label = "PublicPage" }) {
3663
- useEffect6(() => {
4204
+ useEffect9(() => {
3664
4205
  if (!enabled) return;
3665
4206
  console.log(`[${label}] Component mounted`);
3666
4207
  try {
@@ -3701,7 +4242,7 @@ function PublicPageDebugger({ enabled = true, label = "PublicPage" }) {
3701
4242
  };
3702
4243
  }, [enabled, label]);
3703
4244
  if (!enabled) return null;
3704
- return /* @__PURE__ */ jsxs20("div", { style: {
4245
+ return /* @__PURE__ */ jsxs22("div", { style: {
3705
4246
  position: "fixed",
3706
4247
  top: 0,
3707
4248
  right: 0,
@@ -3712,16 +4253,16 @@ function PublicPageDebugger({ enabled = true, label = "PublicPage" }) {
3712
4253
  zIndex: 9999,
3713
4254
  fontFamily: "monospace"
3714
4255
  }, children: [
3715
- /* @__PURE__ */ jsx26("div", { children: "Public Page Debugger" }),
3716
- /* @__PURE__ */ jsx26("div", { children: "Check console for context analysis" })
4256
+ /* @__PURE__ */ jsx28("div", { children: "Public Page Debugger" }),
4257
+ /* @__PURE__ */ jsx28("div", { children: "Check console for context analysis" })
3717
4258
  ] });
3718
4259
  }
3719
4260
 
3720
4261
  // src/components/PublicLayout/PublicPageDiagnostic.tsx
3721
- import { useEffect as useEffect7, useState as useState12 } from "react";
3722
- import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
4262
+ import { useEffect as useEffect10, useState as useState13 } from "react";
4263
+ import { jsx as jsx29, jsxs as jsxs23 } from "react/jsx-runtime";
3723
4264
  function PublicPageDiagnostic({ enabled = true, label = "PublicPage" }) {
3724
- const [diagnostics, setDiagnostics] = useState12({
4265
+ const [diagnostics, setDiagnostics] = useState13({
3725
4266
  hasPublicPageContext: false,
3726
4267
  hasAuthContext: false,
3727
4268
  hasOrgContext: false,
@@ -3729,7 +4270,7 @@ function PublicPageDiagnostic({ enabled = true, label = "PublicPage" }) {
3729
4270
  hasEnvironmentVars: false,
3730
4271
  routeParams: null
3731
4272
  });
3732
- useEffect7(() => {
4273
+ useEffect10(() => {
3733
4274
  if (!enabled) return;
3734
4275
  const runDiagnostics = () => {
3735
4276
  const newDiagnostics = {
@@ -3800,7 +4341,7 @@ function PublicPageDiagnostic({ enabled = true, label = "PublicPage" }) {
3800
4341
  runDiagnostics();
3801
4342
  }, [enabled, label]);
3802
4343
  if (!enabled) return null;
3803
- return /* @__PURE__ */ jsxs21("div", { style: {
4344
+ return /* @__PURE__ */ jsxs23("div", { style: {
3804
4345
  position: "fixed",
3805
4346
  top: 0,
3806
4347
  left: 0,
@@ -3813,40 +4354,40 @@ function PublicPageDiagnostic({ enabled = true, label = "PublicPage" }) {
3813
4354
  maxWidth: "300px",
3814
4355
  borderRadius: "0 0 8px 0"
3815
4356
  }, children: [
3816
- /* @__PURE__ */ jsx27("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F50D} Public Page Diagnostics" }),
3817
- /* @__PURE__ */ jsxs21("div", { children: [
4357
+ /* @__PURE__ */ jsx29("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F50D} Public Page Diagnostics" }),
4358
+ /* @__PURE__ */ jsxs23("div", { children: [
3818
4359
  "Public Context: ",
3819
4360
  diagnostics.hasPublicPageContext ? "\u2705" : "\u274C"
3820
4361
  ] }),
3821
- /* @__PURE__ */ jsxs21("div", { children: [
4362
+ /* @__PURE__ */ jsxs23("div", { children: [
3822
4363
  "Auth Context: ",
3823
4364
  diagnostics.hasAuthContext ? "\u274C BAD" : "\u2705 GOOD"
3824
4365
  ] }),
3825
- /* @__PURE__ */ jsxs21("div", { children: [
4366
+ /* @__PURE__ */ jsxs23("div", { children: [
3826
4367
  "Org Context: ",
3827
4368
  diagnostics.hasOrgContext ? "\u274C BAD" : "\u2705 GOOD"
3828
4369
  ] }),
3829
- /* @__PURE__ */ jsxs21("div", { children: [
4370
+ /* @__PURE__ */ jsxs23("div", { children: [
3830
4371
  "Event Context: ",
3831
4372
  diagnostics.hasEventContext ? "\u274C BAD" : "\u2705 GOOD"
3832
4373
  ] }),
3833
- /* @__PURE__ */ jsxs21("div", { children: [
4374
+ /* @__PURE__ */ jsxs23("div", { children: [
3834
4375
  "Env Vars: ",
3835
4376
  diagnostics.hasEnvironmentVars ? "\u2705" : "\u274C"
3836
4377
  ] }),
3837
- /* @__PURE__ */ jsxs21("div", { children: [
4378
+ /* @__PURE__ */ jsxs23("div", { children: [
3838
4379
  "Route Params: ",
3839
4380
  diagnostics.routeParams ? "\u2705" : "\u274C"
3840
4381
  ] }),
3841
- /* @__PURE__ */ jsx27("div", { style: { marginTop: "8px", fontSize: "10px", opacity: 0.8 }, children: "Check console for detailed analysis" })
4382
+ /* @__PURE__ */ jsx29("div", { style: { marginTop: "8px", fontSize: "10px", opacity: 0.8 }, children: "Check console for detailed analysis" })
3842
4383
  ] });
3843
4384
  }
3844
4385
 
3845
4386
  // src/components/PublicLayout/PublicPageContextChecker.tsx
3846
- import { useEffect as useEffect8 } from "react";
3847
- import { jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
4387
+ import { useEffect as useEffect11 } from "react";
4388
+ import { jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
3848
4389
  function PublicPageContextChecker({ enabled = true, label = "PublicPage" }) {
3849
- useEffect8(() => {
4390
+ useEffect11(() => {
3850
4391
  if (!enabled) return;
3851
4392
  console.group(`\u{1F6A8} [${label}] PUBLIC PAGE CONTEXT CHECK`);
3852
4393
  try {
@@ -3908,7 +4449,7 @@ function PublicPageContextChecker({ enabled = true, label = "PublicPage" }) {
3908
4449
  console.groupEnd();
3909
4450
  }, [enabled, label]);
3910
4451
  if (!enabled) return null;
3911
- return /* @__PURE__ */ jsxs22("div", { style: {
4452
+ return /* @__PURE__ */ jsxs24("div", { style: {
3912
4453
  position: "fixed",
3913
4454
  top: 0,
3914
4455
  left: 0,
@@ -3922,9 +4463,9 @@ function PublicPageContextChecker({ enabled = true, label = "PublicPage" }) {
3922
4463
  borderRadius: "0 0 8px 0",
3923
4464
  border: "2px solid #dc2626"
3924
4465
  }, children: [
3925
- /* @__PURE__ */ jsx28("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F6A8} PUBLIC PAGE CONTEXT CHECK" }),
3926
- /* @__PURE__ */ jsx28("div", { children: "Check console for authentication context analysis" }),
3927
- /* @__PURE__ */ jsx28("div", { style: { marginTop: "8px", fontSize: "10px", opacity: 0.9 }, children: "If you see \u274C errors in console, your public page is inside auth context!" })
4466
+ /* @__PURE__ */ jsx30("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F6A8} PUBLIC PAGE CONTEXT CHECK" }),
4467
+ /* @__PURE__ */ jsx30("div", { children: "Check console for authentication context analysis" }),
4468
+ /* @__PURE__ */ jsx30("div", { style: { marginTop: "8px", fontSize: "10px", opacity: 0.9 }, children: "If you see \u274C errors in console, your public page is inside auth context!" })
3928
4469
  ] });
3929
4470
  }
3930
4471
 
@@ -3955,30 +4496,18 @@ export {
3955
4496
  PaceAppLayout,
3956
4497
  PaceLoginPage,
3957
4498
  ErrorBoundary,
4499
+ SessionRestorationLoader,
3958
4500
  OrganisationSelector,
3959
4501
  PasswordResetForm,
3960
- FILE_SIZE_LIMITS,
3961
- DEFAULT_FILE_SIZE_LIMIT,
3962
- APP_PATH_MAPPING,
3963
- STORAGE_CONFIG,
3964
- getFileSizeLimit,
3965
- validateFileSize,
3966
- formatFileSize,
3967
- generateFilePath,
3968
- generateUniqueFileName,
3969
- extractFileMetadata,
3970
- uploadFile,
3971
- getPublicUrl,
3972
- getSignedUrl,
3973
- deleteFile,
3974
- listFiles,
3975
- archiveFile,
3976
- StorageUtils,
3977
- useStorage,
3978
- useFileUpload,
3979
4502
  useFileReference,
3980
4503
  useFileReferenceForRecord,
4504
+ useFileReferenceById,
4505
+ useFilesByCategory,
4506
+ FileUpload,
3981
4507
  FileDisplay,
4508
+ useEventLogo,
4509
+ clearEventLogoCache,
4510
+ getEventLogoCacheStats,
3982
4511
  Table,
3983
4512
  TableHeader,
3984
4513
  TableBody,
@@ -4001,4 +4530,4 @@ export {
4001
4530
  PublicPageDiagnostic,
4002
4531
  PublicPageContextChecker
4003
4532
  };
4004
- //# sourceMappingURL=chunk-I7O3RSMN.js.map
4533
+ //# sourceMappingURL=chunk-YWAFPVJA.js.map