@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.
- package/dist/{DataTable-HC5S4RKB.js → DataTable-CHX2EFO3.js} +6 -6
- package/dist/{PublicLoadingSpinner-n74JgA9h.d.ts → PublicLoadingSpinner-BWUD6bLU.d.ts} +24 -3
- package/dist/{UnifiedAuthProvider-ZM7VUC45.js → UnifiedAuthProvider-H7RI4KYD.js} +3 -3
- package/dist/{chunk-AZ2QJYKU.js → chunk-2KLAOD4M.js} +3 -3
- package/dist/{chunk-HW5BGOWB.js → chunk-2ZYHCFUO.js} +4 -4
- package/dist/{chunk-AAM57AEU.js → chunk-5RYPBJYL.js} +16 -19
- package/dist/chunk-5RYPBJYL.js.map +1 -0
- package/dist/{chunk-XIBSVWJW.js → chunk-7TQDRDSM.js} +5 -5
- package/dist/{chunk-GP3HU6WS.js → chunk-G7UUVEAP.js} +3 -3
- package/dist/{chunk-M52CQP5W.js → chunk-MKMKUCPF.js} +762 -12
- package/dist/chunk-MKMKUCPF.js.map +1 -0
- package/dist/{chunk-OXFOS62D.js → chunk-MVNOAHOP.js} +2 -2
- package/dist/{chunk-5LAY74WM.js → chunk-O6GASC4Q.js} +877 -788
- package/dist/chunk-O6GASC4Q.js.map +1 -0
- package/dist/{chunk-AYC2P377.js → chunk-ORACUZ7H.js} +2 -2
- package/dist/{chunk-TZXYSZT3.js → chunk-PRM6EYO3.js} +298 -238
- package/dist/{chunk-TZXYSZT3.js.map → chunk-PRM6EYO3.js.map} +1 -1
- package/dist/{chunk-6WFM22A4.js → chunk-ZGCVJ7WW.js} +2 -2
- package/dist/components.d.ts +1 -1
- package/dist/components.js +8 -8
- package/dist/hooks.d.ts +94 -3
- package/dist/hooks.js +20 -8
- package/dist/hooks.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +17 -11
- package/dist/index.js.map +1 -1
- package/dist/providers.js +2 -2
- package/dist/rbac/index.js +7 -7
- package/dist/{usePublicRouteParams-BlgwXweB.d.ts → usePublicRouteParams-BwMR2uub.d.ts} +93 -1
- package/dist/utils.js +1 -1
- package/docs/api/classes/ColumnFactory.md +1 -1
- package/docs/api/classes/ErrorBoundary.md +1 -1
- package/docs/api/classes/InvalidScopeError.md +1 -1
- package/docs/api/classes/MissingUserContextError.md +1 -1
- package/docs/api/classes/OrganisationContextRequiredError.md +1 -1
- package/docs/api/classes/PermissionDeniedError.md +1 -1
- package/docs/api/classes/PublicErrorBoundary.md +1 -1
- package/docs/api/classes/RBACAuditManager.md +1 -1
- package/docs/api/classes/RBACCache.md +1 -1
- package/docs/api/classes/RBACEngine.md +1 -1
- package/docs/api/classes/RBACError.md +1 -1
- package/docs/api/classes/RBACNotInitializedError.md +1 -1
- package/docs/api/classes/SecureSupabaseClient.md +1 -1
- package/docs/api/classes/StorageUtils.md +1 -1
- package/docs/api/enums/FileCategory.md +1 -1
- package/docs/api/interfaces/AggregateConfig.md +1 -1
- package/docs/api/interfaces/ButtonProps.md +1 -1
- package/docs/api/interfaces/CardProps.md +1 -1
- package/docs/api/interfaces/ColorPalette.md +1 -1
- package/docs/api/interfaces/ColorShade.md +1 -1
- package/docs/api/interfaces/DataAccessRecord.md +1 -1
- package/docs/api/interfaces/DataRecord.md +1 -1
- package/docs/api/interfaces/DataTableAction.md +1 -1
- package/docs/api/interfaces/DataTableColumn.md +1 -1
- package/docs/api/interfaces/DataTableProps.md +1 -1
- package/docs/api/interfaces/DataTableToolbarButton.md +1 -1
- package/docs/api/interfaces/EmptyStateConfig.md +1 -1
- package/docs/api/interfaces/EnhancedNavigationMenuProps.md +1 -1
- package/docs/api/interfaces/EventLogoProps.md +1 -1
- package/docs/api/interfaces/FileDisplayProps.md +26 -11
- package/docs/api/interfaces/FileMetadata.md +1 -1
- package/docs/api/interfaces/FileReference.md +1 -1
- package/docs/api/interfaces/FileSizeLimits.md +1 -1
- package/docs/api/interfaces/FileUploadOptions.md +1 -1
- package/docs/api/interfaces/FileUploadProps.md +1 -1
- package/docs/api/interfaces/FooterProps.md +1 -1
- package/docs/api/interfaces/InactivityWarningModalProps.md +1 -1
- package/docs/api/interfaces/InputProps.md +1 -1
- package/docs/api/interfaces/LabelProps.md +1 -1
- package/docs/api/interfaces/LoginFormProps.md +1 -1
- package/docs/api/interfaces/NavigationAccessRecord.md +1 -1
- package/docs/api/interfaces/NavigationContextType.md +1 -1
- package/docs/api/interfaces/NavigationGuardProps.md +1 -1
- package/docs/api/interfaces/NavigationItem.md +1 -1
- package/docs/api/interfaces/NavigationMenuProps.md +1 -1
- package/docs/api/interfaces/NavigationProviderProps.md +1 -1
- package/docs/api/interfaces/Organisation.md +1 -1
- package/docs/api/interfaces/OrganisationContextType.md +1 -1
- package/docs/api/interfaces/OrganisationMembership.md +1 -1
- package/docs/api/interfaces/OrganisationProviderProps.md +1 -1
- package/docs/api/interfaces/OrganisationSecurityError.md +1 -1
- package/docs/api/interfaces/PaceAppLayoutProps.md +1 -1
- package/docs/api/interfaces/PaceLoginPageProps.md +1 -1
- package/docs/api/interfaces/PageAccessRecord.md +1 -1
- package/docs/api/interfaces/PagePermissionContextType.md +1 -1
- package/docs/api/interfaces/PagePermissionGuardProps.md +1 -1
- package/docs/api/interfaces/PagePermissionProviderProps.md +1 -1
- package/docs/api/interfaces/PaletteData.md +1 -1
- package/docs/api/interfaces/PermissionEnforcerProps.md +1 -1
- package/docs/api/interfaces/ProtectedRouteProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryProps.md +1 -1
- package/docs/api/interfaces/PublicErrorBoundaryState.md +1 -1
- package/docs/api/interfaces/PublicLoadingSpinnerProps.md +1 -1
- package/docs/api/interfaces/PublicPageFooterProps.md +1 -1
- package/docs/api/interfaces/PublicPageHeaderProps.md +24 -11
- package/docs/api/interfaces/PublicPageLayoutProps.md +1 -1
- package/docs/api/interfaces/RBACConfig.md +1 -1
- package/docs/api/interfaces/RBACLogger.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterContextType.md +1 -1
- package/docs/api/interfaces/RoleBasedRouterProps.md +1 -1
- package/docs/api/interfaces/RouteAccessRecord.md +1 -1
- package/docs/api/interfaces/RouteConfig.md +1 -1
- package/docs/api/interfaces/SecureDataContextType.md +1 -1
- package/docs/api/interfaces/SecureDataProviderProps.md +1 -1
- package/docs/api/interfaces/StorageConfig.md +1 -1
- package/docs/api/interfaces/StorageFileInfo.md +1 -1
- package/docs/api/interfaces/StorageFileMetadata.md +1 -1
- package/docs/api/interfaces/StorageListOptions.md +1 -1
- package/docs/api/interfaces/StorageListResult.md +1 -1
- package/docs/api/interfaces/StorageUploadOptions.md +1 -1
- package/docs/api/interfaces/StorageUploadResult.md +1 -1
- package/docs/api/interfaces/StorageUrlOptions.md +1 -1
- package/docs/api/interfaces/StyleImport.md +1 -1
- package/docs/api/interfaces/SwitchProps.md +1 -1
- package/docs/api/interfaces/ToastActionElement.md +1 -1
- package/docs/api/interfaces/ToastProps.md +1 -1
- package/docs/api/interfaces/UnifiedAuthContextType.md +1 -1
- package/docs/api/interfaces/UnifiedAuthProviderProps.md +1 -1
- package/docs/api/interfaces/UseEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UseEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerOptions.md +1 -1
- package/docs/api/interfaces/UseInactivityTrackerReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventLogoReturn.md +1 -1
- package/docs/api/interfaces/UsePublicEventOptions.md +1 -1
- package/docs/api/interfaces/UsePublicEventReturn.md +1 -1
- package/docs/api/interfaces/UsePublicFileDisplayOptions.md +47 -0
- package/docs/api/interfaces/UsePublicFileDisplayReturn.md +120 -0
- package/docs/api/interfaces/UsePublicRouteParamsReturn.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeOptions.md +1 -1
- package/docs/api/interfaces/UseResolvedScopeReturn.md +1 -1
- package/docs/api/interfaces/UserEventAccess.md +1 -1
- package/docs/api/interfaces/UserMenuProps.md +1 -1
- package/docs/api/interfaces/UserProfile.md +1 -1
- package/docs/api/modules.md +105 -19
- package/docs/api-reference/components.md +146 -1
- package/docs/best-practices/common-patterns.md +26 -8
- package/docs/getting-started/examples/README.md +10 -26
- package/docs/getting-started/quick-reference.md +23 -0
- package/docs/implementation-guides/authentication.md +39 -16
- package/docs/implementation-guides/file-reference-system.md +15 -0
- package/docs/implementation-guides/file-upload-storage.md +16 -0
- package/package.json +1 -1
- package/src/components/DataTable/__tests__/DataTableCore.test.tsx +9 -7
- package/src/components/DataTable/components/DataTableCore.tsx +8 -1
- package/src/components/DataTable/components/EditableRow.tsx +62 -22
- package/src/components/DataTable/components/UnifiedTableBody.tsx +25 -101
- package/src/components/FileDisplay/FileDisplay.test.tsx +263 -39
- package/src/components/FileDisplay/FileDisplay.tsx +605 -83
- package/src/components/ProtectedRoute/README.md +164 -0
- package/src/components/PublicLayout/EventLogo.tsx +8 -2
- package/src/components/PublicLayout/PublicPageHeader.tsx +20 -18
- package/src/components/PublicLayout/__tests__/PublicPageHeader.test.tsx +75 -29
- package/src/components/Select/Select.test.tsx +83 -6
- package/src/components/Select/Select.tsx +236 -16
- package/src/examples/CorrectPublicPageImplementation.tsx +16 -13
- package/src/examples/PublicEventPage.tsx +9 -6
- package/src/examples/PublicPageApp.tsx +9 -6
- package/src/examples/PublicPageUsageExample.tsx +9 -7
- package/src/hooks/index.ts +4 -0
- package/src/hooks/public/index.ts +2 -0
- package/src/hooks/public/usePublicFileDisplay.ts +355 -0
- package/src/hooks/useFileDisplay.ts +370 -0
- package/src/services/AuthService.ts +19 -22
- package/dist/chunk-5LAY74WM.js.map +0 -1
- package/dist/chunk-AAM57AEU.js.map +0 -1
- package/dist/chunk-M52CQP5W.js.map +0 -1
- /package/dist/{DataTable-HC5S4RKB.js.map → DataTable-CHX2EFO3.js.map} +0 -0
- /package/dist/{UnifiedAuthProvider-ZM7VUC45.js.map → UnifiedAuthProvider-H7RI4KYD.js.map} +0 -0
- /package/dist/{chunk-AZ2QJYKU.js.map → chunk-2KLAOD4M.js.map} +0 -0
- /package/dist/{chunk-HW5BGOWB.js.map → chunk-2ZYHCFUO.js.map} +0 -0
- /package/dist/{chunk-XIBSVWJW.js.map → chunk-7TQDRDSM.js.map} +0 -0
- /package/dist/{chunk-GP3HU6WS.js.map → chunk-G7UUVEAP.js.map} +0 -0
- /package/dist/{chunk-OXFOS62D.js.map → chunk-MVNOAHOP.js.map} +0 -0
- /package/dist/{chunk-AYC2P377.js.map → chunk-ORACUZ7H.js.map} +0 -0
- /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-
|
|
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
|
-
|
|
36
|
-
extractFileMetadata,
|
|
35
|
+
createFileReferenceService,
|
|
37
36
|
getPublicUrl,
|
|
38
37
|
getSignedUrl,
|
|
39
38
|
init_OrganisationProvider,
|
|
40
|
-
|
|
39
|
+
uploadFileWithReference,
|
|
41
40
|
useAppConfig,
|
|
41
|
+
useFileDisplay,
|
|
42
42
|
useIsPublicPage,
|
|
43
43
|
usePublicEventLogo,
|
|
44
|
+
usePublicFileDisplay,
|
|
44
45
|
usePublicPageContext
|
|
45
|
-
} from "./chunk-
|
|
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-
|
|
53
|
+
} from "./chunk-MVNOAHOP.js";
|
|
53
54
|
import {
|
|
54
55
|
UnifiedAuthProvider_exports,
|
|
55
56
|
init_UnifiedAuthProvider as init_UnifiedAuthProvider2
|
|
56
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
}, [
|
|
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
|
|
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
|
-
|
|
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 [
|
|
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(
|
|
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
|
-
|
|
3346
|
-
setLoadingUrls(/* @__PURE__ */ new Set());
|
|
3041
|
+
setInternalFileUrls(/* @__PURE__ */ new Map());
|
|
3347
3042
|
}
|
|
3348
3043
|
}, [fileReferences]);
|
|
3349
3044
|
useEffect7(() => {
|
|
3350
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
3415
|
-
|
|
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
|
|
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 =
|
|
3515
|
-
const isLoadingUrl =
|
|
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: () =>
|
|
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
|
-
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
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
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
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
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3315
|
+
}, [category, table_name, record_id, organisation_id, supabase, getFilesByCategory]);
|
|
3316
|
+
useEffect7(() => {
|
|
3317
|
+
if (!category) {
|
|
3318
|
+
loadFileCount();
|
|
3319
|
+
loadFileReferences();
|
|
3607
3320
|
}
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
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
|
|
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__ */
|
|
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__ */
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
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
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
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__ */
|
|
3927
|
+
/* @__PURE__ */ jsx24("div", { className: "pb-4", children: /* @__PURE__ */ jsxs19("div", { className: "text-center", children: [
|
|
4088
3928
|
event && /* @__PURE__ */ jsxs19(Fragment6, { children: [
|
|
4089
|
-
/* @__PURE__ */
|
|
4090
|
-
event.event_venue && /* @__PURE__ */
|
|
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__ */
|
|
4094
|
-
description && /* @__PURE__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
4115
|
-
logo && /* @__PURE__ */
|
|
4116
|
-
children && /* @__PURE__ */
|
|
4117
|
-
/* @__PURE__ */
|
|
4118
|
-
links && links.length > 0 && /* @__PURE__ */
|
|
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
|
|
4124
|
-
var
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
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__ */
|
|
3998
|
+
/* @__PURE__ */ jsx26("span", { className: "sr-only", children: displayMessage })
|
|
4159
3999
|
] }),
|
|
4160
|
-
displayMessage && /* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4173
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4182
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4193
|
-
/* @__PURE__ */
|
|
4194
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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
|
|
4213
|
-
import { jsx as
|
|
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 =
|
|
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__ */
|
|
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__ */
|
|
4239
|
-
/* @__PURE__ */
|
|
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__ */
|
|
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__ */
|
|
4257
|
-
/* @__PURE__ */
|
|
4258
|
-
/* @__PURE__ */
|
|
4259
|
-
/* @__PURE__ */
|
|
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__ */
|
|
4270
|
-
customHeader || /* @__PURE__ */
|
|
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__ */
|
|
4278
|
-
showFooter && (customFooter || /* @__PURE__ */
|
|
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
|
|
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__ */
|
|
4351
|
-
/* @__PURE__ */
|
|
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
|
|
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__ */
|
|
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__ */
|
|
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
|
|
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__ */
|
|
4561
|
-
/* @__PURE__ */
|
|
4562
|
-
/* @__PURE__ */
|
|
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-
|
|
4717
|
+
//# sourceMappingURL=chunk-O6GASC4Q.js.map
|