"use client"; import { useCallback, useEffect, useState } from "react"; import Link from "next/link"; import { addDays, dishCodes, entriesFor, formatDateLong, formatPrice, mondayOf, todayISO, weekdayIndex, } from "@/lib/menu"; import { formatMessage } from "@/lib/i18n/shared"; import { localized } from "@/lib/types"; import type { Dish, MenuEntry, Section } from "@/lib/types"; import { useDict, useLocale } from "@/components/i18n/LocaleProvider"; export default function WeekEditor({ monday }: { monday: string }) { const dict = useDict(); const locale = useLocale(); const friday = addDays(monday, 4); const days = dict.weekdays.long.map((weekday, i) => ({ weekday, short: dict.weekdays.short[i], iso: addDays(monday, i), })); const isCurrentWeek = monday === mondayOf(todayISO()); const todayIdx = isCurrentWeek ? weekdayIndex(todayISO()) : -1; const [sections, setSections] = useState([]); const [dishes, setDishes] = useState([]); const [entries, setEntries] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // Zelle, in der gerade ein Gericht hinzugefügt wird const [adding, setAdding] = useState<{ iso: string; section: string } | null>( null ); const [selectedDish, setSelectedDish] = useState(""); const [dishSearch, setDishSearch] = useState(""); // Mobil: ein Tag auf einmal statt aller fünf gleichzeitig const [selectedDayIdx, setSelectedDayIdx] = useState(todayIdx >= 0 ? todayIdx : 0); function startAdding(iso: string, section: string) { setAdding({ iso, section }); setSelectedDish(""); setDishSearch(""); } function cancelAdding() { setAdding(null); setSelectedDish(""); setDishSearch(""); } const load = useCallback(async () => { setError(null); const [se, di, en] = await Promise.all([ fetch("/api/sections"), fetch("/api/dishes"), fetch(`/api/menu-entries?from=${monday}&to=${friday}`), ]); if (!se.ok || !di.ok || !en.ok) { setError(formatMessage(dict.weekEditor.loadError, { message: "load failed" })); } else { setSections(await se.json()); setDishes(await di.json()); setEntries(await en.json()); } setLoading(false); }, [monday, friday, dict]); useEffect(() => { setLoading(true); load(); }, [load]); async function addEntry() { if (!adding || !selectedDish) return; const res = await fetch("/api/menu-entries", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ menu_date: adding.iso, section_key: adding.section, dish_id: selectedDish, }), }); if (!res.ok) { const data = await res.json().catch(() => ({})); setError( data.error === "duplicate_entry" ? dict.weekEditor.duplicateEntry : formatMessage(dict.weekEditor.saveError, { message: data.error ?? String(res.status) }) ); } cancelAdding(); await load(); } async function removeEntry(id: string) { const res = await fetch(`/api/menu-entries/${id}`, { method: "DELETE" }); if (!res.ok) setError(formatMessage(dict.weekEditor.deleteError, { message: String(res.status) })); await load(); } const [hintBefore, hintAfter] = dict.weekEditor.newDishesHint.split("{link}"); const selectedDishObj = dishes.find((d) => d.id === selectedDish) ?? null; const query = dishSearch.trim().toLowerCase(); const filteredDishes = query ? dishes.filter((d) => localized(d, locale).toLowerCase().includes(query)) : dishes; // Inhalt einer Tag/Essenszeit-Zelle: Eintragsliste + "hinzufügen"-Flow. // Identisches Fragment für Desktop-Tabelle und Mobile-Karten, damit der // Bearbeitungs-Zustand (adding/selectedDish/dishSearch) nicht dupliziert // werden muss – nur eine Zelle kann gleichzeitig bearbeitet werden, // unabhängig davon, welche Ansicht gerade rendert. function renderCell(iso: string, sectionKey: string) { const isAdding = adding?.iso === iso && adding?.section === sectionKey; return ( <> {entriesFor(entries, iso, sectionKey).map((e) => { const codes = dishCodes(e.dish); return (
{localized(e.dish, locale)} {codes && {codes}} {" – "} {formatPrice(e.dish.price)}
); })} {isAdding ? (
{selectedDishObj ? (
{localized(selectedDishObj, locale)} ( {formatPrice(selectedDishObj.price)})
) : ( <> setDishSearch(e.target.value)} />
    {filteredDishes.map((dish) => (
  • ))} {filteredDishes.length === 0 && (
  • {formatMessage(dict.dishManager.noResults, { query: dishSearch, })}
  • )}
)}
) : ( )} ); } const selectedDay = days[selectedDayIdx]; return (

{dict.weekEditor.title}

{dict.publicMenu.prevWeek} {dict.publicMenu.today} {dict.publicMenu.nextWeek}
{error && (

{error}

)} {loading ? (

{dict.weekEditor.loading}

) : ( <> {/* Mobil (< "sm"): ein Tag auf einmal, per Tabs gewählt */}
{days.map((d, i) => ( ))}

{selectedDay.weekday} · {formatDateLong(selectedDay.iso, dict.dateLocale)}

{sections.map((s) => (
{localized(s, locale)}{" "} · {s.time_range}
{renderCell(selectedDay.iso, s.key)}
))}
{/* Ab "sm": klassische Wochentabelle */}
))} {sections.map((s) => ( {days.map((d) => ( ))} ))}
{days.map((d) => ( {d.weekday}
{formatDateLong(d.iso, dict.dateLocale)}
{localized(s, locale)}
{s.time_range}
{renderCell(d.iso, s.key)}
)}

{hintBefore} {dict.weekEditor.newDishesLinkLabel} {hintAfter}

); }