"use client"; // Pflege der globalen Allergen-/Zusatzstofflisten, die unterhalb // der öffentlichen Speisekarte angezeigt werden. import { useCallback, useEffect, useState } from "react"; import { formatMessage } from "@/lib/i18n/shared"; import { localized } from "@/lib/types"; import type { CodeItem } from "@/lib/types"; import { useDict, useLocale } from "@/components/i18n/LocaleProvider"; export default function CodeListManager({ table, translateEnabled, }: { table: "allergens" | "additives"; translateEnabled: boolean; }) { const dict = useDict(); const locale = useLocale(); const title = table === "allergens" ? dict.codeList.allergensTitle : dict.codeList.additivesTitle; const codeLabel = table === "allergens" ? dict.codeList.allergenCodeLabel : dict.codeList.additiveCodeLabel; const [items, setItems] = useState([]); const [editing, setEditing] = useState<{ original: string | null; // code vor der Bearbeitung, null = neu code: string; name: string; nameEn: string; namePl: string; } | null>(null); const [error, setError] = useState(null); const [translateState, setTranslateState] = useState<"idle" | "busy" | "done">( "idle" ); const load = useCallback(async () => { const res = await fetch(`/api/${table}`); if (!res.ok) setError(formatMessage(dict.codeList.loadError, { message: String(res.status) })); else setItems(await res.json()); }, [table, dict]); useEffect(() => { load(); }, [load]); async function save(e: React.FormEvent) { e.preventDefault(); if (!editing) return; setError(null); const code = editing.code.trim(); const name = editing.name.trim(); if (!code || !name) return; const payload = { code, name, name_en: editing.nameEn.trim() || null, name_pl: editing.namePl.trim() || null, }; const res = editing.original ? await fetch(`/api/${table}/${editing.original}`, { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), }) : await fetch(`/api/${table}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), }); if (!res.ok) { const data = await res.json().catch(() => ({})); setError( data.error === "duplicate_code" ? formatMessage(dict.codeList.duplicateCode, { code }) : formatMessage(dict.codeList.saveError, { message: data.error ?? String(res.status) }) ); return; } setEditing(null); await load(); } async function remove(item: CodeItem) { if ( !window.confirm( formatMessage(dict.codeList.confirmDelete, { code: item.code, name: item.name }) ) ) return; const res = await fetch(`/api/${table}/${item.code}`, { method: "DELETE" }); if (!res.ok) setError(formatMessage(dict.codeList.deleteError, { message: String(res.status) })); await load(); } async function autoTranslate() { if (!editing || !editing.name.trim()) return; setTranslateState("busy"); setError(null); try { const res = await fetch("/api/translate", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ table, id: editing.original, text: editing.name.trim(), }), }); const data = await res.json(); if (!res.ok) throw new Error(data?.error ?? `Fehler (${res.status})`); setEditing((prev) => prev ? { ...prev, nameEn: data.en ?? prev.nameEn, namePl: data.pl ?? prev.namePl } : prev ); setTranslateState("done"); } catch (err) { setError(err instanceof Error ? err.message : String(err)); setTranslateState("idle"); } } return (

{title}

{error && (

{error}

)} {editing && (
setEditing({ ...editing, code: e.target.value })} required />
setEditing({ ...editing, name: e.target.value })} required />
setEditing({ ...editing, nameEn: e.target.value })} />
setEditing({ ...editing, namePl: e.target.value })} />
{translateEnabled && (
{translateState === "done" && ( {dict.dishManager.translated} )}
)}
)}
    {items.map((item) => (
  • {item.code} –{" "} {localized(item, locale)}
  • ))} {items.length === 0 && (
  • {dict.codeList.empty}
  • )}
); }