import { deriveAccentTokens, THEME_PRESETS, type PondTheme } from '@dorfteich/shared'; import { useQueryClient } from '@tanstack/react-query'; import { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { FormError } from '../components/forms'; import { apiPatch } from '../lib/api'; import { AccentSwatches } from './AccentSwatches'; /** * Pond accent setting (issue #186, ADR 0018 stage C): inherit | preset | * custom color, applied to the pond's content via PondThemeScope. Explicit * save like the font manager (AppearanceManager); Pond-Admin-gated by the * api's PATCH guard. Presets here include the default green — unlike the * user setting, picking it PINS the pond to green for every viewer. */ export function PondThemeSection({ pondId, pondSlug, theme, }: { pondId: string; pondSlug: string; theme: PondTheme; }): React.JSX.Element { const { t } = useTranslation('font'); const { t: tSettings } = useTranslation('settings'); const queryClient = useQueryClient(); const [accent, setAccent] = useState(theme.accent); const [status, setStatus] = useState<'idle' | 'saving' | 'saved'>('idle'); const [error, setError] = useState(null); const presetHexes = THEME_PRESETS.map((preset) => preset.accent); const isCustom = accent !== null && !presetHexes.includes(accent); const [customHex, setCustomHex] = useState(isCustom ? accent : '#2f6f4f'); const choose = (value: string | null): void => { setAccent(value); setStatus('idle'); }; const derivedPair = (hex: string): { light: string; dark: string } => ({ light: deriveAccentTokens(hex, 'light').accent, dark: deriveAccentTokens(hex, 'dark').accent, }); async function save(): Promise { setStatus('saving'); setError(null); try { await apiPatch(`/ponds/${pondId}`, { theme: { accent } }); await queryClient.invalidateQueries({ queryKey: ['pond', pondSlug] }); setStatus('saved'); } catch (err) { setError(err); setStatus('idle'); } } return (
{t('pondTheme.legend')} {THEME_PRESETS.map((preset) => ( ))}
choose(customHex)} /> { setCustomHex(event.target.value); choose(event.target.value); }} /> {isCustom && }

{t('pondTheme.hint')}

); }