"use client"; import { useState, useCallback } from "react"; import type { ReactElement } from "react"; import Link from "next/link"; import { useTheme } from "@/providers/ThemeProvider"; import { getAllThemes, type ThemeDefinition } from "@/themes"; import { apiPatch } from "@/lib/api/client"; function ThemeCard({ theme, isActive, onSelect, }: { theme: ThemeDefinition; isActive: boolean; onSelect: () => void; }): ReactElement { const [hovered, setHovered] = useState(false); return ( ); } function SystemThemeCard({ isActive, onSelect, }: { isActive: boolean; onSelect: () => void; }): ReactElement { const [hovered, setHovered] = useState(false); return ( ); } export default function AppearanceSettingsPage(): ReactElement { const { theme: preference, setTheme: setLocalTheme } = useTheme(); const [saving, setSaving] = useState(false); const allThemes = getAllThemes(); const handleThemeSelect = useCallback( async (themeId: string) => { setLocalTheme(themeId); setSaving(true); try { await apiPatch("/api/users/me/preferences", { theme: themeId }); } catch { // Theme is still applied locally even if API save fails } finally { setSaving(false); } }, [setLocalTheme] ); return (
{/* Breadcrumb */}
Settings / Appearance
{/* Page header */}

Appearance

Choose a theme for the Mosaic interface {saving && ( Saving... )}

{/* Theme grid */}
{/* System option first */} void handleThemeSelect("system")} /> {/* All registered themes */} {allThemes.map((t) => ( void handleThemeSelect(t.id)} /> ))}
); }