@jmruthers/pace-core 0.5.92 → 0.5.94

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 (176) hide show
  1. package/dist/{DataTable-HC5S4RKB.js → DataTable-CHX2EFO3.js} +6 -6
  2. package/dist/{PublicLoadingSpinner-n74JgA9h.d.ts → PublicLoadingSpinner-BWUD6bLU.d.ts} +24 -3
  3. package/dist/{UnifiedAuthProvider-ZM7VUC45.js → UnifiedAuthProvider-H7RI4KYD.js} +3 -3
  4. package/dist/{chunk-AZ2QJYKU.js → chunk-2KLAOD4M.js} +3 -3
  5. package/dist/{chunk-HW5BGOWB.js → chunk-2ZYHCFUO.js} +4 -4
  6. package/dist/{chunk-AAM57AEU.js → chunk-5RYPBJYL.js} +16 -19
  7. package/dist/chunk-5RYPBJYL.js.map +1 -0
  8. package/dist/{chunk-XIBSVWJW.js → chunk-7TQDRDSM.js} +5 -5
  9. package/dist/{chunk-GP3HU6WS.js → chunk-G7UUVEAP.js} +3 -3
  10. package/dist/{chunk-M52CQP5W.js → chunk-MKMKUCPF.js} +762 -12
  11. package/dist/chunk-MKMKUCPF.js.map +1 -0
  12. package/dist/{chunk-OXFOS62D.js → chunk-MVNOAHOP.js} +2 -2
  13. package/dist/{chunk-5LAY74WM.js → chunk-O6GASC4Q.js} +877 -788
  14. package/dist/chunk-O6GASC4Q.js.map +1 -0
  15. package/dist/{chunk-AYC2P377.js → chunk-ORACUZ7H.js} +2 -2
  16. package/dist/{chunk-TZXYSZT3.js → chunk-PRM6EYO3.js} +298 -238
  17. package/dist/{chunk-TZXYSZT3.js.map → chunk-PRM6EYO3.js.map} +1 -1
  18. package/dist/{chunk-6WFM22A4.js → chunk-ZGCVJ7WW.js} +2 -2
  19. package/dist/components.d.ts +1 -1
  20. package/dist/components.js +8 -8
  21. package/dist/hooks.d.ts +94 -3
  22. package/dist/hooks.js +20 -8
  23. package/dist/hooks.js.map +1 -1
  24. package/dist/index.d.ts +2 -2
  25. package/dist/index.js +17 -11
  26. package/dist/index.js.map +1 -1
  27. package/dist/providers.js +2 -2
  28. package/dist/rbac/index.js +7 -7
  29. package/dist/{usePublicRouteParams-BlgwXweB.d.ts → usePublicRouteParams-BwMR2uub.d.ts} +93 -1
  30. package/dist/utils.js +1 -1
  31. package/docs/api/classes/ColumnFactory.md +1 -1
  32. package/docs/api/classes/ErrorBoundary.md +1 -1
  33. package/docs/api/classes/InvalidScopeError.md +1 -1
  34. package/docs/api/classes/MissingUserContextError.md +1 -1
  35. package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
  36. package/docs/api/classes/PermissionDeniedError.md +1 -1
  37. package/docs/api/classes/PublicErrorBoundary.md +1 -1
  38. package/docs/api/classes/RBACAuditManager.md +1 -1
  39. package/docs/api/classes/RBACCache.md +1 -1
  40. package/docs/api/classes/RBACEngine.md +1 -1
  41. package/docs/api/classes/RBACError.md +1 -1
  42. package/docs/api/classes/RBACNotInitializedError.md +1 -1
  43. package/docs/api/classes/SecureSupabaseClient.md +1 -1
  44. package/docs/api/classes/StorageUtils.md +1 -1
  45. package/docs/api/enums/FileCategory.md +1 -1
  46. package/docs/api/interfaces/AggregateConfig.md +1 -1
  47. package/docs/api/interfaces/ButtonProps.md +1 -1
  48. package/docs/api/interfaces/CardProps.md +1 -1
  49. package/docs/api/interfaces/ColorPalette.md +1 -1
  50. package/docs/api/interfaces/ColorShade.md +1 -1
  51. package/docs/api/interfaces/DataAccessRecord.md +1 -1
  52. package/docs/api/interfaces/DataRecord.md +1 -1
  53. package/docs/api/interfaces/DataTableAction.md +1 -1
  54. package/docs/api/interfaces/DataTableColumn.md +1 -1
  55. package/docs/api/interfaces/DataTableProps.md +1 -1
  56. package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
  57. package/docs/api/interfaces/EmptyStateConfig.md +1 -1
  58. package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
  59. package/docs/api/interfaces/EventLogoProps.md +1 -1
  60. package/docs/api/interfaces/FileDisplayProps.md +26 -11
  61. package/docs/api/interfaces/FileMetadata.md +1 -1
  62. package/docs/api/interfaces/FileReference.md +1 -1
  63. package/docs/api/interfaces/FileSizeLimits.md +1 -1
  64. package/docs/api/interfaces/FileUploadOptions.md +1 -1
  65. package/docs/api/interfaces/FileUploadProps.md +1 -1
  66. package/docs/api/interfaces/FooterProps.md +1 -1
  67. package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
  68. package/docs/api/interfaces/InputProps.md +1 -1
  69. package/docs/api/interfaces/LabelProps.md +1 -1
  70. package/docs/api/interfaces/LoginFormProps.md +1 -1
  71. package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
  72. package/docs/api/interfaces/NavigationContextType.md +1 -1
  73. package/docs/api/interfaces/NavigationGuardProps.md +1 -1
  74. package/docs/api/interfaces/NavigationItem.md +1 -1
  75. package/docs/api/interfaces/NavigationMenuProps.md +1 -1
  76. package/docs/api/interfaces/NavigationProviderProps.md +1 -1
  77. package/docs/api/interfaces/Organisation.md +1 -1
  78. package/docs/api/interfaces/OrganisationContextType.md +1 -1
  79. package/docs/api/interfaces/OrganisationMembership.md +1 -1
  80. package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
  81. package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
  82. package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
  83. package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
  84. package/docs/api/interfaces/PageAccessRecord.md +1 -1
  85. package/docs/api/interfaces/PagePermissionContextType.md +1 -1
  86. package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
  87. package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
  88. package/docs/api/interfaces/PaletteData.md +1 -1
  89. package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
  90. package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
  91. package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
  92. package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
  93. package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
  94. package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
  95. package/docs/api/interfaces/PublicPageHeaderProps.md +24 -11
  96. package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
  97. package/docs/api/interfaces/RBACConfig.md +1 -1
  98. package/docs/api/interfaces/RBACLogger.md +1 -1
  99. package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
  100. package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
  101. package/docs/api/interfaces/RouteAccessRecord.md +1 -1
  102. package/docs/api/interfaces/RouteConfig.md +1 -1
  103. package/docs/api/interfaces/SecureDataContextType.md +1 -1
  104. package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
  105. package/docs/api/interfaces/StorageConfig.md +1 -1
  106. package/docs/api/interfaces/StorageFileInfo.md +1 -1
  107. package/docs/api/interfaces/StorageFileMetadata.md +1 -1
  108. package/docs/api/interfaces/StorageListOptions.md +1 -1
  109. package/docs/api/interfaces/StorageListResult.md +1 -1
  110. package/docs/api/interfaces/StorageUploadOptions.md +1 -1
  111. package/docs/api/interfaces/StorageUploadResult.md +1 -1
  112. package/docs/api/interfaces/StorageUrlOptions.md +1 -1
  113. package/docs/api/interfaces/StyleImport.md +1 -1
  114. package/docs/api/interfaces/SwitchProps.md +1 -1
  115. package/docs/api/interfaces/ToastActionElement.md +1 -1
  116. package/docs/api/interfaces/ToastProps.md +1 -1
  117. package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
  118. package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
  119. package/docs/api/interfaces/UseEventLogoOptions.md +1 -1
  120. package/docs/api/interfaces/UseEventLogoReturn.md +1 -1
  121. package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
  122. package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
  123. package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
  124. package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
  125. package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
  126. package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
  127. package/docs/api/interfaces/UsePublicFileDisplayOptions.md +47 -0
  128. package/docs/api/interfaces/UsePublicFileDisplayReturn.md +120 -0
  129. package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
  130. package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
  131. package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
  132. package/docs/api/interfaces/UserEventAccess.md +1 -1
  133. package/docs/api/interfaces/UserMenuProps.md +1 -1
  134. package/docs/api/interfaces/UserProfile.md +1 -1
  135. package/docs/api/modules.md +105 -19
  136. package/docs/api-reference/components.md +146 -1
  137. package/docs/best-practices/common-patterns.md +26 -8
  138. package/docs/getting-started/examples/README.md +10 -26
  139. package/docs/getting-started/quick-reference.md +23 -0
  140. package/docs/implementation-guides/authentication.md +39 -16
  141. package/docs/implementation-guides/file-reference-system.md +15 -0
  142. package/docs/implementation-guides/file-upload-storage.md +16 -0
  143. package/package.json +1 -1
  144. package/src/components/DataTable/__tests__/DataTableCore.test.tsx +9 -7
  145. package/src/components/DataTable/components/DataTableCore.tsx +8 -1
  146. package/src/components/DataTable/components/EditableRow.tsx +62 -22
  147. package/src/components/DataTable/components/UnifiedTableBody.tsx +25 -101
  148. package/src/components/FileDisplay/FileDisplay.test.tsx +263 -39
  149. package/src/components/FileDisplay/FileDisplay.tsx +605 -83
  150. package/src/components/ProtectedRoute/README.md +164 -0
  151. package/src/components/PublicLayout/EventLogo.tsx +8 -2
  152. package/src/components/PublicLayout/PublicPageHeader.tsx +20 -18
  153. package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +75 -29
  154. package/src/components/Select/Select.test.tsx +83 -6
  155. package/src/components/Select/Select.tsx +236 -16
  156. package/src/examples/CorrectPublicPageImplementation.tsx +16 -13
  157. package/src/examples/PublicEventPage.tsx +9 -6
  158. package/src/examples/PublicPageApp.tsx +9 -6
  159. package/src/examples/PublicPageUsageExample.tsx +9 -7
  160. package/src/hooks/index.ts +4 -0
  161. package/src/hooks/public/index.ts +2 -0
  162. package/src/hooks/public/usePublicFileDisplay.ts +355 -0
  163. package/src/hooks/useFileDisplay.ts +370 -0
  164. package/src/services/AuthService.ts +19 -22
  165. package/dist/chunk-5LAY74WM.js.map +0 -1
  166. package/dist/chunk-AAM57AEU.js.map +0 -1
  167. package/dist/chunk-M52CQP5W.js.map +0 -1
  168. /package/dist/{DataTable-HC5S4RKB.js.map → DataTable-CHX2EFO3.js.map} +0 -0
  169. /package/dist/{UnifiedAuthProvider-ZM7VUC45.js.map → UnifiedAuthProvider-H7RI4KYD.js.map} +0 -0
  170. /package/dist/{chunk-AZ2QJYKU.js.map → chunk-2KLAOD4M.js.map} +0 -0
  171. /package/dist/{chunk-HW5BGOWB.js.map → chunk-2ZYHCFUO.js.map} +0 -0
  172. /package/dist/{chunk-XIBSVWJW.js.map → chunk-7TQDRDSM.js.map} +0 -0
  173. /package/dist/{chunk-GP3HU6WS.js.map → chunk-G7UUVEAP.js.map} +0 -0
  174. /package/dist/{chunk-OXFOS62D.js.map → chunk-MVNOAHOP.js.map} +0 -0
  175. /package/dist/{chunk-AYC2P377.js.map → chunk-ORACUZ7H.js.map} +0 -0
  176. /package/dist/{chunk-6WFM22A4.js.map → chunk-ZGCVJ7WW.js.map} +0 -0
@@ -23,7 +23,7 @@ import {
23
23
  SelectSeparator,
24
24
  SelectTrigger,
25
25
  SelectValue
26
- } from "./chunk-TZXYSZT3.js";
26
+ } from "./chunk-PRM6EYO3.js";
27
27
  import {
28
28
  isPermitted,
29
29
  isSuperAdmin
@@ -32,28 +32,29 @@ import {
32
32
  OrganisationProvider_exports,
33
33
  PublicErrorBoundary,
34
34
  PublicPageContext,
35
- deleteFile,
36
- extractFileMetadata,
35
+ createFileReferenceService,
37
36
  getPublicUrl,
38
37
  getSignedUrl,
39
38
  init_OrganisationProvider,
40
- uploadFile,
39
+ uploadFileWithReference,
41
40
  useAppConfig,
41
+ useFileDisplay,
42
42
  useIsPublicPage,
43
43
  usePublicEventLogo,
44
+ usePublicFileDisplay,
44
45
  usePublicPageContext
45
- } from "./chunk-M52CQP5W.js";
46
+ } from "./chunk-MKMKUCPF.js";
46
47
  import {
47
48
  useToast
48
49
  } from "./chunk-QPCAGLUS.js";
49
50
  import {
50
51
  useEvents,
51
52
  useOrganisations
52
- } from "./chunk-OXFOS62D.js";
53
+ } from "./chunk-MVNOAHOP.js";
53
54
  import {
54
55
  UnifiedAuthProvider_exports,
55
56
  init_UnifiedAuthProvider as init_UnifiedAuthProvider2
56
- } from "./chunk-AYC2P377.js";
57
+ } from "./chunk-ORACUZ7H.js";
57
58
  import {
58
59
  EventServiceContext,
59
60
  EventServiceProvider,
@@ -63,7 +64,7 @@ import {
63
64
  useEventService,
64
65
  useSessionRestoration,
65
66
  useUnifiedAuth
66
- } from "./chunk-AAM57AEU.js";
67
+ } from "./chunk-5RYPBJYL.js";
67
68
  import {
68
69
  LoadingSpinner
69
70
  } from "./chunk-CDQ3PX7L.js";
@@ -76,10 +77,6 @@ import {
76
77
  import {
77
78
  performanceBudgetMonitor
78
79
  } from "./chunk-O3NWNXDY.js";
79
- import {
80
- init_organisationContext,
81
- setOrganisationContext
82
- } from "./chunk-BDZUMRBD.js";
83
80
  import {
84
81
  __esm,
85
82
  __export,
@@ -1447,7 +1444,7 @@ function PaceAppLayout({
1447
1444
  }
1448
1445
  }
1449
1446
  if (hasAccess && currentRoute.roles && currentRoute.roles.length > 0 && user?.id) {
1450
- const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-ZM7VUC45.js");
1447
+ const { useUnifiedAuth: useUnifiedAuth2 } = await import("./UnifiedAuthProvider-H7RI4KYD.js");
1451
1448
  hasAccess = true;
1452
1449
  }
1453
1450
  if (!isMounted) return;
@@ -2201,309 +2198,11 @@ function PasswordResetForm({
2201
2198
 
2202
2199
  // src/hooks/useFileReference.ts
2203
2200
  import { useState as useState9, useCallback as useCallback5, useEffect as useEffect5, useRef as useRef2, useMemo as useMemo7 } from "react";
2204
-
2205
- // src/utils/file-reference.ts
2206
- init_organisationContext();
2207
- var FileReferenceServiceImpl = class {
2208
- constructor(supabase) {
2209
- this.supabase = supabase;
2210
- }
2211
- async createFileReference(options, file) {
2212
- try {
2213
- if (!options.organisation_id) {
2214
- throw new Error("organisation_id is required for file upload");
2215
- }
2216
- if (!options.table_name) {
2217
- throw new Error("table_name is required for file upload");
2218
- }
2219
- if (!options.record_id) {
2220
- throw new Error("record_id is required for file upload");
2221
- }
2222
- const uploadResult = await uploadFile(this.supabase, file, {
2223
- appName: "file-reference",
2224
- orgId: options.organisation_id,
2225
- isPublic: options.is_public || false,
2226
- customPath: options.category
2227
- // Use category as the custom path
2228
- });
2229
- if (!uploadResult.success) {
2230
- throw new Error(`Failed to upload file: ${uploadResult.error}`);
2231
- }
2232
- if (!uploadResult.path) {
2233
- throw new Error("File upload did not return a path");
2234
- }
2235
- const filePath = uploadResult.path;
2236
- const metadata = await extractFileMetadata(file, {
2237
- appName: "file-reference",
2238
- orgId: options.organisation_id,
2239
- isPublic: options.is_public || false
2240
- }, "system");
2241
- await setOrganisationContext(this.supabase, options.organisation_id);
2242
- const { data, error } = await this.supabase.rpc("data_file_reference_create", {
2243
- p_table_name: options.table_name,
2244
- p_record_id: options.record_id,
2245
- p_file_path: filePath,
2246
- p_organisation_id: options.organisation_id,
2247
- p_app_id: options.app_id,
2248
- p_file_metadata: {
2249
- fileName: file.name,
2250
- fileType: file.type,
2251
- fileSize: file.size,
2252
- category: options.category,
2253
- ...metadata,
2254
- ...options.custom_metadata
2255
- },
2256
- p_is_public: options.is_public || false
2257
- });
2258
- if (error) {
2259
- await deleteFile(this.supabase, filePath, options.is_public || false);
2260
- throw new Error(`Failed to create file reference: ${error.message}`);
2261
- }
2262
- const { data: fileRef, error: fetchError } = await this.supabase.from("file_references").select("*").eq("id", data).single();
2263
- if (fetchError || !fileRef) {
2264
- throw new Error(`Failed to fetch created file reference: ${fetchError?.message}`);
2265
- }
2266
- return fileRef;
2267
- } catch (error) {
2268
- console.error("Error creating file reference:", error);
2269
- throw error;
2270
- }
2271
- }
2272
- async getFileReference(table_name, record_id, organisation_id) {
2273
- try {
2274
- const { data, error } = await this.supabase.from("file_references").select("*").eq("table_name", table_name).eq("record_id", record_id).eq("organisation_id", organisation_id).single();
2275
- if (error) {
2276
- if (error.code === "PGRST116") {
2277
- return null;
2278
- }
2279
- throw new Error(`Failed to get file reference: ${error.message}`);
2280
- }
2281
- return data;
2282
- } catch (error) {
2283
- console.error("Error getting file reference:", error);
2284
- throw error;
2285
- }
2286
- }
2287
- async getFileUrl(table_name, record_id, organisation_id) {
2288
- try {
2289
- const fileRef = await this.getFileReference(table_name, record_id, organisation_id);
2290
- if (!fileRef) {
2291
- return null;
2292
- }
2293
- if (fileRef.is_public) {
2294
- const { data: pathData } = await this.supabase.rpc("data_file_reference_url_get", {
2295
- p_table_name: table_name,
2296
- p_record_id: record_id,
2297
- p_organisation_id: organisation_id
2298
- });
2299
- if (!pathData) {
2300
- return null;
2301
- }
2302
- return getPublicUrl(this.supabase, pathData, true);
2303
- } else {
2304
- return await this.getSignedUrl(table_name, record_id, organisation_id);
2305
- }
2306
- } catch (error) {
2307
- console.error("Error getting file URL:", error);
2308
- throw error;
2309
- }
2310
- }
2311
- async getSignedUrl(table_name, record_id, organisation_id, expires_in = 3600) {
2312
- try {
2313
- const { data: filePath, error } = await this.supabase.rpc("data_file_reference_signed_url_get", {
2314
- p_table_name: table_name,
2315
- p_record_id: record_id,
2316
- p_organisation_id: organisation_id,
2317
- p_expires_in: expires_in
2318
- });
2319
- if (error) {
2320
- throw new Error(`Failed to get signed URL: ${error.message}`);
2321
- }
2322
- if (!filePath) {
2323
- return null;
2324
- }
2325
- const signedUrlResult = await getSignedUrl(this.supabase, filePath, {
2326
- appName: "file-reference",
2327
- orgId: organisation_id,
2328
- expiresIn: expires_in
2329
- });
2330
- return signedUrlResult?.url || null;
2331
- } catch (error) {
2332
- console.error("Error getting signed URL:", error);
2333
- throw error;
2334
- }
2335
- }
2336
- async updateFileReference(id, updates) {
2337
- try {
2338
- const { data, error } = await this.supabase.from("file_references").update(updates).eq("id", id).select().single();
2339
- if (error) {
2340
- throw new Error(`Failed to update file reference: ${error.message}`);
2341
- }
2342
- return data;
2343
- } catch (error) {
2344
- console.error("Error updating file reference:", error);
2345
- throw error;
2346
- }
2347
- }
2348
- async deleteFileReference(table_name, record_id, organisation_id, delete_file = false) {
2349
- try {
2350
- const fileRef = await this.getFileReference(table_name, record_id, organisation_id);
2351
- const { error } = await this.supabase.rpc("data_file_reference_delete", {
2352
- p_table_name: table_name,
2353
- p_record_id: record_id,
2354
- p_organisation_id: organisation_id,
2355
- p_delete_file: delete_file
2356
- });
2357
- if (error) {
2358
- throw new Error(`Failed to delete file reference: ${error.message}`);
2359
- }
2360
- if (delete_file && fileRef) {
2361
- await deleteFile(this.supabase, fileRef.file_path, fileRef.is_public || false);
2362
- }
2363
- return true;
2364
- } catch (error) {
2365
- console.error("Error deleting file reference:", error);
2366
- throw error;
2367
- }
2368
- }
2369
- async listFileReferences(table_name, record_id, organisation_id) {
2370
- try {
2371
- const { data, error } = await this.supabase.rpc("data_file_reference_list", {
2372
- p_table_name: table_name,
2373
- p_record_id: record_id,
2374
- p_organisation_id: organisation_id
2375
- });
2376
- if (error) {
2377
- throw new Error(`Failed to list file references: ${error.message}`);
2378
- }
2379
- if (!data || data.length === 0) {
2380
- return [];
2381
- }
2382
- const ids = data.map((item) => item.id);
2383
- const { data: fullData, error: fetchError } = await this.supabase.from("file_references").select("*").in("id", ids);
2384
- if (fetchError) {
2385
- throw new Error(`Failed to fetch file references: ${fetchError.message}`);
2386
- }
2387
- return fullData || [];
2388
- } catch (error) {
2389
- console.error("Error listing file references:", error);
2390
- throw error;
2391
- }
2392
- }
2393
- async getFileCount(table_name, record_id, organisation_id) {
2394
- try {
2395
- const { data, error } = await this.supabase.rpc("data_file_reference_count_get", {
2396
- p_table_name: table_name,
2397
- p_record_id: record_id,
2398
- p_organisation_id: organisation_id
2399
- });
2400
- if (error) {
2401
- throw new Error(`Failed to get file count: ${error.message}`);
2402
- }
2403
- return data || 0;
2404
- } catch (error) {
2405
- console.error("Error getting file count:", error);
2406
- throw error;
2407
- }
2408
- }
2409
- async getFileReferenceById(id, organisation_id) {
2410
- try {
2411
- const { data, error } = await this.supabase.rpc("data_file_reference_get", {
2412
- p_file_reference_id: id,
2413
- p_organisation_id: organisation_id
2414
- });
2415
- if (error) {
2416
- throw new Error(`Failed to get file reference by ID: ${error.message}`);
2417
- }
2418
- if (!data || data.length === 0) {
2419
- return null;
2420
- }
2421
- return data[0];
2422
- } catch (error) {
2423
- console.error("Error getting file reference by ID:", error);
2424
- throw error;
2425
- }
2426
- }
2427
- async getFilesByCategory(table_name, record_id, category, organisation_id) {
2428
- try {
2429
- const { data, error } = await this.supabase.rpc("data_file_reference_by_category_list", {
2430
- p_table_name: table_name,
2431
- p_record_id: record_id,
2432
- p_category: category,
2433
- p_organisation_id: organisation_id
2434
- });
2435
- if (error) {
2436
- throw new Error(`Failed to get files by category: ${error.message}`);
2437
- }
2438
- if (!data || data.length === 0) {
2439
- return [];
2440
- }
2441
- const ids = data.map((item) => item.id);
2442
- const { data: fullData, error: fetchError } = await this.supabase.from("file_references").select("*").in("id", ids);
2443
- if (fetchError) {
2444
- throw new Error(`Failed to fetch file references: ${fetchError.message}`);
2445
- }
2446
- return fullData || [];
2447
- } catch (error) {
2448
- console.error("Error getting files by category:", error);
2449
- throw error;
2450
- }
2451
- }
2452
- async uploadMultipleFiles(options, files) {
2453
- const success = [];
2454
- const failed = [];
2455
- const results = [];
2456
- for (const file of files) {
2457
- try {
2458
- const fileReference = await this.createFileReference(options, file);
2459
- success.push(fileReference);
2460
- results.push({
2461
- file,
2462
- result: {
2463
- file_reference: fileReference,
2464
- file_url: fileReference.is_public ? getPublicUrl(this.supabase, fileReference.file_path, true) : ""
2465
- }
2466
- });
2467
- } catch (error) {
2468
- const message = error instanceof Error ? error.message : "Unknown error";
2469
- failed.push({ file, error: message });
2470
- results.push({ file, result: null, error: message });
2471
- }
2472
- }
2473
- return {
2474
- success,
2475
- failed,
2476
- total: results.length,
2477
- successful: success.length,
2478
- results
2479
- };
2480
- }
2481
- };
2482
- function createFileReferenceService(supabase) {
2483
- return new FileReferenceServiceImpl(supabase);
2484
- }
2485
- async function uploadFileWithReference(supabase, options, file) {
2486
- const service = createFileReferenceService(supabase);
2487
- const fileReference = await service.createFileReference(options, file);
2488
- const fileUrl = options.is_public ? getPublicUrl(supabase, fileReference.file_path, true) : await getSignedUrl(supabase, fileReference.file_path, {
2489
- appName: "file-reference",
2490
- orgId: options.organisation_id,
2491
- expiresIn: 3600
2492
- });
2493
- const urlString = typeof fileUrl === "string" ? fileUrl : fileUrl?.url || "";
2494
- return {
2495
- file_reference: fileReference,
2496
- file_url: urlString,
2497
- signed_url: options.is_public ? void 0 : urlString || void 0
2498
- };
2499
- }
2500
-
2501
- // src/hooks/useFileReference.ts
2502
2201
  function useFileReference(supabase) {
2503
2202
  const [isLoading, setIsLoading] = useState9(false);
2504
2203
  const [error, setError] = useState9(null);
2505
2204
  const service = useMemo7(() => createFileReferenceService(supabase), [supabase]);
2506
- const uploadFile2 = useCallback5(async (options, file) => {
2205
+ const uploadFile = useCallback5(async (options, file) => {
2507
2206
  setIsLoading(true);
2508
2207
  setError(null);
2509
2208
  try {
@@ -2640,7 +2339,7 @@ function useFileReference(supabase) {
2640
2339
  return {
2641
2340
  isLoading,
2642
2341
  error,
2643
- uploadFile: uploadFile2,
2342
+ uploadFile,
2644
2343
  getFileReference,
2645
2344
  getFileReferenceById,
2646
2345
  getFileUrl,
@@ -2690,7 +2389,7 @@ function useFileReferenceForRecord(supabase, table_name, record_id, organisation
2690
2389
  setFileCount(count);
2691
2390
  return count;
2692
2391
  }, [getFileCount, table_name, record_id, organisation_id]);
2693
- const deleteFile2 = useCallback5(async (delete_file) => {
2392
+ const deleteFile = useCallback5(async (delete_file) => {
2694
2393
  const success = await deleteFileReference(table_name, record_id, organisation_id, delete_file);
2695
2394
  if (success) {
2696
2395
  setFileReference(null);
@@ -2728,7 +2427,7 @@ function useFileReferenceForRecord(supabase, table_name, record_id, organisation
2728
2427
  loadFileUrl,
2729
2428
  loadFileReferences,
2730
2429
  loadFileCount,
2731
- deleteFile: deleteFile2,
2430
+ deleteFile,
2732
2431
  updateFileReference,
2733
2432
  clearError
2734
2433
  };
@@ -2905,7 +2604,7 @@ function FileUpload({
2905
2604
  const [isResolvingAppId, setIsResolvingAppId] = useState10(!app_id);
2906
2605
  const [appIdError, setAppIdError] = useState10(null);
2907
2606
  const fileInputRef = useRef3(null);
2908
- const { uploadFile: uploadFile2, isLoading, error } = useFileReference(supabase);
2607
+ const { uploadFile, isLoading, error } = useFileReference(supabase);
2909
2608
  useEffect6(() => {
2910
2609
  if (app_id) {
2911
2610
  setResolvedAppId(app_id);
@@ -3066,7 +2765,7 @@ function FileUpload({
3066
2765
  const errorMsg = appIdError || "App ID not available. Please provide app_id prop or set app name.";
3067
2766
  throw new Error(errorMsg);
3068
2767
  }
3069
- const result = await uploadFile2({
2768
+ const result = await uploadFile({
3070
2769
  table_name,
3071
2770
  record_id,
3072
2771
  organisation_id,
@@ -3165,7 +2864,7 @@ function FileUpload({
3165
2864
  onUploadError?.(errorMessage, file);
3166
2865
  }
3167
2866
  }
3168
- }, [uploadFile2, table_name, record_id, organisation_id, resolvedAppId, category, isPublic, maxSize, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError]);
2867
+ }, [uploadFile, table_name, record_id, organisation_id, resolvedAppId, category, isPublic, maxSize, onUploadSuccess, onUploadError, onProgress, validateFile, generatePreview, showPreview, appIdError]);
3169
2868
  const handleDragOver = useCallback6((e) => {
3170
2869
  e.preventDefault();
3171
2870
  e.stopPropagation();
@@ -3303,77 +3002,53 @@ function FileUpload({
3303
3002
  }
3304
3003
 
3305
3004
  // src/components/FileDisplay/FileDisplay.tsx
3306
- import { useState as useState11, useEffect as useEffect7, useRef as useRef4 } from "react";
3005
+ import { useState as useState11, useEffect as useEffect7, useRef as useRef4, useContext } from "react";
3006
+ init_UnifiedAuthProvider();
3307
3007
  import { jsx as jsx22, jsxs as jsxs18 } from "react/jsx-runtime";
3308
- function FileDisplay({
3008
+ function FileDisplayContent({
3009
+ isLoading,
3010
+ error,
3011
+ fileUrl,
3012
+ fileReference,
3013
+ fileReferences,
3014
+ fileUrls,
3015
+ fileCount,
3016
+ category,
3017
+ displayOnly,
3018
+ showDelete,
3019
+ className,
3020
+ children,
3021
+ onDelete,
3022
+ clearError,
3309
3023
  supabase,
3310
- table_name,
3311
- record_id,
3312
3024
  organisation_id,
3313
- category,
3314
- showUpload = false,
3315
- showDelete = false,
3316
- className = "",
3317
- children
3025
+ loadingUrls = /* @__PURE__ */ new Set()
3318
3026
  }) {
3319
- const {
3320
- isLoading,
3321
- error,
3322
- fileUrl,
3323
- fileReference,
3324
- fileReferences,
3325
- fileCount,
3326
- loadFileReference,
3327
- loadFileUrl,
3328
- loadFileReferences,
3329
- loadFileCount,
3330
- deleteFile: deleteFile2,
3331
- clearError
3332
- } = useFileReferenceForRecord(supabase, table_name, record_id, organisation_id);
3333
3027
  const [imageError, setImageError] = useState11(false);
3334
- const [fileUrls, setFileUrls] = useState11(/* @__PURE__ */ new Map());
3335
- const [loadingUrls, setLoadingUrls] = useState11(/* @__PURE__ */ new Set());
3028
+ const [internalFileUrls, setInternalFileUrls] = useState11(new Map(fileUrls));
3336
3029
  const loadedFilesRef = useRef4(/* @__PURE__ */ new Set());
3337
- const loadingUrlsRef = useRef4(/* @__PURE__ */ new Set());
3030
+ const loadingUrlsRef = useRef4(new Set(loadingUrls));
3338
3031
  const fileReferencesRef = useRef4([]);
3032
+ useEffect7(() => {
3033
+ setInternalFileUrls(new Map(fileUrls));
3034
+ }, [fileUrls]);
3339
3035
  useEffect7(() => {
3340
3036
  const currentIds = fileReferences.map((f) => f.id).join(",");
3341
3037
  const prevIds = fileReferencesRef.current.map((f) => f.id).join(",");
3342
3038
  if (currentIds !== prevIds) {
3343
3039
  fileReferencesRef.current = fileReferences;
3344
3040
  loadedFilesRef.current.clear();
3345
- setFileUrls(/* @__PURE__ */ new Map());
3346
- setLoadingUrls(/* @__PURE__ */ new Set());
3041
+ setInternalFileUrls(/* @__PURE__ */ new Map());
3347
3042
  }
3348
3043
  }, [fileReferences]);
3349
3044
  useEffect7(() => {
3350
- loadFileCount();
3351
- if (category) {
3352
- loadFileReference();
3353
- } else {
3354
- loadFileReferences();
3355
- }
3356
- }, [loadFileCount, loadFileReference, loadFileReferences, category]);
3357
- useEffect7(() => {
3358
- if (fileReference) {
3359
- loadFileUrl();
3360
- }
3361
- }, [fileReference, loadFileUrl]);
3362
- useEffect7(() => {
3363
- if (category || fileReferences.length === 0) return;
3045
+ if (!supabase || category || fileReferences.length === 0) return;
3364
3046
  const loadFileUrls = async () => {
3365
3047
  const urlsToLoad = fileReferences.filter((fileRef) => {
3366
3048
  return !loadedFilesRef.current.has(fileRef.id) && !loadingUrlsRef.current.has(fileRef.id);
3367
3049
  });
3368
3050
  if (urlsToLoad.length === 0) return;
3369
- setLoadingUrls((prev) => {
3370
- const updated = new Set(prev);
3371
- urlsToLoad.forEach((fileRef) => {
3372
- updated.add(fileRef.id);
3373
- loadingUrlsRef.current.add(fileRef.id);
3374
- });
3375
- return updated;
3376
- });
3051
+ loadingUrlsRef.current = /* @__PURE__ */ new Set([...loadingUrlsRef.current, ...urlsToLoad.map((f) => f.id)]);
3377
3052
  for (const fileRef of urlsToLoad) {
3378
3053
  try {
3379
3054
  let url = null;
@@ -3388,7 +3063,7 @@ function FileDisplay({
3388
3063
  url = signedUrlResult?.url || null;
3389
3064
  }
3390
3065
  if (url) {
3391
- setFileUrls((prev) => {
3066
+ setInternalFileUrls((prev) => {
3392
3067
  const updated = new Map(prev);
3393
3068
  updated.set(fileRef.id, url);
3394
3069
  return updated;
@@ -3398,12 +3073,7 @@ function FileDisplay({
3398
3073
  } catch (error2) {
3399
3074
  console.error(`Failed to load URL for file ${fileRef.id}:`, error2);
3400
3075
  } finally {
3401
- setLoadingUrls((prev) => {
3402
- const updated = new Set(prev);
3403
- updated.delete(fileRef.id);
3404
- loadingUrlsRef.current.delete(fileRef.id);
3405
- return updated;
3406
- });
3076
+ loadingUrlsRef.current.delete(fileRef.id);
3407
3077
  }
3408
3078
  }
3409
3079
  };
@@ -3411,10 +3081,10 @@ function FileDisplay({
3411
3081
  }, [category, fileReferences.map((f) => f.id).join(","), supabase, organisation_id]);
3412
3082
  const handleDelete = async () => {
3413
3083
  if (window.confirm("Are you sure you want to delete this file?")) {
3414
- const success = await deleteFile2(true);
3415
- if (success) {
3416
- setImageError(false);
3084
+ if (onDelete) {
3085
+ await onDelete();
3417
3086
  }
3087
+ setImageError(false);
3418
3088
  }
3419
3089
  };
3420
3090
  const handleImageError = () => {
@@ -3444,9 +3114,9 @@ function FileDisplay({
3444
3114
  return /* @__PURE__ */ jsxs18("div", { className: `p-4 bg-acc-50 border border-acc-200 rounded-lg ${className}`, children: [
3445
3115
  /* @__PURE__ */ jsxs18("div", { className: "text-acc-600", children: [
3446
3116
  "Error loading file: ",
3447
- error
3117
+ error instanceof Error ? error.message : String(error)
3448
3118
  ] }),
3449
- /* @__PURE__ */ jsx22(
3119
+ clearError && /* @__PURE__ */ jsx22(
3450
3120
  "button",
3451
3121
  {
3452
3122
  onClick: clearError,
@@ -3462,8 +3132,19 @@ function FileDisplay({
3462
3132
  children
3463
3133
  ] });
3464
3134
  }
3465
- if (category && fileReference) {
3135
+ if ((category || displayOnly) && fileReference) {
3466
3136
  const isImage = fileReference.file_metadata.fileType?.startsWith("image/");
3137
+ if (displayOnly && isImage && fileUrl && !imageError && !showDelete) {
3138
+ return /* @__PURE__ */ jsx22(
3139
+ "img",
3140
+ {
3141
+ src: fileUrl,
3142
+ alt: fileReference.file_metadata.fileName || "File",
3143
+ className: className || "max-w-full h-auto",
3144
+ onError: handleImageError
3145
+ }
3146
+ );
3147
+ }
3467
3148
  return /* @__PURE__ */ jsxs18("div", { className: `space-y-2 ${className}`, children: [
3468
3149
  isImage && fileUrl && !imageError ? /* @__PURE__ */ jsxs18("div", { className: "relative", children: [
3469
3150
  /* @__PURE__ */ jsx22(
@@ -3471,7 +3152,7 @@ function FileDisplay({
3471
3152
  {
3472
3153
  src: fileUrl,
3473
3154
  alt: fileReference.file_metadata.fileName || "File",
3474
- className: "max-w-full h-auto rounded-lg border border-sec-200",
3155
+ className: "max-w-full h-auto",
3475
3156
  onError: handleImageError
3476
3157
  }
3477
3158
  ),
@@ -3511,8 +3192,8 @@ function FileDisplay({
3511
3192
  return /* @__PURE__ */ jsxs18("div", { className: `space-y-2 ${className}`, children: [
3512
3193
  fileReferences.map((fileRef) => {
3513
3194
  const isImage = fileRef.file_metadata.fileType?.startsWith("image/");
3514
- const fileUrl2 = fileUrls.get(fileRef.id) || null;
3515
- const isLoadingUrl = loadingUrls.has(fileRef.id);
3195
+ const fileUrl2 = internalFileUrls.get(fileRef.id) || null;
3196
+ const isLoadingUrl = loadingUrlsRef.current.has(fileRef.id);
3516
3197
  const canDownload = !isImage && fileUrl2;
3517
3198
  return /* @__PURE__ */ jsxs18("div", { className: "flex items-center space-x-3 p-3 bg-sec-50 rounded-lg border border-sec-200", children: [
3518
3199
  isLoadingUrl ? /* @__PURE__ */ jsx22("div", { className: "w-12 h-12 flex items-center justify-center", children: /* @__PURE__ */ jsx22("div", { className: "animate-spin rounded-full h-6 w-6 border-b-2 border-main-500" }) }) : isImage && fileUrl2 ? /* @__PURE__ */ jsx22(
@@ -3543,10 +3224,12 @@ function FileDisplay({
3543
3224
  children: "\u2193"
3544
3225
  }
3545
3226
  ),
3546
- showDelete && /* @__PURE__ */ jsx22(
3227
+ showDelete && onDelete && /* @__PURE__ */ jsx22(
3547
3228
  "button",
3548
3229
  {
3549
- onClick: () => deleteFile2(true),
3230
+ onClick: () => {
3231
+ onDelete();
3232
+ },
3550
3233
  className: "text-acc-500 hover:text-acc-700 p-1",
3551
3234
  title: "Delete file",
3552
3235
  children: "\xD7"
@@ -3558,62 +3241,466 @@ function FileDisplay({
3558
3241
  children
3559
3242
  ] });
3560
3243
  }
3561
-
3562
- // src/hooks/useEventLogo.ts
3563
- import { useState as useState12, useEffect as useEffect8, useCallback as useCallback8, useMemo as useMemo9 } from "react";
3564
- function defaultGenerateFallbackText(eventName) {
3565
- if (!eventName) return "EV";
3566
- return eventName.split(" ").map((word) => word.charAt(0).toUpperCase()).join("").substring(0, 3);
3567
- }
3568
- var authenticatedLogoCache = /* @__PURE__ */ new Map();
3569
- var MAX_CACHE_SIZE = 100;
3570
- function cleanupCache() {
3571
- const now = Date.now();
3572
- const entries = Array.from(authenticatedLogoCache.entries());
3573
- entries.forEach(([key, value]) => {
3574
- if (now - value.timestamp > value.ttl) {
3575
- authenticatedLogoCache.delete(key);
3576
- }
3577
- });
3578
- if (authenticatedLogoCache.size > MAX_CACHE_SIZE) {
3579
- const sortedEntries = Array.from(authenticatedLogoCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
3580
- const toRemove = sortedEntries.slice(0, authenticatedLogoCache.size - MAX_CACHE_SIZE);
3581
- toRemove.forEach(([key]) => authenticatedLogoCache.delete(key));
3582
- }
3583
- }
3584
- function useEventLogo(supabase, eventId, eventName, organisationId, options = {}) {
3244
+ function FileDisplayBackwardsCompat({
3245
+ supabase,
3246
+ table_name,
3247
+ record_id,
3248
+ organisation_id,
3249
+ category,
3250
+ displayOnly = false,
3251
+ showUpload = false,
3252
+ showDelete = false,
3253
+ className = "",
3254
+ children
3255
+ }) {
3585
3256
  const {
3586
- cacheTtl = 30 * 60 * 1e3,
3587
- // 30 minutes
3588
- enableCache = true,
3589
- validateImage = true,
3590
- generateFallbackText = defaultGenerateFallbackText
3591
- } = options;
3592
- const [logoUrl, setLogoUrl] = useState12(null);
3593
- const [isLoading, setIsLoading] = useState12(false);
3594
- const [error, setError] = useState12(null);
3595
- const fallbackText = useMemo9(() => {
3596
- return eventName ? generateFallbackText(eventName) : "EV";
3597
- }, [eventName, generateFallbackText]);
3598
- const fetchLogo = useCallback8(async () => {
3599
- if (!eventId || !organisationId || !supabase) {
3600
- setLogoUrl(null);
3601
- setIsLoading(false);
3602
- return;
3257
+ isLoading: isLoadingForRecord,
3258
+ error: errorForRecord,
3259
+ fileUrl,
3260
+ fileReference,
3261
+ fileReferences,
3262
+ fileCount,
3263
+ loadFileReference,
3264
+ loadFileUrl,
3265
+ loadFileReferences,
3266
+ loadFileCount,
3267
+ deleteFile,
3268
+ clearError
3269
+ } = useFileReferenceForRecord(supabase, table_name, record_id, organisation_id);
3270
+ const {
3271
+ getFilesByCategory,
3272
+ isLoading: isLoadingCategory,
3273
+ error: errorCategory
3274
+ } = useFileReference(supabase);
3275
+ const [categoryFileReference, setCategoryFileReference] = useState11(null);
3276
+ const [categoryFileUrl, setCategoryFileUrl] = useState11(null);
3277
+ const [categoryFileReferences, setCategoryFileReferences] = useState11([]);
3278
+ const [displayOnlyFileReference, setDisplayOnlyFileReference] = useState11(null);
3279
+ const [displayOnlyFileUrl, setDisplayOnlyFileUrl] = useState11(null);
3280
+ useEffect7(() => {
3281
+ if (category) {
3282
+ const loadCategoryFiles = async () => {
3283
+ try {
3284
+ const files = await getFilesByCategory(table_name, record_id, category, organisation_id);
3285
+ setCategoryFileReferences(files);
3286
+ if (files.length > 0) {
3287
+ const firstFile = files[0];
3288
+ setCategoryFileReference(firstFile);
3289
+ let url = null;
3290
+ if (firstFile.is_public) {
3291
+ url = getPublicUrl(supabase, firstFile.file_path, true);
3292
+ } else {
3293
+ const signedUrlResult = await getSignedUrl(supabase, firstFile.file_path, {
3294
+ appName: "file-reference",
3295
+ orgId: organisation_id,
3296
+ expiresIn: 3600
3297
+ });
3298
+ url = signedUrlResult?.url || null;
3299
+ }
3300
+ setCategoryFileUrl(url);
3301
+ } else {
3302
+ setCategoryFileReference(null);
3303
+ setCategoryFileUrl(null);
3304
+ }
3305
+ } catch (err) {
3306
+ console.error("[FileDisplayBackwardsCompat] Error loading files by category:", err);
3307
+ }
3308
+ };
3309
+ loadCategoryFiles();
3310
+ } else {
3311
+ setCategoryFileReference(null);
3312
+ setCategoryFileUrl(null);
3313
+ setCategoryFileReferences([]);
3603
3314
  }
3604
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3605
- if (!uuidRegex.test(organisationId)) {
3606
- console.warn("[useEventLogo] Invalid organisationId format (not a valid UUID):", organisationId);
3315
+ }, [category, table_name, record_id, organisation_id, supabase, getFilesByCategory]);
3316
+ useEffect7(() => {
3317
+ if (!category) {
3318
+ loadFileCount();
3319
+ loadFileReferences();
3607
3320
  }
3608
- const cacheKey = `event_logo_${eventId}_${organisationId}`;
3609
- if (enableCache) {
3610
- const cached = authenticatedLogoCache.get(cacheKey);
3611
- if (cached && Date.now() - cached.timestamp < cached.ttl) {
3612
- setLogoUrl(cached.data);
3613
- setIsLoading(false);
3614
- setError(null);
3615
- return;
3616
- }
3321
+ }, [loadFileCount, loadFileReferences, category]);
3322
+ useEffect7(() => {
3323
+ if (!category && fileReference) {
3324
+ loadFileUrl();
3325
+ }
3326
+ }, [category, fileReference, loadFileUrl]);
3327
+ useEffect7(() => {
3328
+ if (displayOnly && !category && fileReferences.length > 0) {
3329
+ const loadDisplayOnlyFile = async () => {
3330
+ try {
3331
+ const imageFiles = fileReferences.filter(
3332
+ (f) => f.file_metadata.fileType?.startsWith("image/")
3333
+ );
3334
+ const targetFile = imageFiles.length > 0 ? imageFiles[0] : fileReferences[0];
3335
+ setDisplayOnlyFileReference(targetFile);
3336
+ let url = null;
3337
+ if (targetFile.is_public) {
3338
+ url = getPublicUrl(supabase, targetFile.file_path, true);
3339
+ } else {
3340
+ const signedUrlResult = await getSignedUrl(supabase, targetFile.file_path, {
3341
+ appName: "file-reference",
3342
+ orgId: organisation_id,
3343
+ expiresIn: 3600
3344
+ });
3345
+ url = signedUrlResult?.url || null;
3346
+ }
3347
+ setDisplayOnlyFileUrl(url);
3348
+ } catch (err) {
3349
+ console.error("[FileDisplayBackwardsCompat] Error loading displayOnly file:", err);
3350
+ }
3351
+ };
3352
+ loadDisplayOnlyFile();
3353
+ } else if (!displayOnly || category) {
3354
+ setDisplayOnlyFileReference(null);
3355
+ setDisplayOnlyFileUrl(null);
3356
+ }
3357
+ }, [displayOnly, category, fileReferences, supabase, organisation_id]);
3358
+ const handleDelete = async () => {
3359
+ if (window.confirm("Are you sure you want to delete this file?")) {
3360
+ await deleteFile(true);
3361
+ }
3362
+ };
3363
+ let finalFileReference = null;
3364
+ let finalFileUrl = null;
3365
+ let finalFileReferences = [];
3366
+ let finalFileCount = 0;
3367
+ let finalIsLoading = false;
3368
+ let finalError = null;
3369
+ if (category) {
3370
+ finalFileReference = categoryFileReference;
3371
+ finalFileUrl = categoryFileUrl;
3372
+ finalFileReferences = categoryFileReferences;
3373
+ finalFileCount = categoryFileReferences.length;
3374
+ finalIsLoading = isLoadingCategory;
3375
+ finalError = errorCategory;
3376
+ } else if (displayOnly) {
3377
+ finalFileReference = displayOnlyFileReference;
3378
+ finalFileUrl = displayOnlyFileUrl;
3379
+ finalFileReferences = displayOnlyFileReference ? [displayOnlyFileReference] : [];
3380
+ finalFileCount = displayOnlyFileReference ? 1 : 0;
3381
+ finalIsLoading = isLoadingForRecord;
3382
+ finalError = errorForRecord;
3383
+ } else {
3384
+ finalFileReference = fileReference;
3385
+ finalFileUrl = fileUrl;
3386
+ finalFileReferences = fileReferences;
3387
+ finalFileCount = fileCount;
3388
+ finalIsLoading = isLoadingForRecord;
3389
+ finalError = errorForRecord;
3390
+ }
3391
+ return /* @__PURE__ */ jsx22(
3392
+ FileDisplayContent,
3393
+ {
3394
+ isLoading: finalIsLoading,
3395
+ error: finalError,
3396
+ fileUrl: finalFileUrl,
3397
+ fileReference: finalFileReference,
3398
+ fileReferences: finalFileReferences,
3399
+ fileUrls: /* @__PURE__ */ new Map(),
3400
+ fileCount: finalFileCount,
3401
+ category,
3402
+ displayOnly,
3403
+ showDelete,
3404
+ className,
3405
+ children,
3406
+ onDelete: handleDelete,
3407
+ clearError,
3408
+ supabase,
3409
+ organisation_id,
3410
+ loadingUrls: /* @__PURE__ */ new Set()
3411
+ }
3412
+ );
3413
+ }
3414
+ function FileDisplayPublic({
3415
+ table_name,
3416
+ record_id,
3417
+ organisation_id,
3418
+ category,
3419
+ displayOnly = false,
3420
+ showUpload = false,
3421
+ showDelete = false,
3422
+ className = "",
3423
+ children
3424
+ }) {
3425
+ const publicPageContext = useContext(PublicPageContext);
3426
+ const supabase = publicPageContext?.supabase ?? null;
3427
+ if (!supabase) {
3428
+ return /* @__PURE__ */ jsx22("div", { className: `text-sec-500 text-center p-4 ${className}`, children: "Supabase client not available in public context" });
3429
+ }
3430
+ const {
3431
+ fileUrl,
3432
+ fileReference,
3433
+ fileReferences,
3434
+ fileUrls,
3435
+ fileCount,
3436
+ isLoading,
3437
+ error,
3438
+ refetch
3439
+ } = usePublicFileDisplay(
3440
+ table_name,
3441
+ record_id,
3442
+ organisation_id,
3443
+ category,
3444
+ { supabase }
3445
+ );
3446
+ const handleDelete = async () => {
3447
+ console.warn("[FileDisplay] Delete operation not supported in public context");
3448
+ };
3449
+ let finalFileReference = fileReference;
3450
+ let finalFileUrl = fileUrl;
3451
+ let finalFileReferences = fileReferences;
3452
+ let finalFileCount = fileCount;
3453
+ if (displayOnly && !category && fileReferences.length > 0) {
3454
+ const imageFiles = fileReferences.filter(
3455
+ (f) => f.file_metadata.fileType?.startsWith("image/")
3456
+ );
3457
+ const targetFile = imageFiles.length > 0 ? imageFiles[0] : fileReferences[0];
3458
+ finalFileReference = targetFile;
3459
+ finalFileReferences = [targetFile];
3460
+ finalFileCount = 1;
3461
+ finalFileUrl = fileUrls.get(targetFile.id) || null;
3462
+ }
3463
+ return /* @__PURE__ */ jsx22(
3464
+ FileDisplayContent,
3465
+ {
3466
+ isLoading,
3467
+ error,
3468
+ fileUrl: finalFileUrl,
3469
+ fileReference: finalFileReference,
3470
+ fileReferences: finalFileReferences,
3471
+ fileUrls,
3472
+ fileCount: finalFileCount,
3473
+ category,
3474
+ displayOnly,
3475
+ showDelete: false,
3476
+ className,
3477
+ children,
3478
+ onDelete: showDelete ? handleDelete : void 0,
3479
+ supabase,
3480
+ organisation_id
3481
+ }
3482
+ );
3483
+ }
3484
+ function FileDisplayAuthenticated({
3485
+ table_name,
3486
+ record_id,
3487
+ organisation_id,
3488
+ category,
3489
+ displayOnly = false,
3490
+ showUpload = false,
3491
+ showDelete = false,
3492
+ className = "",
3493
+ children
3494
+ }) {
3495
+ const { supabase } = useUnifiedAuth();
3496
+ if (!supabase) {
3497
+ return /* @__PURE__ */ jsx22("div", { className: `text-sec-500 text-center p-4 ${className}`, children: "Supabase client not available in authenticated context" });
3498
+ }
3499
+ const {
3500
+ fileUrl,
3501
+ fileReference,
3502
+ fileReferences,
3503
+ fileUrls,
3504
+ fileCount,
3505
+ isLoading,
3506
+ error,
3507
+ refetch
3508
+ } = useFileDisplay(
3509
+ table_name,
3510
+ record_id,
3511
+ organisation_id,
3512
+ category,
3513
+ { supabase }
3514
+ );
3515
+ const [displayOnlyFileReference, setDisplayOnlyFileReference] = useState11(null);
3516
+ const [displayOnlyFileUrl, setDisplayOnlyFileUrl] = useState11(null);
3517
+ useEffect7(() => {
3518
+ if (displayOnly && !category && fileReferences.length > 0) {
3519
+ const loadDisplayOnlyFile = async () => {
3520
+ try {
3521
+ const imageFiles = fileReferences.filter(
3522
+ (f) => f.file_metadata.fileType?.startsWith("image/")
3523
+ );
3524
+ const targetFile = imageFiles.length > 0 ? imageFiles[0] : fileReferences[0];
3525
+ setDisplayOnlyFileReference(targetFile);
3526
+ const existingUrl = fileUrls.get(targetFile.id);
3527
+ if (existingUrl) {
3528
+ setDisplayOnlyFileUrl(existingUrl);
3529
+ return;
3530
+ }
3531
+ let url = null;
3532
+ if (targetFile.is_public) {
3533
+ url = getPublicUrl(supabase, targetFile.file_path, true);
3534
+ } else {
3535
+ const signedUrlResult = await getSignedUrl(supabase, targetFile.file_path, {
3536
+ appName: "file-reference",
3537
+ orgId: organisation_id,
3538
+ expiresIn: 3600
3539
+ });
3540
+ url = signedUrlResult?.url || null;
3541
+ }
3542
+ setDisplayOnlyFileUrl(url);
3543
+ } catch (err) {
3544
+ console.error("[FileDisplayAuthenticated] Error loading displayOnly file:", err);
3545
+ }
3546
+ };
3547
+ loadDisplayOnlyFile();
3548
+ } else if (!displayOnly || category) {
3549
+ setDisplayOnlyFileReference(null);
3550
+ setDisplayOnlyFileUrl(null);
3551
+ }
3552
+ }, [displayOnly, category, fileReferences, fileUrls, supabase, organisation_id]);
3553
+ const handleDelete = async () => {
3554
+ console.warn("[FileDisplay] Delete operation needs to be implemented via FileReferenceService");
3555
+ };
3556
+ let finalFileReference = fileReference;
3557
+ let finalFileUrl = fileUrl;
3558
+ let finalFileReferences = fileReferences;
3559
+ let finalFileCount = fileCount;
3560
+ if (displayOnly && !category) {
3561
+ finalFileReference = displayOnlyFileReference;
3562
+ finalFileUrl = displayOnlyFileUrl;
3563
+ finalFileReferences = displayOnlyFileReference ? [displayOnlyFileReference] : [];
3564
+ finalFileCount = displayOnlyFileReference ? 1 : 0;
3565
+ }
3566
+ return /* @__PURE__ */ jsx22(
3567
+ FileDisplayContent,
3568
+ {
3569
+ isLoading,
3570
+ error,
3571
+ fileUrl: finalFileUrl,
3572
+ fileReference: finalFileReference,
3573
+ fileReferences: finalFileReferences,
3574
+ fileUrls,
3575
+ fileCount: finalFileCount,
3576
+ category,
3577
+ displayOnly,
3578
+ showDelete,
3579
+ className,
3580
+ children,
3581
+ onDelete: showDelete ? handleDelete : void 0,
3582
+ supabase,
3583
+ organisation_id
3584
+ }
3585
+ );
3586
+ }
3587
+ function FileDisplay({
3588
+ supabase,
3589
+ table_name,
3590
+ record_id,
3591
+ organisation_id,
3592
+ category,
3593
+ displayOnly = false,
3594
+ showUpload = false,
3595
+ showDelete = false,
3596
+ className = "",
3597
+ children
3598
+ }) {
3599
+ if (supabase) {
3600
+ return /* @__PURE__ */ jsx22(
3601
+ FileDisplayBackwardsCompat,
3602
+ {
3603
+ supabase,
3604
+ table_name,
3605
+ record_id,
3606
+ organisation_id,
3607
+ category,
3608
+ displayOnly,
3609
+ showUpload,
3610
+ showDelete,
3611
+ className,
3612
+ children
3613
+ }
3614
+ );
3615
+ }
3616
+ const isPublicPage = useIsPublicPage();
3617
+ if (isPublicPage) {
3618
+ return /* @__PURE__ */ jsx22(
3619
+ FileDisplayPublic,
3620
+ {
3621
+ table_name,
3622
+ record_id,
3623
+ organisation_id,
3624
+ category,
3625
+ displayOnly,
3626
+ showUpload,
3627
+ showDelete,
3628
+ className,
3629
+ children
3630
+ }
3631
+ );
3632
+ }
3633
+ return /* @__PURE__ */ jsx22(
3634
+ FileDisplayAuthenticated,
3635
+ {
3636
+ table_name,
3637
+ record_id,
3638
+ organisation_id,
3639
+ category,
3640
+ displayOnly,
3641
+ showUpload,
3642
+ showDelete,
3643
+ className,
3644
+ children
3645
+ }
3646
+ );
3647
+ }
3648
+
3649
+ // src/hooks/useEventLogo.ts
3650
+ import { useState as useState12, useEffect as useEffect8, useCallback as useCallback8, useMemo as useMemo9 } from "react";
3651
+ function defaultGenerateFallbackText(eventName) {
3652
+ if (!eventName) return "EV";
3653
+ return eventName.split(" ").map((word) => word.charAt(0).toUpperCase()).join("").substring(0, 3);
3654
+ }
3655
+ var authenticatedLogoCache = /* @__PURE__ */ new Map();
3656
+ var MAX_CACHE_SIZE = 100;
3657
+ function cleanupCache() {
3658
+ const now = Date.now();
3659
+ const entries = Array.from(authenticatedLogoCache.entries());
3660
+ entries.forEach(([key, value]) => {
3661
+ if (now - value.timestamp > value.ttl) {
3662
+ authenticatedLogoCache.delete(key);
3663
+ }
3664
+ });
3665
+ if (authenticatedLogoCache.size > MAX_CACHE_SIZE) {
3666
+ const sortedEntries = Array.from(authenticatedLogoCache.entries()).sort((a, b) => a[1].timestamp - b[1].timestamp);
3667
+ const toRemove = sortedEntries.slice(0, authenticatedLogoCache.size - MAX_CACHE_SIZE);
3668
+ toRemove.forEach(([key]) => authenticatedLogoCache.delete(key));
3669
+ }
3670
+ }
3671
+ function useEventLogo(supabase, eventId, eventName, organisationId, options = {}) {
3672
+ const {
3673
+ cacheTtl = 30 * 60 * 1e3,
3674
+ // 30 minutes
3675
+ enableCache = true,
3676
+ validateImage = true,
3677
+ generateFallbackText = defaultGenerateFallbackText
3678
+ } = options;
3679
+ const [logoUrl, setLogoUrl] = useState12(null);
3680
+ const [isLoading, setIsLoading] = useState12(false);
3681
+ const [error, setError] = useState12(null);
3682
+ const fallbackText = useMemo9(() => {
3683
+ return eventName ? generateFallbackText(eventName) : "EV";
3684
+ }, [eventName, generateFallbackText]);
3685
+ const fetchLogo = useCallback8(async () => {
3686
+ if (!eventId || !organisationId || !supabase) {
3687
+ setLogoUrl(null);
3688
+ setIsLoading(false);
3689
+ return;
3690
+ }
3691
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3692
+ if (!uuidRegex.test(organisationId)) {
3693
+ console.warn("[useEventLogo] Invalid organisationId format (not a valid UUID):", organisationId);
3694
+ }
3695
+ const cacheKey = `event_logo_${eventId}_${organisationId}`;
3696
+ if (enableCache) {
3697
+ const cached = authenticatedLogoCache.get(cacheKey);
3698
+ if (cached && Date.now() - cached.timestamp < cached.ttl) {
3699
+ setLogoUrl(cached.data);
3700
+ setIsLoading(false);
3701
+ setError(null);
3702
+ return;
3703
+ }
3617
3704
  }
3618
3705
  try {
3619
3706
  setIsLoading(true);
@@ -3774,278 +3861,31 @@ var TableHead = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE_
3774
3861
  "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
3775
3862
  className
3776
3863
  ),
3777
- ...props
3778
- }
3779
- ));
3780
- TableHead.displayName = "TableHead";
3781
- var TableCell = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
3782
- "td",
3783
- {
3784
- ref,
3785
- className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className),
3786
- ...props
3787
- }
3788
- ));
3789
- TableCell.displayName = "TableCell";
3790
- var TableCaption = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
3791
- "caption",
3792
- {
3793
- ref,
3794
- className: cn("mt-4 text-sm text-muted-foreground", className),
3795
- ...props
3796
- }
3797
- ));
3798
- TableCaption.displayName = "TableCaption";
3799
-
3800
- // src/components/PublicLayout/EventLogo.tsx
3801
- import { useMemo as useMemo10, useContext } from "react";
3802
- init_UnifiedAuthProvider();
3803
- import { jsx as jsx24 } from "react/jsx-runtime";
3804
- var sizeClasses = {
3805
- xs: "h-4 w-4 text-xs",
3806
- sm: "h-6 w-6 text-sm",
3807
- md: "h-8 w-8 text-base",
3808
- lg: "h-12 w-12 text-lg",
3809
- xl: "h-16 w-16 text-xl",
3810
- "2xl": "h-20 w-20 text-2xl"
3811
- };
3812
- function defaultGenerateFallbackText2(eventName) {
3813
- if (!eventName) return "EV";
3814
- return eventName.split(" ").map((word) => word.charAt(0).toUpperCase()).join("").substring(0, 3);
3815
- }
3816
- function EventLogoPublic({
3817
- eventId,
3818
- eventName,
3819
- organisationId,
3820
- size,
3821
- className,
3822
- showFallback,
3823
- generateFallbackText,
3824
- validateImage,
3825
- LoadingComponent,
3826
- ErrorComponent
3827
- }) {
3828
- const publicPageContext = useContext(PublicPageContext);
3829
- const supabase = publicPageContext?.supabase ?? null;
3830
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3831
- const hasValidOrganisationId = organisationId && uuidRegex.test(organisationId);
3832
- if (!supabase) {
3833
- const effectiveSize = size || "md";
3834
- return /* @__PURE__ */ jsx24("div", { className: `${sizeClasses[effectiveSize]} ${className}`.trim(), title: `${eventName} logo (Supabase not configured)`, children: eventName ? defaultGenerateFallbackText2(eventName) : "EV" });
3835
- }
3836
- const {
3837
- logoUrl,
3838
- fallbackText,
3839
- isLoading,
3840
- error
3841
- } = usePublicEventLogo(
3842
- eventId,
3843
- eventName,
3844
- organisationId,
3845
- // Always pass organisationId, let the hook handle validation
3846
- {
3847
- validateImage,
3848
- generateFallbackText,
3849
- supabase
3850
- }
3851
- );
3852
- const sizeClass = useMemo10(() => sizeClasses[size || "md"], [size]);
3853
- const combinedClasses = useMemo10(() => {
3854
- const baseClasses = "flex items-center justify-center bg-gray-100 text-gray-600 font-semibold rounded";
3855
- return `${baseClasses} ${sizeClass} ${className}`.trim();
3856
- }, [sizeClass, className]);
3857
- if (!hasValidOrganisationId && !isLoading && !logoUrl && showFallback) {
3858
- return /* @__PURE__ */ jsx24("div", { className: combinedClasses, title: `${eventName} logo (invalid organisation ID)`, children: fallbackText });
3859
- }
3860
- if (isLoading) {
3861
- if (LoadingComponent) {
3862
- return /* @__PURE__ */ jsx24(LoadingComponent, {});
3863
- }
3864
- return /* @__PURE__ */ jsx24("div", { className: `${combinedClasses} animate-pulse`, children: /* @__PURE__ */ jsx24("div", { className: "w-3/4 h-3/4 bg-gray-300 rounded" }) });
3865
- }
3866
- if (error) {
3867
- if (ErrorComponent) {
3868
- return /* @__PURE__ */ jsx24(ErrorComponent, { error });
3869
- }
3870
- if (showFallback) {
3871
- return /* @__PURE__ */ jsx24("div", { className: combinedClasses, title: `${eventName} (logo unavailable)`, children: fallbackText });
3872
- }
3873
- return null;
3874
- }
3875
- if (!logoUrl) {
3876
- if (showFallback) {
3877
- return /* @__PURE__ */ jsx24("div", { className: combinedClasses, title: `${eventName} logo`, children: fallbackText });
3878
- }
3879
- return null;
3880
- }
3881
- return /* @__PURE__ */ jsx24(
3882
- "img",
3883
- {
3884
- src: logoUrl,
3885
- alt: `${eventName} logo`,
3886
- className: `${sizeClass} ${className}`.trim(),
3887
- onError: (e) => {
3888
- const target = e.target;
3889
- target.style.display = "none";
3890
- const fallback = document.createElement("div");
3891
- fallback.className = combinedClasses;
3892
- fallback.textContent = fallbackText;
3893
- fallback.title = `${eventName} logo`;
3894
- target.parentNode?.insertBefore(fallback, target.nextSibling);
3895
- }
3896
- }
3897
- );
3898
- }
3899
- function EventLogoAuthenticated({
3900
- eventId,
3901
- eventName,
3902
- organisationId,
3903
- size,
3904
- className,
3905
- showFallback,
3906
- generateFallbackText,
3907
- validateImage,
3908
- LoadingComponent,
3909
- ErrorComponent
3910
- }) {
3911
- const { supabase } = useUnifiedAuth();
3912
- const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
3913
- const hasValidOrganisationId = organisationId && uuidRegex.test(organisationId);
3914
- if (!supabase) {
3915
- const effectiveSize = size || "md";
3916
- return /* @__PURE__ */ jsx24("div", { className: `${sizeClasses[effectiveSize]} ${className}`.trim(), title: `${eventName} logo (Supabase not configured)`, children: eventName ? defaultGenerateFallbackText2(eventName) : "EV" });
3917
- }
3918
- const {
3919
- logoUrl,
3920
- fallbackText,
3921
- isLoading,
3922
- error
3923
- } = useEventLogo(
3924
- supabase,
3925
- eventId,
3926
- eventName,
3927
- organisationId,
3928
- {
3929
- validateImage,
3930
- generateFallbackText
3931
- }
3932
- );
3933
- const sizeClass = useMemo10(() => sizeClasses[size || "md"], [size]);
3934
- const combinedClasses = useMemo10(() => {
3935
- const baseClasses = "flex items-center justify-center bg-gray-100 text-gray-600 font-semibold rounded";
3936
- return `${baseClasses} ${sizeClass} ${className}`.trim();
3937
- }, [sizeClass, className]);
3938
- if (!hasValidOrganisationId && !isLoading && !logoUrl && showFallback) {
3939
- return /* @__PURE__ */ jsx24("div", { className: combinedClasses, title: `${eventName} logo (invalid organisation ID)`, children: fallbackText });
3940
- }
3941
- if (isLoading) {
3942
- if (LoadingComponent) {
3943
- return /* @__PURE__ */ jsx24(LoadingComponent, {});
3944
- }
3945
- return /* @__PURE__ */ jsx24("div", { className: `${combinedClasses} animate-pulse`, children: /* @__PURE__ */ jsx24("div", { className: "w-3/4 h-3/4 bg-gray-300 rounded" }) });
3946
- }
3947
- if (error) {
3948
- if (ErrorComponent) {
3949
- return /* @__PURE__ */ jsx24(ErrorComponent, { error });
3950
- }
3951
- if (showFallback) {
3952
- return /* @__PURE__ */ jsx24("div", { className: combinedClasses, title: `${eventName} (logo unavailable)`, children: fallbackText });
3953
- }
3954
- return null;
3955
- }
3956
- if (!logoUrl) {
3957
- if (showFallback) {
3958
- return /* @__PURE__ */ jsx24("div", { className: combinedClasses, title: `${eventName} logo`, children: fallbackText });
3959
- }
3960
- return null;
3961
- }
3962
- return /* @__PURE__ */ jsx24(
3963
- "img",
3964
- {
3965
- src: logoUrl,
3966
- alt: `${eventName} logo`,
3967
- className: `${sizeClass} ${className}`.trim(),
3968
- onError: (e) => {
3969
- const target = e.target;
3970
- target.style.display = "none";
3971
- const fallback = document.createElement("div");
3972
- fallback.className = combinedClasses;
3973
- fallback.textContent = fallbackText;
3974
- fallback.title = `${eventName} logo`;
3975
- target.parentNode?.insertBefore(fallback, target.nextSibling);
3976
- }
3977
- }
3978
- );
3979
- }
3980
- function EventLogo({
3981
- eventId,
3982
- eventName,
3983
- organisationId,
3984
- size = "md",
3985
- className = "",
3986
- showFallback = true,
3987
- generateFallbackText = defaultGenerateFallbackText2,
3988
- validateImage = true,
3989
- loadingComponent: LoadingComponent,
3990
- errorComponent: ErrorComponent
3991
- }) {
3992
- const isPublicPage = useIsPublicPage();
3993
- if (isPublicPage) {
3994
- return /* @__PURE__ */ jsx24(
3995
- EventLogoPublic,
3996
- {
3997
- eventId,
3998
- eventName,
3999
- organisationId,
4000
- size,
4001
- className,
4002
- showFallback,
4003
- generateFallbackText,
4004
- validateImage,
4005
- LoadingComponent,
4006
- ErrorComponent
4007
- }
4008
- );
4009
- }
4010
- return /* @__PURE__ */ jsx24(
4011
- EventLogoAuthenticated,
4012
- {
4013
- eventId,
4014
- eventName,
4015
- organisationId,
4016
- size,
4017
- className,
4018
- showFallback,
4019
- generateFallbackText,
4020
- validateImage,
4021
- LoadingComponent,
4022
- ErrorComponent
4023
- }
4024
- );
4025
- }
4026
- function EventLogoCompact(props) {
4027
- return /* @__PURE__ */ jsx24(
4028
- EventLogo,
4029
- {
4030
- ...props,
4031
- size: "sm",
4032
- className: `${props.className || ""} rounded-sm`
4033
- }
4034
- );
4035
- }
4036
- function EventLogoLarge(props) {
4037
- return /* @__PURE__ */ jsx24(
4038
- EventLogo,
4039
- {
4040
- ...props,
4041
- size: "xl",
4042
- className: `${props.className || ""} rounded-lg`
4043
- }
4044
- );
4045
- }
3864
+ ...props
3865
+ }
3866
+ ));
3867
+ TableHead.displayName = "TableHead";
3868
+ var TableCell = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
3869
+ "td",
3870
+ {
3871
+ ref,
3872
+ className: cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className),
3873
+ ...props
3874
+ }
3875
+ ));
3876
+ TableCell.displayName = "TableCell";
3877
+ var TableCaption = React19.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx23(
3878
+ "caption",
3879
+ {
3880
+ ref,
3881
+ className: cn("mt-4 text-sm text-muted-foreground", className),
3882
+ ...props
3883
+ }
3884
+ ));
3885
+ TableCaption.displayName = "TableCaption";
4046
3886
 
4047
3887
  // src/components/PublicLayout/PublicPageHeader.tsx
4048
- import { Fragment as Fragment6, jsx as jsx25, jsxs as jsxs19 } from "react/jsx-runtime";
3888
+ import { Fragment as Fragment6, jsx as jsx24, jsxs as jsxs19 } from "react/jsx-runtime";
4049
3889
  function PublicPageHeader({
4050
3890
  event,
4051
3891
  eventCode,
@@ -4056,50 +3896,50 @@ function PublicPageHeader({
4056
3896
  className = "",
4057
3897
  children,
4058
3898
  customAppLogo,
4059
- customEventLogo
3899
+ customEventLogo,
3900
+ supabase
4060
3901
  }) {
4061
3902
  const { appName } = useAppConfig();
4062
3903
  const headerClasses = `bg-white border-b border-gray-200 ${className}`.trim();
4063
- return /* @__PURE__ */ jsx25("header", { className: headerClasses, children: /* @__PURE__ */ jsxs19("div", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto", children: [
3904
+ return /* @__PURE__ */ jsx24("header", { className: headerClasses, children: /* @__PURE__ */ jsxs19("div", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto", children: [
4064
3905
  /* @__PURE__ */ jsxs19("div", { className: "flex items-center justify-between py-4", children: [
4065
- showAppLogo && /* @__PURE__ */ jsx25("div", { className: "flex-shrink-0", children: customAppLogo || /* @__PURE__ */ jsxs19("div", { className: "flex items-center", children: [
4066
- /* @__PURE__ */ jsx25(
4067
- "img",
4068
- {
4069
- className: "h-8 w-auto",
4070
- src: `/${appName.toLowerCase()}_logo_wide.svg`,
4071
- alt: appName
4072
- }
4073
- ),
4074
- /* @__PURE__ */ jsx25("span", { className: "ml-2 text-lg font-semibold text-gray-900", children: appName })
4075
- ] }) }),
4076
- showEventLogo && event && /* @__PURE__ */ jsx25("div", { className: "flex-shrink-0", children: customEventLogo || /* @__PURE__ */ jsx25(
4077
- EventLogo,
3906
+ showAppLogo && /* @__PURE__ */ jsx24("div", { className: "flex-shrink-0", children: customAppLogo || /* @__PURE__ */ jsx24(
3907
+ "img",
3908
+ {
3909
+ className: "h-8 w-8 object-contain",
3910
+ src: `/${appName.toLowerCase()}_logo_square.svg`,
3911
+ alt: appName
3912
+ }
3913
+ ) }),
3914
+ showEventLogo && event && /* @__PURE__ */ jsx24("div", { className: "flex-shrink-0", children: customEventLogo || /* @__PURE__ */ jsx24(
3915
+ FileDisplay,
4078
3916
  {
4079
- eventId: event.event_id,
4080
- eventName: event.event_name,
4081
- organisationId: event.organisation_id,
4082
- size: "md",
4083
- className: "h-12 w-12"
3917
+ supabase,
3918
+ table_name: "event",
3919
+ record_id: event.event_id,
3920
+ organisation_id: event.organisation_id,
3921
+ category: "event_logos" /* EVENT_LOGOS */,
3922
+ showDelete: false,
3923
+ className: "[&_img]:h-12 [&_img]:w-12 [&_img]:object-contain"
4084
3924
  }
4085
3925
  ) })
4086
3926
  ] }),
4087
- /* @__PURE__ */ jsx25("div", { className: "pb-4", children: /* @__PURE__ */ jsxs19("div", { className: "text-center", children: [
3927
+ /* @__PURE__ */ jsx24("div", { className: "pb-4", children: /* @__PURE__ */ jsxs19("div", { className: "text-center", children: [
4088
3928
  event && /* @__PURE__ */ jsxs19(Fragment6, { children: [
4089
- /* @__PURE__ */ jsx25("h1", { className: "text-3xl font-bold text-gray-900 mb-2", children: event.event_name }),
4090
- event.event_venue && /* @__PURE__ */ jsx25("p", { className: "text-md text-gray-500 mb-4", children: event.event_venue })
3929
+ /* @__PURE__ */ jsx24("h1", { className: "text-3xl font-bold text-gray-900 mb-2", children: event.event_name }),
3930
+ event.event_venue && /* @__PURE__ */ jsx24("p", { className: "text-md text-gray-500 mb-4", children: event.event_venue })
4091
3931
  ] }),
4092
3932
  title && /* @__PURE__ */ jsxs19("div", { className: "mt-6", children: [
4093
- /* @__PURE__ */ jsx25("h2", { className: "text-2xl font-semibold text-gray-800 mb-2", children: title }),
4094
- description && /* @__PURE__ */ jsx25("p", { className: "text-lg text-gray-600 max-w-3xl mx-auto", children: description })
3933
+ /* @__PURE__ */ jsx24("h2", { className: "text-2xl font-semibold text-gray-800 mb-2", children: title }),
3934
+ description && /* @__PURE__ */ jsx24("p", { className: "text-lg text-gray-600 max-w-3xl mx-auto", children: description })
4095
3935
  ] }),
4096
- children && /* @__PURE__ */ jsx25("div", { className: "mt-4", children })
3936
+ children && /* @__PURE__ */ jsx24("div", { className: "mt-4", children })
4097
3937
  ] }) })
4098
3938
  ] }) });
4099
3939
  }
4100
3940
 
4101
3941
  // src/components/PublicLayout/PublicPageFooter.tsx
4102
- import { Fragment as Fragment7, jsx as jsx26, jsxs as jsxs20 } from "react/jsx-runtime";
3942
+ import { Fragment as Fragment7, jsx as jsx25, jsxs as jsxs20 } from "react/jsx-runtime";
4103
3943
  function PublicPageFooter({
4104
3944
  event,
4105
3945
  companyName = "Solvera Solutions Pty Ltd",
@@ -4111,17 +3951,17 @@ function PublicPageFooter({
4111
3951
  children
4112
3952
  }) {
4113
3953
  const copyrightText = copyright || `\xA9 Copyright 2022\u2013${year} all rights reserved, ${companyName}.`;
4114
- return /* @__PURE__ */ jsx26("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs20("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
4115
- logo && /* @__PURE__ */ jsx26("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
4116
- children && /* @__PURE__ */ jsx26(Fragment7, { children }),
4117
- /* @__PURE__ */ jsx26("span", { className: "text-muted-foreground", children: copyrightText }),
4118
- links && links.length > 0 && /* @__PURE__ */ jsx26("ul", { className: "flex gap-4 mt-2 md:mt-0", children: links.map((link, index) => /* @__PURE__ */ jsx26("li", { children: /* @__PURE__ */ jsx26("a", { href: link.href, className: "text-muted-foreground hover:text-foreground", children: link.label }) }, index)) })
3954
+ return /* @__PURE__ */ jsx25("footer", { className: cn("mt-8 py-6 flex justify-center border-t border-border bg-main-100", className), children: /* @__PURE__ */ jsxs20("section", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto text-center", children: [
3955
+ logo && /* @__PURE__ */ jsx25("img", { src: logo, alt: "Logo", className: "h-8 w-auto" }),
3956
+ children && /* @__PURE__ */ jsx25(Fragment7, { children }),
3957
+ /* @__PURE__ */ jsx25("span", { className: "text-muted-foreground", children: copyrightText }),
3958
+ 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)) })
4119
3959
  ] }) });
4120
3960
  }
4121
3961
 
4122
3962
  // src/components/PublicLayout/PublicLoadingSpinner.tsx
4123
- import { jsx as jsx27, jsxs as jsxs21 } from "react/jsx-runtime";
4124
- var sizeClasses2 = {
3963
+ import { jsx as jsx26, jsxs as jsxs21 } from "react/jsx-runtime";
3964
+ var sizeClasses = {
4125
3965
  sm: "h-4 w-4",
4126
3966
  md: "h-8 w-8",
4127
3967
  lg: "h-12 w-12",
@@ -4135,10 +3975,10 @@ function PublicLoadingSpinner({
4135
3975
  customMessage,
4136
3976
  centered = true
4137
3977
  }) {
4138
- const sizeClass = sizeClasses2[size];
3978
+ const sizeClass = sizeClasses[size];
4139
3979
  const displayMessage = customMessage || message;
4140
3980
  const content = /* @__PURE__ */ jsxs21("div", { className: `flex flex-col items-center ${className}`, children: [
4141
- showLogo && /* @__PURE__ */ jsx27("div", { className: "mb-4", children: /* @__PURE__ */ jsx27(
3981
+ showLogo && /* @__PURE__ */ jsx26("div", { className: "mb-4", children: /* @__PURE__ */ jsx26(
4142
3982
  "img",
4143
3983
  {
4144
3984
  className: "h-8 w-auto",
@@ -4147,7 +3987,7 @@ function PublicLoadingSpinner({
4147
3987
  }
4148
3988
  ) }),
4149
3989
  /* @__PURE__ */ jsxs21("div", { className: "relative", children: [
4150
- /* @__PURE__ */ jsx27(
3990
+ /* @__PURE__ */ jsx26(
4151
3991
  "div",
4152
3992
  {
4153
3993
  className: `${sizeClass} border-2 border-gray-200 border-t-blue-600 rounded-full animate-spin`,
@@ -4155,12 +3995,12 @@ function PublicLoadingSpinner({
4155
3995
  "aria-label": "Loading"
4156
3996
  }
4157
3997
  ),
4158
- /* @__PURE__ */ jsx27("span", { className: "sr-only", children: displayMessage })
3998
+ /* @__PURE__ */ jsx26("span", { className: "sr-only", children: displayMessage })
4159
3999
  ] }),
4160
- displayMessage && /* @__PURE__ */ jsx27("p", { className: "mt-4 text-sm text-gray-600 text-center", children: displayMessage })
4000
+ displayMessage && /* @__PURE__ */ jsx26("p", { className: "mt-4 text-sm text-gray-600 text-center", children: displayMessage })
4161
4001
  ] });
4162
4002
  if (centered) {
4163
- return /* @__PURE__ */ jsx27("div", { className: "min-h-screen bg-white flex items-center justify-center", children: /* @__PURE__ */ jsx27("div", { className: "max-w-md mx-auto px-4", children: content }) });
4003
+ 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 }) });
4164
4004
  }
4165
4005
  return content;
4166
4006
  }
@@ -4169,8 +4009,8 @@ function PublicLoadingSpinnerFullPage({
4169
4009
  eventName,
4170
4010
  className = ""
4171
4011
  }) {
4172
- return /* @__PURE__ */ jsx27("div", { className: `min-h-screen bg-white flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs21("div", { className: "max-w-md mx-auto text-center px-4", children: [
4173
- /* @__PURE__ */ jsx27("div", { className: "mb-8", children: /* @__PURE__ */ jsx27(
4012
+ return /* @__PURE__ */ jsx26("div", { className: `min-h-screen bg-white flex items-center justify-center ${className}`, children: /* @__PURE__ */ jsxs21("div", { className: "max-w-md mx-auto text-center px-4", children: [
4013
+ /* @__PURE__ */ jsx26("div", { className: "mb-8", children: /* @__PURE__ */ jsx26(
4174
4014
  "img",
4175
4015
  {
4176
4016
  className: "h-12 w-auto mx-auto",
@@ -4178,8 +4018,8 @@ function PublicLoadingSpinnerFullPage({
4178
4018
  alt: "PACE Core"
4179
4019
  }
4180
4020
  ) }),
4181
- eventName && /* @__PURE__ */ jsx27("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: eventName }),
4182
- /* @__PURE__ */ jsx27("div", { className: "relative mb-6", children: /* @__PURE__ */ jsx27(
4021
+ eventName && /* @__PURE__ */ jsx26("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: eventName }),
4022
+ /* @__PURE__ */ jsx26("div", { className: "relative mb-6", children: /* @__PURE__ */ jsx26(
4183
4023
  "div",
4184
4024
  {
4185
4025
  className: "h-12 w-12 border-4 border-gray-200 border-t-blue-600 rounded-full animate-spin mx-auto",
@@ -4187,11 +4027,11 @@ function PublicLoadingSpinnerFullPage({
4187
4027
  "aria-label": "Loading"
4188
4028
  }
4189
4029
  ) }),
4190
- /* @__PURE__ */ jsx27("p", { className: "text-lg text-gray-600", children: message }),
4030
+ /* @__PURE__ */ jsx26("p", { className: "text-lg text-gray-600", children: message }),
4191
4031
  /* @__PURE__ */ jsxs21("div", { className: "mt-4 flex justify-center space-x-1", children: [
4192
- /* @__PURE__ */ jsx27("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
4193
- /* @__PURE__ */ jsx27("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
4194
- /* @__PURE__ */ jsx27("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "300ms" } })
4032
+ /* @__PURE__ */ jsx26("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "0ms" } }),
4033
+ /* @__PURE__ */ jsx26("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "150ms" } }),
4034
+ /* @__PURE__ */ jsx26("div", { className: "h-2 w-2 bg-blue-600 rounded-full animate-bounce", style: { animationDelay: "300ms" } })
4195
4035
  ] })
4196
4036
  ] }) });
4197
4037
  }
@@ -4199,7 +4039,7 @@ function PublicLoadingSkeleton({
4199
4039
  lines = 3,
4200
4040
  className = ""
4201
4041
  }) {
4202
- return /* @__PURE__ */ jsx27("div", { className: `animate-pulse ${className}`, children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ jsx27(
4042
+ return /* @__PURE__ */ jsx26("div", { className: `animate-pulse ${className}`, children: Array.from({ length: lines }).map((_, index) => /* @__PURE__ */ jsx26(
4203
4043
  "div",
4204
4044
  {
4205
4045
  className: `h-4 bg-gray-200 rounded mb-2 ${index === lines - 1 ? "w-3/4" : "w-full"}`
@@ -4209,8 +4049,8 @@ function PublicLoadingSkeleton({
4209
4049
  }
4210
4050
 
4211
4051
  // src/components/PublicLayout/PublicPageLayout.tsx
4212
- import { useMemo as useMemo11 } from "react";
4213
- import { jsx as jsx28, jsxs as jsxs22 } from "react/jsx-runtime";
4052
+ import { useMemo as useMemo10 } from "react";
4053
+ import { jsx as jsx27, jsxs as jsxs22 } from "react/jsx-runtime";
4214
4054
  function PublicPageLayout({
4215
4055
  eventCode,
4216
4056
  children,
@@ -4227,22 +4067,22 @@ function PublicPageLayout({
4227
4067
  const error = null;
4228
4068
  const refetch = async () => {
4229
4069
  };
4230
- const layoutClasses = useMemo11(() => {
4070
+ const layoutClasses = useMemo10(() => {
4231
4071
  const baseClasses = "min-h-screen bg-white flex flex-col";
4232
4072
  return `${baseClasses} ${className}`.trim();
4233
4073
  }, [className]);
4234
4074
  if (isLoading) {
4235
- return /* @__PURE__ */ jsx28("div", { className: layoutClasses, children: /* @__PURE__ */ jsx28("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsx28(LoadingFallback, {}) }) });
4075
+ return /* @__PURE__ */ jsx27("div", { className: layoutClasses, children: /* @__PURE__ */ jsx27("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsx27(LoadingFallback, {}) }) });
4236
4076
  }
4237
4077
  if (error && showValidationErrors) {
4238
- return /* @__PURE__ */ jsx28("div", { className: layoutClasses, children: /* @__PURE__ */ jsx28("div", { className: "flex-1 flex items-center justify-center", children: ErrorFallback ? /* @__PURE__ */ jsx28(ErrorFallback, { error, retry: refetch }) : /* @__PURE__ */ jsxs22("div", { className: "text-center p-8", children: [
4239
- /* @__PURE__ */ jsx28("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Found" }),
4078
+ 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__ */ jsxs22("div", { className: "text-center p-8", children: [
4079
+ /* @__PURE__ */ jsx27("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Found" }),
4240
4080
  /* @__PURE__ */ jsxs22("p", { className: "text-gray-600 mb-6", children: [
4241
4081
  'The event code "',
4242
4082
  eventCode,
4243
4083
  '" is invalid or the event is not available for public viewing.'
4244
4084
  ] }),
4245
- /* @__PURE__ */ jsx28(
4085
+ /* @__PURE__ */ jsx27(
4246
4086
  "button",
4247
4087
  {
4248
4088
  onClick: refetch,
@@ -4253,10 +4093,10 @@ function PublicPageLayout({
4253
4093
  ] }) }) });
4254
4094
  }
4255
4095
  if (!event) {
4256
- return /* @__PURE__ */ jsx28("div", { className: layoutClasses, children: /* @__PURE__ */ jsx28("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs22("div", { className: "text-center p-8", children: [
4257
- /* @__PURE__ */ jsx28("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Available" }),
4258
- /* @__PURE__ */ jsx28("p", { className: "text-gray-600 mb-6", children: "This event is not available for public viewing." }),
4259
- /* @__PURE__ */ jsx28(
4096
+ return /* @__PURE__ */ jsx27("div", { className: layoutClasses, children: /* @__PURE__ */ jsx27("div", { className: "flex-1 flex items-center justify-center", children: /* @__PURE__ */ jsxs22("div", { className: "text-center p-8", children: [
4097
+ /* @__PURE__ */ jsx27("h1", { className: "text-2xl font-bold text-gray-900 mb-4", children: "Event Not Available" }),
4098
+ /* @__PURE__ */ jsx27("p", { className: "text-gray-600 mb-6", children: "This event is not available for public viewing." }),
4099
+ /* @__PURE__ */ jsx27(
4260
4100
  "button",
4261
4101
  {
4262
4102
  onClick: refetch,
@@ -4266,16 +4106,16 @@ function PublicPageLayout({
4266
4106
  )
4267
4107
  ] }) }) });
4268
4108
  }
4269
- return /* @__PURE__ */ jsx28(PublicErrorBoundary, { children: /* @__PURE__ */ jsxs22("div", { className: layoutClasses, children: [
4270
- customHeader || /* @__PURE__ */ jsx28(
4109
+ return /* @__PURE__ */ jsx27(PublicErrorBoundary, { children: /* @__PURE__ */ jsxs22("div", { className: layoutClasses, children: [
4110
+ customHeader || /* @__PURE__ */ jsx27(
4271
4111
  PublicPageHeader,
4272
4112
  {
4273
4113
  event,
4274
4114
  eventCode
4275
4115
  }
4276
4116
  ),
4277
- /* @__PURE__ */ jsx28("main", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children }),
4278
- showFooter && (customFooter || /* @__PURE__ */ jsx28(PublicPageFooter, { event }))
4117
+ /* @__PURE__ */ jsx27("main", { className: "px-4 w-[min(var(--app-width),100%)] mx-auto py-8", children }),
4118
+ showFooter && (customFooter || /* @__PURE__ */ jsx27(PublicPageFooter, { event }))
4279
4119
  ] }) });
4280
4120
  }
4281
4121
  function usePublicPageContext2() {
@@ -4293,7 +4133,7 @@ function usePublicPageContext2() {
4293
4133
 
4294
4134
  // src/components/PublicLayout/PublicPageDebugger.tsx
4295
4135
  import { useEffect as useEffect9 } from "react";
4296
- import { jsx as jsx29, jsxs as jsxs23 } from "react/jsx-runtime";
4136
+ import { jsx as jsx28, jsxs as jsxs23 } from "react/jsx-runtime";
4297
4137
  function PublicPageDebugger({ enabled = true, label = "PublicPage" }) {
4298
4138
  useEffect9(() => {
4299
4139
  if (!enabled) return;
@@ -4347,14 +4187,14 @@ function PublicPageDebugger({ enabled = true, label = "PublicPage" }) {
4347
4187
  zIndex: 9999,
4348
4188
  fontFamily: "monospace"
4349
4189
  }, children: [
4350
- /* @__PURE__ */ jsx29("div", { children: "Public Page Debugger" }),
4351
- /* @__PURE__ */ jsx29("div", { children: "Check console for context analysis" })
4190
+ /* @__PURE__ */ jsx28("div", { children: "Public Page Debugger" }),
4191
+ /* @__PURE__ */ jsx28("div", { children: "Check console for context analysis" })
4352
4192
  ] });
4353
4193
  }
4354
4194
 
4355
4195
  // src/components/PublicLayout/PublicPageDiagnostic.tsx
4356
4196
  import { useEffect as useEffect10, useState as useState13 } from "react";
4357
- import { jsx as jsx30, jsxs as jsxs24 } from "react/jsx-runtime";
4197
+ import { jsx as jsx29, jsxs as jsxs24 } from "react/jsx-runtime";
4358
4198
  function PublicPageDiagnostic({ enabled = true, label = "PublicPage" }) {
4359
4199
  const [diagnostics, setDiagnostics] = useState13({
4360
4200
  hasPublicPageContext: false,
@@ -4448,7 +4288,7 @@ function PublicPageDiagnostic({ enabled = true, label = "PublicPage" }) {
4448
4288
  maxWidth: "300px",
4449
4289
  borderRadius: "0 0 8px 0"
4450
4290
  }, children: [
4451
- /* @__PURE__ */ jsx30("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F50D} Public Page Diagnostics" }),
4291
+ /* @__PURE__ */ jsx29("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F50D} Public Page Diagnostics" }),
4452
4292
  /* @__PURE__ */ jsxs24("div", { children: [
4453
4293
  "Public Context: ",
4454
4294
  diagnostics.hasPublicPageContext ? "\u2705" : "\u274C"
@@ -4473,13 +4313,13 @@ function PublicPageDiagnostic({ enabled = true, label = "PublicPage" }) {
4473
4313
  "Route Params: ",
4474
4314
  diagnostics.routeParams ? "\u2705" : "\u274C"
4475
4315
  ] }),
4476
- /* @__PURE__ */ jsx30("div", { style: { marginTop: "8px", fontSize: "10px", opacity: 0.8 }, children: "Check console for detailed analysis" })
4316
+ /* @__PURE__ */ jsx29("div", { style: { marginTop: "8px", fontSize: "10px", opacity: 0.8 }, children: "Check console for detailed analysis" })
4477
4317
  ] });
4478
4318
  }
4479
4319
 
4480
4320
  // src/components/PublicLayout/PublicPageContextChecker.tsx
4481
4321
  import { useEffect as useEffect11 } from "react";
4482
- import { jsx as jsx31, jsxs as jsxs25 } from "react/jsx-runtime";
4322
+ import { jsx as jsx30, jsxs as jsxs25 } from "react/jsx-runtime";
4483
4323
  function PublicPageContextChecker({ enabled = true, label = "PublicPage" }) {
4484
4324
  useEffect11(() => {
4485
4325
  if (!enabled) return;
@@ -4557,12 +4397,261 @@ function PublicPageContextChecker({ enabled = true, label = "PublicPage" }) {
4557
4397
  borderRadius: "0 0 8px 0",
4558
4398
  border: "2px solid #dc2626"
4559
4399
  }, children: [
4560
- /* @__PURE__ */ jsx31("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F6A8} PUBLIC PAGE CONTEXT CHECK" }),
4561
- /* @__PURE__ */ jsx31("div", { children: "Check console for authentication context analysis" }),
4562
- /* @__PURE__ */ jsx31("div", { style: { marginTop: "8px", fontSize: "10px", opacity: 0.9 }, children: "If you see \u274C errors in console, your public page is inside auth context!" })
4400
+ /* @__PURE__ */ jsx30("div", { style: { fontWeight: "bold", marginBottom: "8px" }, children: "\u{1F6A8} PUBLIC PAGE CONTEXT CHECK" }),
4401
+ /* @__PURE__ */ jsx30("div", { children: "Check console for authentication context analysis" }),
4402
+ /* @__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!" })
4563
4403
  ] });
4564
4404
  }
4565
4405
 
4406
+ // src/components/PublicLayout/EventLogo.tsx
4407
+ import { useMemo as useMemo11, useContext as useContext2 } from "react";
4408
+ init_UnifiedAuthProvider();
4409
+ import { jsx as jsx31 } from "react/jsx-runtime";
4410
+ var sizeClasses2 = {
4411
+ xs: "h-4 w-4 text-xs",
4412
+ sm: "h-6 w-6 text-sm",
4413
+ md: "h-8 w-8 text-base",
4414
+ lg: "h-12 w-12 text-lg",
4415
+ xl: "h-16 w-16 text-xl",
4416
+ "2xl": "h-20 w-20 text-2xl"
4417
+ };
4418
+ function defaultGenerateFallbackText2(eventName) {
4419
+ if (!eventName) return "EV";
4420
+ return eventName.split(" ").map((word) => word.charAt(0).toUpperCase()).join("").substring(0, 3);
4421
+ }
4422
+ function EventLogoPublic({
4423
+ eventId,
4424
+ eventName,
4425
+ organisationId,
4426
+ size,
4427
+ className,
4428
+ showFallback,
4429
+ generateFallbackText,
4430
+ validateImage,
4431
+ LoadingComponent,
4432
+ ErrorComponent
4433
+ }) {
4434
+ const publicPageContext = useContext2(PublicPageContext);
4435
+ const supabase = publicPageContext?.supabase ?? null;
4436
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
4437
+ const hasValidOrganisationId = organisationId && uuidRegex.test(organisationId);
4438
+ if (!supabase) {
4439
+ const effectiveSize = size || "md";
4440
+ return /* @__PURE__ */ jsx31("div", { className: `${sizeClasses2[effectiveSize]} ${className}`.trim(), title: `${eventName} logo (Supabase not configured)`, children: eventName ? defaultGenerateFallbackText2(eventName) : "EV" });
4441
+ }
4442
+ const {
4443
+ logoUrl,
4444
+ fallbackText,
4445
+ isLoading,
4446
+ error
4447
+ } = usePublicEventLogo(
4448
+ eventId,
4449
+ eventName,
4450
+ organisationId,
4451
+ // Always pass organisationId, let the hook handle validation
4452
+ {
4453
+ validateImage,
4454
+ generateFallbackText,
4455
+ supabase
4456
+ }
4457
+ );
4458
+ const sizeClass = useMemo11(() => sizeClasses2[size || "md"], [size]);
4459
+ const combinedClasses = useMemo11(() => {
4460
+ const baseClasses = "flex items-center justify-center bg-gray-100 text-gray-600 font-semibold rounded";
4461
+ return `${baseClasses} ${sizeClass} ${className}`.trim();
4462
+ }, [sizeClass, className]);
4463
+ if (!hasValidOrganisationId && !isLoading && !logoUrl && showFallback) {
4464
+ return /* @__PURE__ */ jsx31("div", { className: combinedClasses, title: `${eventName} logo (invalid organisation ID)`, children: fallbackText });
4465
+ }
4466
+ if (isLoading) {
4467
+ if (LoadingComponent) {
4468
+ return /* @__PURE__ */ jsx31(LoadingComponent, {});
4469
+ }
4470
+ return /* @__PURE__ */ jsx31("div", { className: `${combinedClasses} animate-pulse`, children: /* @__PURE__ */ jsx31("div", { className: "w-3/4 h-3/4 bg-gray-300 rounded" }) });
4471
+ }
4472
+ if (error) {
4473
+ if (ErrorComponent) {
4474
+ return /* @__PURE__ */ jsx31(ErrorComponent, { error });
4475
+ }
4476
+ if (showFallback) {
4477
+ return /* @__PURE__ */ jsx31("div", { className: combinedClasses, title: `${eventName} (logo unavailable)`, children: fallbackText });
4478
+ }
4479
+ return null;
4480
+ }
4481
+ if (!logoUrl) {
4482
+ if (showFallback) {
4483
+ return /* @__PURE__ */ jsx31("div", { className: combinedClasses, title: `${eventName} logo`, children: fallbackText });
4484
+ }
4485
+ return null;
4486
+ }
4487
+ const imageClasses = `${sizeClass} object-contain rounded ${className}`.trim();
4488
+ return /* @__PURE__ */ jsx31(
4489
+ "img",
4490
+ {
4491
+ src: logoUrl,
4492
+ alt: `${eventName} logo`,
4493
+ className: imageClasses,
4494
+ onError: (e) => {
4495
+ const target = e.target;
4496
+ target.style.display = "none";
4497
+ const fallback = document.createElement("div");
4498
+ fallback.className = combinedClasses;
4499
+ fallback.textContent = fallbackText;
4500
+ fallback.title = `${eventName} logo`;
4501
+ target.parentNode?.insertBefore(fallback, target.nextSibling);
4502
+ }
4503
+ }
4504
+ );
4505
+ }
4506
+ function EventLogoAuthenticated({
4507
+ eventId,
4508
+ eventName,
4509
+ organisationId,
4510
+ size,
4511
+ className,
4512
+ showFallback,
4513
+ generateFallbackText,
4514
+ validateImage,
4515
+ LoadingComponent,
4516
+ ErrorComponent
4517
+ }) {
4518
+ const { supabase } = useUnifiedAuth();
4519
+ const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
4520
+ const hasValidOrganisationId = organisationId && uuidRegex.test(organisationId);
4521
+ if (!supabase) {
4522
+ const effectiveSize = size || "md";
4523
+ return /* @__PURE__ */ jsx31("div", { className: `${sizeClasses2[effectiveSize]} ${className}`.trim(), title: `${eventName} logo (Supabase not configured)`, children: eventName ? defaultGenerateFallbackText2(eventName) : "EV" });
4524
+ }
4525
+ const {
4526
+ logoUrl,
4527
+ fallbackText,
4528
+ isLoading,
4529
+ error
4530
+ } = useEventLogo(
4531
+ supabase,
4532
+ eventId,
4533
+ eventName,
4534
+ organisationId,
4535
+ {
4536
+ validateImage,
4537
+ generateFallbackText
4538
+ }
4539
+ );
4540
+ const sizeClass = useMemo11(() => sizeClasses2[size || "md"], [size]);
4541
+ const combinedClasses = useMemo11(() => {
4542
+ const baseClasses = "flex items-center justify-center bg-gray-100 text-gray-600 font-semibold rounded";
4543
+ return `${baseClasses} ${sizeClass} ${className}`.trim();
4544
+ }, [sizeClass, className]);
4545
+ if (!hasValidOrganisationId && !isLoading && !logoUrl && showFallback) {
4546
+ return /* @__PURE__ */ jsx31("div", { className: combinedClasses, title: `${eventName} logo (invalid organisation ID)`, children: fallbackText });
4547
+ }
4548
+ if (isLoading) {
4549
+ if (LoadingComponent) {
4550
+ return /* @__PURE__ */ jsx31(LoadingComponent, {});
4551
+ }
4552
+ return /* @__PURE__ */ jsx31("div", { className: `${combinedClasses} animate-pulse`, children: /* @__PURE__ */ jsx31("div", { className: "w-3/4 h-3/4 bg-gray-300 rounded" }) });
4553
+ }
4554
+ if (error) {
4555
+ if (ErrorComponent) {
4556
+ return /* @__PURE__ */ jsx31(ErrorComponent, { error });
4557
+ }
4558
+ if (showFallback) {
4559
+ return /* @__PURE__ */ jsx31("div", { className: combinedClasses, title: `${eventName} (logo unavailable)`, children: fallbackText });
4560
+ }
4561
+ return null;
4562
+ }
4563
+ if (!logoUrl) {
4564
+ if (showFallback) {
4565
+ return /* @__PURE__ */ jsx31("div", { className: combinedClasses, title: `${eventName} logo`, children: fallbackText });
4566
+ }
4567
+ return null;
4568
+ }
4569
+ const imageClasses = `${sizeClass} object-contain rounded ${className}`.trim();
4570
+ return /* @__PURE__ */ jsx31(
4571
+ "img",
4572
+ {
4573
+ src: logoUrl,
4574
+ alt: `${eventName} logo`,
4575
+ className: imageClasses,
4576
+ onError: (e) => {
4577
+ const target = e.target;
4578
+ target.style.display = "none";
4579
+ const fallback = document.createElement("div");
4580
+ fallback.className = combinedClasses;
4581
+ fallback.textContent = fallbackText;
4582
+ fallback.title = `${eventName} logo`;
4583
+ target.parentNode?.insertBefore(fallback, target.nextSibling);
4584
+ }
4585
+ }
4586
+ );
4587
+ }
4588
+ function EventLogo({
4589
+ eventId,
4590
+ eventName,
4591
+ organisationId,
4592
+ size = "md",
4593
+ className = "",
4594
+ showFallback = true,
4595
+ generateFallbackText = defaultGenerateFallbackText2,
4596
+ validateImage = true,
4597
+ loadingComponent: LoadingComponent,
4598
+ errorComponent: ErrorComponent
4599
+ }) {
4600
+ const isPublicPage = useIsPublicPage();
4601
+ if (isPublicPage) {
4602
+ return /* @__PURE__ */ jsx31(
4603
+ EventLogoPublic,
4604
+ {
4605
+ eventId,
4606
+ eventName,
4607
+ organisationId,
4608
+ size,
4609
+ className,
4610
+ showFallback,
4611
+ generateFallbackText,
4612
+ validateImage,
4613
+ LoadingComponent,
4614
+ ErrorComponent
4615
+ }
4616
+ );
4617
+ }
4618
+ return /* @__PURE__ */ jsx31(
4619
+ EventLogoAuthenticated,
4620
+ {
4621
+ eventId,
4622
+ eventName,
4623
+ organisationId,
4624
+ size,
4625
+ className,
4626
+ showFallback,
4627
+ generateFallbackText,
4628
+ validateImage,
4629
+ LoadingComponent,
4630
+ ErrorComponent
4631
+ }
4632
+ );
4633
+ }
4634
+ function EventLogoCompact(props) {
4635
+ return /* @__PURE__ */ jsx31(
4636
+ EventLogo,
4637
+ {
4638
+ ...props,
4639
+ size: "sm",
4640
+ className: `${props.className || ""} rounded-sm`
4641
+ }
4642
+ );
4643
+ }
4644
+ function EventLogoLarge(props) {
4645
+ return /* @__PURE__ */ jsx31(
4646
+ EventLogo,
4647
+ {
4648
+ ...props,
4649
+ size: "xl",
4650
+ className: `${props.className || ""} rounded-lg`
4651
+ }
4652
+ );
4653
+ }
4654
+
4566
4655
  export {
4567
4656
  init_EventProvider,
4568
4657
  Label,
@@ -4611,9 +4700,6 @@ export {
4611
4700
  TableHead,
4612
4701
  TableCell,
4613
4702
  TableCaption,
4614
- EventLogo,
4615
- EventLogoCompact,
4616
- EventLogoLarge,
4617
4703
  PublicPageHeader,
4618
4704
  PublicPageFooter,
4619
4705
  PublicLoadingSpinner,
@@ -4623,6 +4709,9 @@ export {
4623
4709
  usePublicPageContext2 as usePublicPageContext,
4624
4710
  PublicPageDebugger,
4625
4711
  PublicPageDiagnostic,
4626
- PublicPageContextChecker
4712
+ PublicPageContextChecker,
4713
+ EventLogo,
4714
+ EventLogoCompact,
4715
+ EventLogoLarge
4627
4716
  };
4628
- //# sourceMappingURL=chunk-5LAY74WM.js.map
4717
+ //# sourceMappingURL=chunk-O6GASC4Q.js.map