"use client"; import { useCallback, useEffect, useMemo, useState } from "react"; import { createClient } from "@/lib/supabase/client"; import { formatPrice } from "@/lib/menu"; import type { Dish } from "@/lib/types"; interface DishForm { id: string | null; // null = neues Gericht name: string; price: string; } const EMPTY_FORM: DishForm = { id: null, name: "", price: "" }; export default function DishManager() { const supabase = useMemo(() => createClient(), []); const [dishes, setDishes] = useState([]); const [form, setForm] = useState(null); const [error, setError] = useState(null); const [loading, setLoading] = useState(true); const [selected, setSelected] = useState>(new Set()); const [bulkBusy, setBulkBusy] = useState(false); const load = useCallback(async () => { const { data, error } = await supabase .from("dishes") .select("*") .order("name"); if (error) setError(`Laden fehlgeschlagen: ${error.message}`); else setDishes(data as Dish[]); setLoading(false); }, [supabase]); useEffect(() => { load(); }, [load]); async function save(e: React.FormEvent) { e.preventDefault(); if (!form) return; setError(null); const price = Number.parseFloat(form.price.replace(",", ".")); if (Number.isNaN(price) || price < 0) { setError("Bitte einen gültigen Preis angeben, z. B. 3,50"); return; } const payload = { name: form.name.trim(), price }; const { error } = form.id ? await supabase.from("dishes").update(payload).eq("id", form.id) : await supabase.from("dishes").insert(payload); if (error) { setError(`Speichern fehlgeschlagen: ${error.message}`); return; } setForm(null); await load(); } async function remove(dish: Dish) { if ( !window.confirm( `„${dish.name}“ wirklich löschen? Das Gericht wird auch aus allen Wochenplänen entfernt.` ) ) return; const { error } = await supabase.from("dishes").delete().eq("id", dish.id); if (error) setError(`Löschen fehlgeschlagen: ${error.message}`); setSelected((prev) => { const next = new Set(prev); next.delete(dish.id); return next; }); await load(); } function toggleOne(id: string) { setSelected((prev) => { const next = new Set(prev); if (next.has(id)) next.delete(id); else next.add(id); return next; }); } function toggleAll() { setSelected((prev) => prev.size === dishes.length ? new Set() : new Set(dishes.map((d) => d.id)) ); } async function removeSelected() { if (selected.size === 0) return; if ( !window.confirm( `${selected.size} Gericht(e) wirklich löschen? Sie werden auch aus allen Wochenplänen entfernt.` ) ) return; setBulkBusy(true); setError(null); const { error } = await supabase .from("dishes") .delete() .in("id", Array.from(selected)); if (error) setError(`Löschen fehlgeschlagen: ${error.message}`); setSelected(new Set()); setBulkBusy(false); await load(); } const allSelected = dishes.length > 0 && selected.size === dishes.length; return (

Gerichte

{error && (

{error}

)} {form && (

{form.id ? "Gericht bearbeiten" : "Neues Gericht"}

setForm({ ...form, name: e.target.value })} required />
setForm({ ...form, price: e.target.value })} required />
)} {loading ? (

Lade Gerichte…

) : ( <> {dishes.length > 0 && (
{selected.size} ausgewählt
)}
    {dishes.map((dish) => (
  • toggleOne(dish.id)} aria-label={`${dish.name} auswählen`} /> {dish.name}{" "} – {formatPrice(dish.price)}
  • ))} {dishes.length === 0 && (
  • Noch keine Gerichte angelegt.
  • )}
)}
); }