From b63a8774c4b44733b903736b2ca5a472a884055e Mon Sep 17 00:00:00 2001 From: Paul Nothaft Date: Mon, 27 Apr 2026 16:49:50 +0200 Subject: [PATCH] fix: theme-preset match loop ignores extra fields like logoUrl (#323) The "which preset does this saved theme match?" loop in BrandingPage and CreateEventPage was doing a full JSON.stringify equality on preset.config vs the loaded theme. The previous #323 logo-preservation work means the saved theme legitimately carries a `logoUrl` (and any other fields the parent maintains), so the equality check would never match and the preset summary fell back to "Custom Theme" / Classic Grid even when the saved theme was structurally Dark Modern, etc. Compare only on the preset's own keys instead. Surfaced by the new smoke spec 07-branding-default-on-create-event which would otherwise pass green against the broken state. --- frontend/src/pages/admin/BrandingPage.tsx | 11 +++++++++-- frontend/src/pages/admin/CreateEventPage.tsx | 11 ++++++++--- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/frontend/src/pages/admin/BrandingPage.tsx b/frontend/src/pages/admin/BrandingPage.tsx index fc26fd6d..2e6c84b9 100644 --- a/frontend/src/pages/admin/BrandingPage.tsx +++ b/frontend/src/pages/admin/BrandingPage.tsx @@ -106,9 +106,16 @@ export const BrandingPage: React.FC = () => { setBrandingSettings(prev => ({ ...prev, logo_url: formatted.logoUrl })); } - // Try to identify which preset this matches + // Try to identify which preset this matches. Compare only on the + // fields the preset itself defines so saved themes carrying extras + // like a `logoUrl` (preserved through preset changes — see + // handlePresetChange) still match the original preset shape. for (const [key, preset] of Object.entries(GALLERY_THEME_PRESETS)) { - if (JSON.stringify(preset.config) === JSON.stringify(formatted)) { + const keys = Object.keys(preset.config); + const matches = keys.every((k) => + JSON.stringify((preset.config as any)[k]) === JSON.stringify((formatted as any)[k]) + ); + if (matches) { setCurrentThemeName(key); break; } diff --git a/frontend/src/pages/admin/CreateEventPage.tsx b/frontend/src/pages/admin/CreateEventPage.tsx index b96c29b3..11d59417 100644 --- a/frontend/src/pages/admin/CreateEventPage.tsx +++ b/frontend/src/pages/admin/CreateEventPage.tsx @@ -213,11 +213,16 @@ export const CreateEventPage: React.FC = () => { if (!brandingTheme || Object.keys(brandingTheme).length === 0) return; brandingThemeApplied.current = true; - // Identify which preset (if any) the Branding theme matches, so the - // "Theme & Style" panel shows the right name. + // Identify which preset (if any) the Branding theme matches. Compare + // only on the preset's own fields so saved themes carrying extras + // (e.g. logoUrl preserved through preset changes) still match. let matchedPreset = 'custom'; for (const [key, preset] of Object.entries(GALLERY_THEME_PRESETS)) { - if (JSON.stringify(preset.config) === JSON.stringify(brandingTheme)) { + const keys = Object.keys(preset.config); + const matches = keys.every((k) => + JSON.stringify((preset.config as any)[k]) === JSON.stringify((brandingTheme as any)[k]) + ); + if (matches) { matchedPreset = key; break; }