import Link from "next/link"; import { query } from "@/lib/db"; import { loadMenuEntries } from "@/lib/db/menu-entries"; import { getSettings } from "@/lib/db/settings"; import { addDays, dishCodes, entriesFor, formatDateLong, formatPrice, mondayOf, todayISO, } from "@/lib/menu"; import { getDictionary, getLocale } from "@/lib/i18n"; import { localized, logoUrl, SITE_TITLE } from "@/lib/types"; import type { CodeItem, Section } from "@/lib/types"; import PublicMobileMenu from "@/components/PublicMobileMenu"; import LanguageSwitcher from "@/components/i18n/LanguageSwitcher"; export default async function Home({ searchParams, }: { searchParams: Promise<{ woche?: string }>; }) { const { woche } = await searchParams; const monday = mondayOf(woche); const friday = addDays(monday, 4); const currentWeek = mondayOf(todayISO()); const locale = await getLocale(); const dict = getDictionary(locale); const days = dict.weekdays.long.map((weekday, i) => ({ weekday, iso: addDays(monday, i), })); const [sections, entries, allergens, additives, settings] = await Promise.all([ query
("select * from sections order by sort"), loadMenuEntries(monday, friday), query("select * from allergens order by sort"), query("select * from additives order by sort"), getSettings(), ]); const logo = logoUrl(settings?.logo_path); const labelingDetailed = (settings?.labeling_mode ?? "detailed") !== "notice"; return (
{/* Kopfbereich: Sprache + Login-Link eigene Zeile, Logo zentriert darunter. Kein absolutes Positionieren mehr – ein breites Logo (z. B. ein Banner-Format) konnte sonst mit dem Login-Link kollidieren. */}
{/* Auf Mobilgeräten übernimmt PublicMobileMenu den Sprachumschalter, hier würde er sonst doppelt erscheinen. */}
{dict.common.login}
{logo ? ( // eslint-disable-next-line @next/next/no-img-element Logo ) : (

{SITE_TITLE}

)}
{/* Mobil: Tag (Standard) oder Woche umschaltbar */} {/* Ab "sm": klassische Wochentabelle */}
{dict.publicMenu.prevWeek} {dict.publicMenu.today} {dict.publicMenu.nextWeek} {dict.publicMenu.suggestDish}
))} {sections.map((s) => ( {days.map((d) => ( ))} ))}
{days.map((d) => ( {d.weekday}
{formatDateLong(d.iso, dict.dateLocale)}
{localized(s, locale)}
{s.time_range}
{entriesFor(entries, d.iso, s.key).map((e) => { const codes = dishCodes(e.dish); return (
{localized(e.dish, locale)} {labelingDetailed && codes && ( {codes} )} {" – "} {formatPrice(e.dish.price)}
); })}
{/* Allergene & Zusatzstoffe: entweder Legende zu den Kürzeln bei den Gerichten, oder – falls im Hinweismodus – nur ein Hinweistext. */} {labelingDetailed ? (

{dict.publicMenu.allergens}

    {allergens.map((a) => (
  • {a.code} –{" "} {localized(a, locale)}
  • ))}

{dict.publicMenu.additives}

    {additives.map((a) => (
  • {a.code} –{" "} {localized(a, locale)}
  • ))}
) : ( settings && (

{dict.publicMenu.labelingNoticeTitle}

{localized( { name: settings.labeling_notice, name_en: settings.labeling_notice_en, name_pl: settings.labeling_notice_pl, }, locale )}

) )}
); }