"Bereiche" zu "Essenszeiten" umbenannt

Betrifft UI-Texte (DE/EN/PL), Route (/intern/bereiche ->
/intern/essenszeiten), Code-Kommentare, Changelog und README.
Fachlich unverändert (weiterhin die Tabelle/Komponente "sections"/
SectionManager im Code), da "Essenszeiten" den Zeitbezug des Features
klarer ausdrückt als der bisherige Sammelbegriff.
This commit is contained in:
2026-07-18 08:26:15 +02:00
parent d85d2e3fe3
commit 0f20ad6527
9 changed files with 32 additions and 32 deletions
+2 -2
View File
@@ -7,9 +7,9 @@ Versionierung nach [Semantic Versioning](https://semver.org/lang/de/).
## [1.4.0] – 2026-07-18 (Branch `feature/v1.4`, noch nicht gemergt) ## [1.4.0] – 2026-07-18 (Branch `feature/v1.4`, noch nicht gemergt)
### Hinzugefügt ### Hinzugefügt
- Bereiche (Brotzeit/Mittagessen/…) vollständig verwaltbar: anlegen, - Essenszeiten (Brotzeit/Mittagessen/…) vollständig verwaltbar: anlegen,
umbenennen (inkl. EN/PL), Uhrzeit ändern, löschen und per Pfeil-Buttons umbenennen (inkl. EN/PL), Uhrzeit ändern, löschen und per Pfeil-Buttons
neu anordnen – neue Seite „Bereiche" im Kantinen-Bereich. Löschen neu anordnen – neue Seite „Essenszeiten" im Kantinen-Bereich. Löschen
entfernt zugewiesene Gerichte automatisch aus allen Wochenplänen. entfernt zugewiesene Gerichte automatisch aus allen Wochenplänen.
### Geändert ### Geändert
+4 -4
View File
@@ -14,8 +14,8 @@ markieren die jeweiligen Versionsstände (`git tag`).
| Bereich | Funktionen | | Bereich | Funktionen |
| --- | --- | | --- | --- |
| Öffentlich (ohne Login) | Wochenplan Mo–Fr mit den Bereichen Brotzeit (09:00–10:00), Mittagessen, Mittagessen vegetarisch und Suppe (je 11:30–13:30); Navigation vorherige/nächste Woche/Heute; auf schmalen Bildschirmen umschaltbare Tages-/Wochenansicht (Tag ist Standard); Logo zentriert über der Karte; Allergen-/Zusatzstoff-Kürzel je Gericht, Legende unterhalb der Karte; Sprachumschalter Deutsch/Englisch/Polnisch; Rezeptvorschläge einreichen | | Öffentlich (ohne Login) | Wochenplan Mo–Fr mit den Essenszeiten Brotzeit (09:00–10:00), Mittagessen, Mittagessen vegetarisch und Suppe (je 11:30–13:30); Navigation vorherige/nächste Woche/Heute; auf schmalen Bildschirmen umschaltbare Tages-/Wochenansicht (Tag ist Standard); Logo zentriert über der Karte; Allergen-/Zusatzstoff-Kürzel je Gericht, Legende unterhalb der Karte; Sprachumschalter Deutsch/Englisch/Polnisch; Rezeptvorschläge einreichen |
| Kantinen-Team (`/intern`) | Gerichte anlegen/bearbeiten/löschen (inkl. Live-Suche, Mehrfachauswahl zum Batch-Löschen, englischem/polnischem Namen mit automatischer DeepL-Übersetzung) mit Allergenen/Zusatzstoffen je Gericht; Gerichte Tagen/Bereichen zuweisen (mehrere pro Zelle) und wieder entfernen; globale Allergen-/Zusatzstofflisten pflegen (ebenfalls mehrsprachig); eingereichte Rezeptvorschläge sichten, übernehmen oder ablehnen; eigenes Konto verwalten (Name, E-Mail, Passwort, Passkeys, Passwort-Anmeldung an/aus) | | Kantinen-Team (`/intern`) | Gerichte anlegen/bearbeiten/löschen (inkl. Live-Suche, Mehrfachauswahl zum Batch-Löschen, englischem/polnischem Namen mit automatischer DeepL-Übersetzung) mit Allergenen/Zusatzstoffen je Gericht; Gerichte Tagen/Essenszeiten zuweisen (mehrere pro Zelle) und wieder entfernen; globale Allergen-/Zusatzstofflisten pflegen (ebenfalls mehrsprachig); eingereichte Rezeptvorschläge sichten, übernehmen oder ablehnen; eigenes Konto verwalten (Name, E-Mail, Passwort, Passkeys, Passwort-Anmeldung an/aus) |
| Admin (`/admin`) | Kantinenmitarbeiter anlegen/bearbeiten/löschen (inkl. Passwort-Reset mit Wiederholung und Rollenvergabe); Farbgebung der Speisekarte anpassen; Logo und Favicon hochladen/entfernen | | Admin (`/admin`) | Kantinenmitarbeiter anlegen/bearbeiten/löschen (inkl. Passwort-Reset mit Wiederholung und Rollenvergabe); Farbgebung der Speisekarte anpassen; Logo und Favicon hochladen/entfernen |
Anmeldung mit E-Mail + Passwort oder alternativ per **Passkey** Anmeldung mit E-Mail + Passwort oder alternativ per **Passkey**
@@ -24,7 +24,7 @@ Passwort-Anmeldung kann pro Konto deaktiviert werden, sobald mindestens
ein Passkey registriert ist. ein Passkey registriert ist.
Die gesamte Oberfläche ist auf Deutsch, Englisch und Polnisch verfügbar Die gesamte Oberfläche ist auf Deutsch, Englisch und Polnisch verfügbar
(Sprachumschalter, Cookie-basiert). Gerichte, Bereiche, Allergene und (Sprachumschalter, Cookie-basiert). Gerichte, Essenszeiten, Allergene und
Zusatzstoffe lassen sich zusätzlich auf Englisch/Polnisch benennen – Zusatzstoffe lassen sich zusätzlich auf Englisch/Polnisch benennen –
mit optionaler automatischer Übersetzung über DeepL (siehe mit optionaler automatischer Übersetzung über DeepL (siehe
`DEEPL_API_KEY` unten) und jederzeit manuell korrigierbar. `DEEPL_API_KEY` unten) und jederzeit manuell korrigierbar.
@@ -136,7 +136,7 @@ ihre Gültigkeit und müssen neu registriert werden.
Sicherheitsmodell (Row Level Security): Sicherheitsmodell (Row Level Security):
- `anon` darf ausschließlich lesen (Speisekarte, Bereiche, Allergene, - `anon` darf ausschließlich lesen (Speisekarte, Essenszeiten, Allergene,
Zusatzstoffe, Einstellungen). Zusatzstoffe, Einstellungen).
- `staff`/`admin` (Rolle im `profiles`-Eintrag) pflegen Gerichte, - `staff`/`admin` (Rolle im `profiles`-Eintrag) pflegen Gerichte,
Wochenplan und Kennzeichnungen. Wochenplan und Kennzeichnungen.
@@ -1,5 +1,5 @@
import SectionManager from "@/components/SectionManager"; import SectionManager from "@/components/SectionManager";
export default function BereichePage() { export default function EssenszeitenPage() {
return <SectionManager />; return <SectionManager />;
} }
+1 -1
View File
@@ -23,7 +23,7 @@ export default function AppHeader({
const menuLinks = [ const menuLinks = [
{ href: "/intern", label: dict.header.weekPlan }, { href: "/intern", label: dict.header.weekPlan },
{ href: "/intern/bereiche", label: dict.header.sections }, { href: "/intern/essenszeiten", label: dict.header.sections },
{ href: "/intern/gerichte", label: dict.header.dishes }, { href: "/intern/gerichte", label: dict.header.dishes },
{ href: "/intern/kennzeichnung", label: dict.header.labels }, { href: "/intern/kennzeichnung", label: dict.header.labels },
{ href: "/intern/vorschlaege", label: dict.header.suggestions }, { href: "/intern/vorschlaege", label: dict.header.suggestions },
+2 -2
View File
@@ -1,6 +1,6 @@
"use client"; "use client";
// Verwaltung der Speiseplan-Bereiche (Brotzeit, Mittagessen, …): // Verwaltung der Essenszeiten (Brotzeit, Mittagessen, …):
// anlegen, umbenennen, Uhrzeit ändern, löschen, Reihenfolge anpassen. // anlegen, umbenennen, Uhrzeit ändern, löschen, Reihenfolge anpassen.
import { useCallback, useEffect, useMemo, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
@@ -11,7 +11,7 @@ import type { Section } from "@/lib/types";
import { useDict, useLocale } from "@/components/i18n/LocaleProvider"; import { useDict, useLocale } from "@/components/i18n/LocaleProvider";
interface SectionForm { interface SectionForm {
key: string | null; // null = neuer Bereich key: string | null; // null = neue Essenszeit
label: string; label: string;
labelEn: string; labelEn: string;
labelPl: string; labelPl: string;
+15 -15
View File
@@ -30,7 +30,7 @@ const de = {
canteen: "Kantine", canteen: "Kantine",
menuGroup: "Speiseplan", menuGroup: "Speiseplan",
weekPlan: "Wochenplan", weekPlan: "Wochenplan",
sections: "Bereiche", sections: "Essenszeiten",
dishes: "Gerichte", dishes: "Gerichte",
labels: "Allergene & Zusatzstoffe", labels: "Allergene & Zusatzstoffe",
adminGroup: "Verwaltung", adminGroup: "Verwaltung",
@@ -120,9 +120,9 @@ const de = {
deleteError: "Löschen fehlgeschlagen: {message}", deleteError: "Löschen fehlgeschlagen: {message}",
}, },
sectionManager: { sectionManager: {
title: "Bereiche", title: "Essenszeiten",
newSection: "Neuer Bereich", newSection: "Neue Essenszeit",
editSection: "Bereich bearbeiten", editSection: "Essenszeit bearbeiten",
nameLabel: "Bezeichnung", nameLabel: "Bezeichnung",
nameEnLabel: "Bezeichnung (Englisch)", nameEnLabel: "Bezeichnung (Englisch)",
namePlLabel: "Bezeichnung (Polnisch)", namePlLabel: "Bezeichnung (Polnisch)",
@@ -130,7 +130,7 @@ const de = {
timeTo: "Bis", timeTo: "Bis",
moveUp: "Nach oben", moveUp: "Nach oben",
moveDown: "Nach unten", moveDown: "Nach unten",
empty: "Noch keine Bereiche angelegt.", empty: "Noch keine Essenszeiten angelegt.",
confirmDelete: confirmDelete:
"„{name}“ wirklich löschen? Zugewiesene Gerichte werden auch aus allen Wochenplänen entfernt.", "„{name}“ wirklich löschen? Zugewiesene Gerichte werden auch aus allen Wochenplänen entfernt.",
loadError: "Laden fehlgeschlagen: {message}", loadError: "Laden fehlgeschlagen: {message}",
@@ -286,7 +286,7 @@ const en: Dict = {
canteen: "Canteen", canteen: "Canteen",
menuGroup: "Menu", menuGroup: "Menu",
weekPlan: "Weekly plan", weekPlan: "Weekly plan",
sections: "Sections", sections: "Meal times",
dishes: "Dishes", dishes: "Dishes",
labels: "Allergens & Additives", labels: "Allergens & Additives",
adminGroup: "Administration", adminGroup: "Administration",
@@ -376,9 +376,9 @@ const en: Dict = {
deleteError: "Deleting failed: {message}", deleteError: "Deleting failed: {message}",
}, },
sectionManager: { sectionManager: {
title: "Sections", title: "Meal times",
newSection: "New section", newSection: "New meal time",
editSection: "Edit section", editSection: "Edit meal time",
nameLabel: "Name", nameLabel: "Name",
nameEnLabel: "Name (English)", nameEnLabel: "Name (English)",
namePlLabel: "Name (Polish)", namePlLabel: "Name (Polish)",
@@ -386,7 +386,7 @@ const en: Dict = {
timeTo: "To", timeTo: "To",
moveUp: "Move up", moveUp: "Move up",
moveDown: "Move down", moveDown: "Move down",
empty: "No sections yet.", empty: "No meal times yet.",
confirmDelete: confirmDelete:
"Really delete “{name}”? Assigned dishes will also be removed from all weekly plans.", "Really delete “{name}”? Assigned dishes will also be removed from all weekly plans.",
loadError: "Loading failed: {message}", loadError: "Loading failed: {message}",
@@ -540,7 +540,7 @@ const pl: Dict = {
canteen: "Stołówka", canteen: "Stołówka",
menuGroup: "Jadłospis", menuGroup: "Jadłospis",
weekPlan: "Plan tygodnia", weekPlan: "Plan tygodnia",
sections: "Sekcje", sections: "Pory posiłków",
dishes: "Dania", dishes: "Dania",
labels: "Alergeny i dodatki", labels: "Alergeny i dodatki",
adminGroup: "Administracja", adminGroup: "Administracja",
@@ -630,9 +630,9 @@ const pl: Dict = {
deleteError: "Usuwanie nie powiodło się: {message}", deleteError: "Usuwanie nie powiodło się: {message}",
}, },
sectionManager: { sectionManager: {
title: "Sekcje", title: "Pory posiłków",
newSection: "Nowa sekcja", newSection: "Nowa pora posiłku",
editSection: "Edytuj sekcję", editSection: "Edytuj porę posiłku",
nameLabel: "Nazwa", nameLabel: "Nazwa",
nameEnLabel: "Nazwa (angielski)", nameEnLabel: "Nazwa (angielski)",
namePlLabel: "Nazwa (polski)", namePlLabel: "Nazwa (polski)",
@@ -640,7 +640,7 @@ const pl: Dict = {
timeTo: "Do", timeTo: "Do",
moveUp: "Przesuń w górę", moveUp: "Przesuń w górę",
moveDown: "Przesuń w dół", moveDown: "Przesuń w dół",
empty: "Nie dodano jeszcze żadnych sekcji.", empty: "Nie dodano jeszcze żadnych pór posiłków.",
confirmDelete: confirmDelete:
"Czy na pewno usunąć „{name}”? Przypisane dania zostaną również usunięte ze wszystkich planów tygodniowych.", "Czy na pewno usunąć „{name}”? Przypisane dania zostaną również usunięte ze wszystkich planów tygodniowych.",
loadError: "Wczytywanie nie powiodło się: {message}", loadError: "Wczytywanie nie powiodło się: {message}",
+1 -1
View File
@@ -64,7 +64,7 @@ export function dishCodes(dish: { allergens: string[]; additives: string[] }): s
return [...(dish.allergens ?? []), ...(dish.additives ?? [])].join(","); return [...(dish.allergens ?? []), ...(dish.additives ?? [])].join(",");
} }
/** Einträge eines Tages/Bereichs aus der geladenen Wochenliste herausfiltern. */ /** Einträge eines Tages/einer Essenszeit aus der geladenen Wochenliste herausfiltern. */
export function entriesFor( export function entriesFor(
entries: MenuEntry[], entries: MenuEntry[],
iso: string, iso: string,
+2 -2
View File
@@ -49,7 +49,7 @@ create trigger on_auth_user_created
after insert on auth.users after insert on auth.users
for each row execute function public.handle_new_user(); for each row execute function public.handle_new_user();
-- ---------- Bereiche der Speisekarte ---------- -- ---------- Essenszeiten der Speisekarte ----------
create table public.sections ( create table public.sections (
key text primary key, key text primary key,
label text not null, label text not null,
@@ -101,7 +101,7 @@ create trigger dishes_touch_updated_at
before update on public.dishes before update on public.dishes
for each row execute function public.touch_updated_at(); for each row execute function public.touch_updated_at();
-- ---------- Zuweisung Gericht -> Tag/Bereich ---------- -- ---------- Zuweisung Gericht -> Tag/Essenszeit ----------
create table public.menu_entries ( create table public.menu_entries (
id uuid primary key default gen_random_uuid(), id uuid primary key default gen_random_uuid(),
menu_date date not null, menu_date date not null,
@@ -1,14 +1,14 @@
-- ============================================================= -- =============================================================
-- Bereiche (Brotzeit/Mittagessen/…) vollständig verwaltbar machen: -- Essenszeiten (Brotzeit/Mittagessen/…) vollständig verwaltbar machen:
-- anlegen, umbenennen, Uhrzeit ändern, löschen. -- anlegen, umbenennen, Uhrzeit ändern, löschen.
-- ============================================================= -- =============================================================
-- Neue Bereiche bekommen einen automatisch generierten Schlüssel -- Neue Essenszeiten bekommen einen automatisch generierten Schlüssel
-- (wie bei dishes.id) statt eines von Hand vergebenen Slugs. -- (wie bei dishes.id) statt eines von Hand vergebenen Slugs.
alter table public.sections alter table public.sections
alter column key set default (gen_random_uuid())::text; alter column key set default (gen_random_uuid())::text;
-- Löscht man einen Bereich, werden seine Wochenplan-Einträge mit -- Löscht man eine Essenszeit, werden ihre Wochenplan-Einträge mit
-- entfernt (analog zu menu_entries_dish_id_fkey bei Gerichten) statt -- entfernt (analog zu menu_entries_dish_id_fkey bei Gerichten) statt
-- die Löschung zu blockieren. -- die Löschung zu blockieren.
alter table public.menu_entries alter table public.menu_entries
@@ -18,7 +18,7 @@ alter table public.menu_entries
foreign key (section_key) references public.sections(key) on delete cascade; foreign key (section_key) references public.sections(key) on delete cascade;
-- Bisher gab es nur eine Lesepolicy für sections; jetzt dürfen -- Bisher gab es nur eine Lesepolicy für sections; jetzt dürfen
-- Kantinenmitarbeiter/Admins Bereiche auch anlegen/ändern/löschen. -- Kantinenmitarbeiter/Admins Essenszeiten auch anlegen/ändern/löschen.
create policy "sections_staff_write" on public.sections create policy "sections_staff_write" on public.sections
for all to authenticated for all to authenticated
using (public.app_role() in ('staff', 'admin')) using (public.app_role() in ('staff', 'admin'))