"use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import { useRouter } from "next/navigation"; import { createClient } from "@/lib/supabase/client"; import { COLOR_LABELS, DEFAULT_COLORS, logoUrl } from "@/lib/types"; export default function DesignEditor() { const supabase = useMemo(() => createClient(), []); const router = useRouter(); const [colors, setColors] = useState>(DEFAULT_COLORS); const [logoPath, setLogoPath] = useState(null); const [error, setError] = useState(null); const [info, setInfo] = useState(null); const [busy, setBusy] = useState(false); const load = useCallback(async () => { const { data, error } = await supabase .from("settings") .select("colors, logo_path") .eq("id", 1) .maybeSingle(); if (error) { setError(`Laden fehlgeschlagen: ${error.message}`); return; } setColors({ ...DEFAULT_COLORS, ...(data?.colors ?? {}) }); setLogoPath(data?.logo_path ?? null); }, [supabase]); useEffect(() => { load(); }, [load]); async function saveColors() { setBusy(true); setError(null); setInfo(null); const { error } = await supabase .from("settings") .update({ colors }) .eq("id", 1); if (error) setError(`Speichern fehlgeschlagen: ${error.message}`); else { setInfo("Farben gespeichert."); router.refresh(); } setBusy(false); } async function resetColors() { setColors(DEFAULT_COLORS); } async function uploadLogo(e: React.ChangeEvent) { const file = e.target.files?.[0]; e.target.value = ""; if (!file) return; if (!/^image\//.test(file.type)) { setError("Bitte eine Bilddatei auswählen (PNG, JPG, SVG, WebP)."); return; } setBusy(true); setError(null); setInfo(null); const ext = file.name.split(".").pop()?.toLowerCase() ?? "png"; const path = `logo-${Date.now()}.${ext}`; const { error: uploadError } = await supabase.storage .from("branding") .upload(path, file, { contentType: file.type }); if (uploadError) { setError(`Upload fehlgeschlagen: ${uploadError.message}`); setBusy(false); return; } const oldPath = logoPath; const { error: settingsError } = await supabase .from("settings") .update({ logo_path: path }) .eq("id", 1); if (settingsError) { setError(`Speichern fehlgeschlagen: ${settingsError.message}`); setBusy(false); return; } if (oldPath) { await supabase.storage.from("branding").remove([oldPath]); } setLogoPath(path); setInfo("Logo aktualisiert."); router.refresh(); setBusy(false); } async function removeLogo() { if (!logoPath) return; if (!window.confirm("Logo wirklich entfernen?")) return; setBusy(true); setError(null); const { error } = await supabase .from("settings") .update({ logo_path: null }) .eq("id", 1); if (error) { setError(`Speichern fehlgeschlagen: ${error.message}`); } else { await supabase.storage.from("branding").remove([logoPath]); setLogoPath(null); setInfo("Logo entfernt."); router.refresh(); } setBusy(false); } const currentLogo = logoUrl(logoPath); return (

Design

{error && (

{error}

)} {info &&

{info}

}

Logo

Das Logo wird zentriert über der Speisekarte angezeigt.

{currentLogo ? ( // eslint-disable-next-line @next/next/no-img-element Aktuelles Logo ) : (

Kein Logo hinterlegt.

)}
{currentLogo && ( )}

Farbgebung

{Object.entries(COLOR_LABELS).map(([key, label]) => ( ))}
); }