Files
EventSnap/frontend/src/lib/event-config-store.ts
MechaCat02 57a907eca5 feat(theme+comments): runtime colour theme and COMMENTS_ENABLED switch
Colour theme is configurable at runtime from two seed colours (brand + accent);
neutrals stay fixed for contrast safety. Tailwind v4 var()-based tokens let a
:root:root override recolour everything with no rebuild; the 50->950 ramps are
derived via a color-mix ladder. Config lives in the DB config table (admin UI:
Config > Farbschema, presets + custom pickers + live preview), served on the public
/event endpoint with env defaults (THEME_PRESET/PRIMARY/ACCENT), propagated live via
event-updated SSE, and cached in localStorage for a no-flash boot. The keepsake export
mirrors the same ladder in Rust so offline archives match the event theme.

COMMENTS_ENABLED (env, default true) is a boot-time kill-switch: the backend rejects
new comments with 403 and the frontend hides the comment button (feed card) and
panel/composer (lightbox). Existing comments stay in the DB, hidden, and return when
re-enabled.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 15:21:55 +02:00

61 lines
2.0 KiB
TypeScript

/**
* Public event presentation config: the colour theme and the comments feature flag,
* served unauthenticated from `GET /api/v1/event`. Loaded once on boot (and refreshed
* on the `event-updated` SSE) so the theme applies before the user has even joined and
* the comment UI reflects the instance setting.
*
* The resolved theme CSS is cached in localStorage so the boot script in app.html can
* paint the right colours before the JS bundle loads (no flash of the default palette).
*/
import { writable } from 'svelte/store';
import { buildPaletteCss, applyPaletteCss, type ThemeConfig } from './theme/palette';
export const PALETTE_CACHE_KEY = 'eventsnap_palette_css';
export type EventConfig = {
name: string;
slug: string;
commentsEnabled: boolean;
theme: ThemeConfig;
};
export const eventConfig = writable<EventConfig | null>(null);
/** Convenience flag for the comment UI. Optimistic `true` until /event resolves. */
export const commentsEnabled = writable<boolean>(true);
/** Fetch /event, apply the theme, and cache the resolved CSS for the next boot. */
export async function loadEventConfig(): Promise<void> {
try {
const res = await fetch('/api/v1/event');
if (!res.ok) return;
const b = await res.json();
const theme: ThemeConfig = {
preset: b.theme_preset ?? 'champagne-gold',
primary: b.theme_primary ?? '#8a6a2b',
accent: b.theme_accent ?? '#8a6a2b'
};
eventConfig.set({
name: b.name,
slug: b.slug,
commentsEnabled: b.comments_enabled ?? true,
theme
});
commentsEnabled.set(b.comments_enabled ?? true);
const css = buildPaletteCss(theme);
applyPaletteCss(css);
try {
localStorage.setItem(PALETTE_CACHE_KEY, css);
} catch {
/* private mode / quota — the theme still applied for this session */
}
} catch {
/* offline / server down — keep whatever the boot script already painted */
}
}
/** Apply a theme immediately without persisting — used by the admin live preview. */
export function previewTheme(theme: ThemeConfig): void {
applyPaletteCss(buildPaletteCss(theme));
}