Ersetzt den "Tag schließen"-Textlink durch ein Schloss-Symbol (🔓/🔒) und lässt den "Geschlossen"-Hinweis eines geschlossenen Tages über alle Essenszeiten-Zeilen durchlaufen (per rowSpan), statt ihn in jeder Zeile einzeln zu wiederholen – sowohl im Wochenplan als auch auf der öffentlichen Speisekarte.
445 lines
22 KiB
Markdown
445 lines
22 KiB
Markdown
# Changelog
|
||
|
||
Alle nennenswerten Änderungen an diesem Projekt werden hier dokumentiert.
|
||
Format angelehnt an [Keep a Changelog](https://keepachangelog.com/de/1.1.0/),
|
||
Versionierung nach [Semantic Versioning](https://semver.org/lang/de/).
|
||
|
||
## [1.12.1] – 2026-07-20
|
||
|
||
### Geändert
|
||
- Bedienung geschlossener Tage im Wochenplan überarbeitet: Statt eines
|
||
Text-Links am Datum markiert jetzt ein Schloss-Symbol (🔓 zum
|
||
Schließen, 🔒 zeigt „geschlossen" an und öffnet per Klick wieder) den
|
||
Tag. Ein geschlossener Tag zeigt sowohl im Wochenplan als auch auf
|
||
der öffentlichen Speisekarte (Desktop-Tabelle) einen einzigen, über
|
||
alle Essenszeiten-Zeilen durchgehenden „Geschlossen"-Hinweis statt
|
||
einer Wiederholung in jeder einzelnen Zeile.
|
||
|
||
## [1.12.0] – 2026-07-20
|
||
|
||
### Hinzugefügt
|
||
- Einzelne Tage als geschlossen markierbar (z. B. Feiertage,
|
||
Betriebsausflug) – im Wochenplan lässt sich pro Tag über „Tag
|
||
schließen" ein optionaler, mehrsprachiger Grund hinterlegen (inkl.
|
||
automatischer Übersetzung per DeepL, sofern konfiguriert). Ein
|
||
geschlossener Tag:
|
||
- blendet in der Gerichte-Verwaltung des Wochenplans „Mahlzeit
|
||
hinzufügen" für diesen Tag aus (bestehende Einträge lassen sich
|
||
weiterhin entfernen), lässt sich per „Wieder öffnen" jederzeit
|
||
rückgängig machen.
|
||
- zeigt auf der öffentlichen Speisekarte (Desktop-Tabelle und
|
||
mobile Ansicht) einen „Geschlossen"-Hinweis mit Grund statt der
|
||
Essenszeiten-Spalten/-Karte für diesen Tag.
|
||
- erscheint im RSS-Feed als eigener Eintrag mit Schließungsgrund
|
||
statt eines leeren oder fehlenden Tages.
|
||
- Neue Tabellen `closed_days`/`closed_day_translations` (Migration
|
||
`0007_closed_days.sql`).
|
||
|
||
## [1.11.1] – 2026-07-20
|
||
|
||
### Behoben
|
||
- Wurde Deutsch im Sprachen-Admin deaktiviert (z. B. um die App auf nur
|
||
Englisch zu reduzieren), blieb die gesamte App trotzdem auf Deutsch
|
||
stehen, sowohl im öffentlichen als auch im internen Bereich: `getLocale()`
|
||
fiel bei fehlendem/ungültigem Sprach-Cookie bisher immer fest auf
|
||
Deutsch zurück, unabhängig davon, ob Deutsch überhaupt noch aktiv war.
|
||
Da der Sprachumschalter sich bei nur einer aktiven Sprache zusätzlich
|
||
automatisch ausblendet, gab es keine Möglichkeit, das über die
|
||
Oberfläche zu korrigieren. Der Fallback nutzt jetzt Deutsch nur noch,
|
||
wenn es tatsächlich aktiv ist – sonst die erste aktive Sprache.
|
||
|
||
## [1.11.0] – 2026-07-20
|
||
|
||
### Hinzugefügt
|
||
- Speiseplan-Inhalte variabel gemacht (Teil 2 des "mehrsprachig
|
||
variabel"-Umbaus): Gerichtnamen, Essenszeiten-Bezeichnungen sowie
|
||
Allergen-/Zusatzstoff-Namen sind jetzt genauso dynamisch mehrsprachig
|
||
wie die Bedienoberfläche aus Version 1.10.0, statt auf feste
|
||
Englisch-/Polnisch-Spalten begrenzt zu sein:
|
||
- In den Verwaltungsseiten (Gerichte, Essenszeiten, Allergene &
|
||
Zusatzstoffe) erscheint jetzt automatisch ein Eingabefeld je aktiv
|
||
geschalteter Sprache – wird im Sprachen-Admin eine neue Sprache
|
||
angelegt, taucht dort sofort ein passendes Feld auf, ohne
|
||
Codeänderung.
|
||
- Der "Automatisch übersetzen"-Button (DeepL) übersetzt künftig in
|
||
alle aktiven, von DeepL unterstützten Sprachen statt fix nur
|
||
Englisch/Polnisch.
|
||
- CSV-Export/-Import für Gerichte, Allergene und Zusatzstoffe hat
|
||
jetzt eine Spalte je aktiver Sprache (`name_en`, `name_fr`, …)
|
||
statt der bisher fest verdrahteten `name_en`/`name_pl`-Spalten.
|
||
- Reduziert der Admin das Sprachenfeature im Sprachen-Bereich auf nur
|
||
Deutsch, verschwinden diese Zusatzfelder ebenfalls automatisch aus
|
||
allen drei Verwaltungsseiten.
|
||
|
||
### Geändert
|
||
- Neue Migration `0006_content_translations.sql` ersetzt die festen
|
||
Spalten `name_en`/`name_pl` (Gerichte, Allergene, Zusatzstoffe) bzw.
|
||
`label_en`/`label_pl` (Essenszeiten) durch je eine
|
||
Übersetzungstabelle (`dish_translations`, `section_translations`,
|
||
`allergen_translations`, `additive_translations`); bestehende
|
||
Übersetzungen werden dabei automatisch übernommen.
|
||
**Vor dem Einspielen auf einem Produktivsystem unbedingt ein Backup
|
||
der Datenbank anlegen** – die alten Spalten werden nach der
|
||
Übernahme entfernt.
|
||
|
||
## [1.10.0] – 2026-07-20
|
||
|
||
### Hinzugefügt
|
||
- Dynamisches Sprachpaket-System für die Bedienoberfläche (Teil 1 des
|
||
"mehrsprachig variabel"-Umbaus, Speiseplan-Inhalte folgen in einer
|
||
späteren Version). Sprachen sind jetzt zur Laufzeit über eine neue
|
||
Admin-Seite „Sprachen" verwaltbar statt fest im Code zu stehen:
|
||
- Vorlage der aktuellen deutschen Texte herunterladen, übersetzt
|
||
wieder hochladen – neue Übersetzungen werden sofort aktiv, ohne
|
||
Deployment.
|
||
- Fehlende Begriffe fallen automatisch auf Deutsch zurück statt leer
|
||
zu bleiben; die Admin-Seite zeigt pro Sprache Vollständigkeit in %
|
||
sowie „N neue Begriffe seit letztem Import", falls eine neue
|
||
App-Version zusätzliche Texte eingeführt hat.
|
||
- Sprachen lassen sich einzeln deaktivieren, bis auf eine einzige
|
||
reduzierbar (der Sprachumschalter blendet sich dann automatisch
|
||
aus) – mindestens eine muss aktiv bleiben.
|
||
- Neue Sprachen lassen sich direkt anlegen (Code + Anzeigename),
|
||
Deutsch bleibt als einzige garantiert vollständige Basis-Sprache
|
||
unlöschbar.
|
||
- Import validiert hochgeladene Übersetzungen gegen die aktuelle
|
||
Vorlage: Platzhalter wie `{message}` müssen erhalten bleiben,
|
||
unbekannte Schlüssel werden ignoriert statt Fehler zu werfen.
|
||
- Neue Tabellen `languages`/`ui_translations` (Migration `0004`),
|
||
bestehende Englisch-/Polnisch-Texte automatisch übernommen
|
||
(Migration `0005`) – keine manuelle Nacharbeit nötig.
|
||
|
||
## [1.9.5] – 2026-07-20
|
||
|
||
### Hinzugefügt
|
||
- Interner Bereich (Wochenplan, Essenszeiten, Gerichte, Allergene &
|
||
Zusatzstoffe, Vorschläge, Benutzer, Design, Mein Konto) für
|
||
Mobilgeräte nutzbar gemacht. `AppHeader.tsx` bekommt unterhalb der
|
||
`sm`-Breakpoint-Grenze ein Hamburger-Menü mit denselben Links
|
||
gestapelt statt der bisherigen, bei schmalen Bildschirmen unübersichtlich
|
||
umbrechenden einzeiligen Navigation. Der Wochenplan (`WeekEditor.tsx`)
|
||
zeigt auf Mobilgeräten eine Tag-für-Tag-Ansicht mit Tab-Leiste
|
||
(Mo–Fr) statt der für 375px viel zu schmalen 6-spaltigen Tabelle –
|
||
Gericht hinzufügen/löschen funktioniert unverändert, da beide
|
||
Ansichten denselben Bearbeitungs-Zustand teilen. In DishManager,
|
||
CodeListManager, UserManager, SectionManager und PasskeyManager
|
||
brechen Kopf- und Listenzeilen jetzt bei Bedarf um, statt Buttons
|
||
abzuschneiden.
|
||
|
||
## [1.9.0] – 2026-07-20
|
||
|
||
### Hinzugefügt
|
||
- SSO-Login per OpenID Connect (z. B. gegen ein selbst gehostetes
|
||
Authentik), zusätzlich zu Passwort und Passkey. Konfiguration über
|
||
drei optionale Env-Vars (`OIDC_ISSUER`, `OIDC_CLIENT_ID`,
|
||
`OIDC_CLIENT_SECRET`) – ohne sie bleibt der SSO-Button auf der
|
||
Anmeldeseite ausgeblendet. Authorization-Code-Flow mit PKCE, ID-Token-
|
||
Signaturprüfung gegen das JWKS des Providers (neue Abhängigkeit
|
||
`jose`), State/Nonce serverseitig kurzlebig und einmalig verwendbar
|
||
(neue Tabelle `oidc_states`, Migration `0003_oidc_state.sql`).
|
||
SSO-Login funktioniert ausschließlich für bereits unter „Benutzer“
|
||
angelegte E-Mail-Adressen – es werden nie neue Konten angelegt, und
|
||
die Rolle (Admin/Kantinenmitarbeiter) bleibt ausschließlich über die
|
||
bestehende Benutzerverwaltung steuerbar, nie aus SSO-Claims
|
||
übernommen. In DEPLOYMENT.md unter „SSO/OpenID Connect“ dokumentiert.
|
||
|
||
## [1.8.1] – 2026-07-20
|
||
|
||
### Hinzugefügt
|
||
- `update.sh`: Update-Skript für Linux-Deployments – stoppt den Docker-
|
||
Stack, sichert lokale Änderungen an `docker-compose.yml` per
|
||
`git stash` (falls vorhanden), führt `git pull` aus, spielt die
|
||
Änderungen zurück und startet den Stack neu im Build-Modus. Bricht
|
||
bei einem `git pull`- oder Stash-Konflikt kontrolliert ab, statt mit
|
||
einem halb aktualisierten Stand weiterzumachen. In DEPLOYMENT.md unter
|
||
„Updates einspielen“ dokumentiert.
|
||
|
||
## [1.8.0] – 2026-07-19
|
||
|
||
### Hinzugefügt
|
||
- Umschaltbarer Hinweismodus für Allergene/Zusatzstoffe: Auf der Seite
|
||
„Allergene & Zusatzstoffe“ kann zwischen der bisherigen detaillierten
|
||
Auswahl je Gericht und einem einfachen, in Deutsch/Englisch/Polnisch
|
||
editierbaren Hinweistext (z. B. „Bei Fragen zu Allergenen und
|
||
Zusatzstoffen wenden Sie sich bitte an das Kantinen-Team.“)
|
||
umgeschaltet werden. Im Hinweismodus entfällt auf der öffentlichen
|
||
Speisekarte die Legende und die Kürzel an den Gerichten, und in der
|
||
Gerichte-Verwaltung wird die Allergen-/Zusatzstoff-Auswahl beim
|
||
Bearbeiten ausgeblendet (bereits zugeordnete Daten bleiben in der
|
||
Datenbank erhalten). Umschalten und Hinweistext bearbeiten dürfen
|
||
sowohl Kantinenpersonal als auch Admins.
|
||
|
||
## [1.7.0] – 2026-07-19
|
||
|
||
### Hinzugefügt
|
||
- CSV-Import/-Export für Gerichte, Allergene und Zusatzstoffe (Buttons
|
||
„Exportieren“/„Importieren“ auf den jeweiligen Verwaltungsseiten).
|
||
Export lädt die aktuelle Liste als CSV herunter (Gerichte:
|
||
`name,name_en,name_pl,price,allergens,additives`, Allergene/
|
||
Zusatzstoffe: `code,name,name_en,name_pl`; Kürzel bei Gerichten
|
||
Semikolon-getrennt in einer Zelle, z. B. `A;G`). Import liest dieselbe
|
||
Spaltenstruktur (Reihenfolge egal, Groß-/Kleinschreibung der
|
||
Kopfzeile wird ignoriert) und aktualisiert bestehende Einträge
|
||
(Abgleich über Kürzel bei Allergenen/Zusatzstoffen, über den exakten
|
||
Namen bei Gerichten) bzw. legt neue an. Zeilen mit fehlenden
|
||
Pflichtfeldern, ungültigem Preis oder mehrdeutigem Gerichtsnamen
|
||
(mehrere Gerichte mit demselben Namen) werden übersprungen und mit
|
||
Grund in der Erfolgsmeldung aufgelistet, statt den ganzen Import
|
||
abzubrechen.
|
||
|
||
### Behoben
|
||
- RSS-Feed (`/feed.xml`): Mehrere Feed-Reader (u. a. Outlook,
|
||
Thunderbird) behandeln `<description>` als kurze Vorschau und kürzen
|
||
sie eigenmächtig – dadurch war bei Tagen mit mehreren Essenszeiten
|
||
oft nur die erste sichtbar, obwohl der Server bereits alle
|
||
Essenszeiten des Tages in der Beschreibung lieferte. Zusätzlich zu
|
||
`<description>` wird jetzt auch `<content:encoded>` (RSS-Content-
|
||
Modul) mit demselben vollständigen Inhalt ausgeliefert – von den
|
||
meisten Readern als vollständiger Artikeltext erkannt und ungekürzt
|
||
angezeigt.
|
||
|
||
## [1.6.3] – 2026-07-18
|
||
|
||
### Behoben
|
||
- `docker-compose.yml`: Der `app`-Dienst setzte `BRANDING_DIR` nicht, sodass
|
||
`lib/branding.ts` beim Hochladen von Logo/Favicon auf den Fallback-Pfad
|
||
`${cwd}/data/branding` (= `/app/data/branding`) statt auf das im
|
||
Dockerfile vorbereitete, gemountete Verzeichnis `/data/branding` auswich.
|
||
`/app` gehört im Container `root`, der App-Prozess läuft aber als
|
||
nicht-root-Nutzer `nextjs` – das Anlegen des Fallback-Verzeichnisses
|
||
scheiterte mit `EACCES`, der Upload endete mit „Upload fehlgeschlagen:
|
||
500". Jetzt wird `BRANDING_DIR=/data/branding` explizit gesetzt, passend
|
||
zum Volume-Mount und zum in `Dockerfile` per `chown` freigegebenen
|
||
Verzeichnis.
|
||
|
||
## [1.6.2] – 2026-07-18
|
||
|
||
### Behoben
|
||
- `scripts/bootstrap-admin.mjs`: Konnte `ZUGANGSDATEN.md` nicht
|
||
geschrieben werden (z. B. `EACCES`, weil die per Bind-Mount
|
||
eingebundene Host-Datei root gehört und der App-Container als
|
||
nicht-root läuft), brach das Skript ab, nachdem der Admin-Benutzer
|
||
bereits in der Datenbank angelegt war – das generierte Passwort war
|
||
dann nirgends mehr zu finden. Schreibt jetzt bei einem Fehler
|
||
stattdessen E-Mail/Passwort ins Log und beendet sich weiterhin
|
||
erfolgreich.
|
||
- DEPLOYMENT.md: Schritt 2 fehlte `chmod 666 ZUGANGSDATEN.md` (der
|
||
eigentliche Auslöser des Bugs oben). Neue Fehlerbehebung-Einträge für
|
||
`ECONNREFUSED` beim Start (harmlose Start-Reihenfolge, löst sich
|
||
durch den automatischen Neustart von selbst) und für diesen
|
||
`EACCES`-Fall inkl. Recovery-Anleitung für einen bereits verwaisten
|
||
Admin-Account.
|
||
|
||
## [1.6.1] – 2026-07-18
|
||
|
||
### Geändert
|
||
- PostgreSQL-Container ist nicht mehr über einen Host-Port erreichbar
|
||
(`docker-compose.yml`: `ports: 5433:5432` beim `db`-Dienst entfernt).
|
||
App und Dev-Server erreichen die Datenbank weiterhin über das von
|
||
Docker Compose automatisch angelegte interne Netzwerk (Hostname
|
||
`db`) – reduziert die Angriffsfläche, ohne den Betrieb zu ändern.
|
||
Debugging/Backup weiterhin über `docker compose exec db psql`/
|
||
`pg_dump` möglich.
|
||
|
||
### Behoben
|
||
- DEPLOYMENT.md: Fehlerbehebung-Abschnitt für
|
||
`password authentication failed for user "postgres"` ergänzt (tritt
|
||
auf, wenn `docker compose up` vor dem Setzen von `LOCAL_PG_PASSWORD`
|
||
läuft oder ohne `--env-file .env.local` – PostgreSQL übernimmt das
|
||
Passwort nur beim allerersten Start auf leerem Datenverzeichnis).
|
||
`.env.example` warnt jetzt vor Sonderzeichen in `LOCAL_PG_PASSWORD`,
|
||
die beim `.env`-Parsing zu stillen Fehlern führen können.
|
||
|
||
## [1.6.0] – 2026-07-18
|
||
|
||
### Hinzugefügt
|
||
- RSS-Feed des Speiseplans (`/feed.xml`, ein Eintrag pro Tag mit den
|
||
Gerichten je Essenszeit für die aktuelle und die nächste Woche) zum
|
||
Abonnieren in einem Feedreader. Autodiscovery-Link im Seiten-`<head>`
|
||
sowie sichtbares RSS-Icon im Kopfbereich der öffentlichen
|
||
Speisekarte.
|
||
- Kantinen-Bereich: „Vorschläge“-Navigationspunkt zeigt jetzt die
|
||
Anzahl offener Rezeptvorschläge als Zahl im roten Kreis.
|
||
- Neues [DEPLOYMENT.md](DEPLOYMENT.md): Schritt-für-Schritt-Anleitung
|
||
für die Inbetriebnahme auf einem neuen Server (Docker Compose,
|
||
Konfiguration, Reverse-Proxy/HTTPS, Updates, Backup).
|
||
|
||
### Geändert
|
||
- Letzte Erwähnungen von Supabase in aktiven Doku-Texten und
|
||
Code-Kommentaren entfernt/umformuliert (README, Migrationsschema,
|
||
Passkey-Konfiguration, Branding-Ablage) – die App läuft seit v1.5
|
||
vollständig ohne Supabase, das sollte sich jetzt auch durchgängig in
|
||
der Dokumentation widerspiegeln. Historische CHANGELOG-Einträge
|
||
bleiben unverändert.
|
||
- `.env.example`: `LOCAL_PG_PASSWORD` (von `docker-compose.yml`
|
||
verwendet, um die Datenbank-Verbindung der App-Container
|
||
zusammenzubauen) war bisher nirgends dokumentiert – beim Schreiben
|
||
der Deployment-Anleitung aufgefallen und ergänzt.
|
||
|
||
## [1.5.0] – 2026-07-18
|
||
|
||
### Hinzugefügt
|
||
- Wochenplan: „Mahlzeit hinzufügen" bietet jetzt ein Suchfeld mit
|
||
gefilterter Trefferliste statt einer langen Dropdown-Liste zum
|
||
Durchscrollen.
|
||
- `db/seed-demo.sql` (`npm run db:seed-demo`): spielt für lokale
|
||
Entwicklung/Demos den ursprünglichen Beispieldatensatz ein
|
||
(Essenszeiten, Allergene, Zusatzstoffe, Testgerichte, zwei
|
||
Beispielwochen) – kein Teil der automatischen Migrationen, frische
|
||
Deployments starten weiterhin leer.
|
||
|
||
### Geändert
|
||
- **Supabase vollständig entfernt** – die App läuft jetzt komplett
|
||
selbst gehostet, einzige externe Abhängigkeit bleibt optional DeepL.
|
||
- Datenbank: selbst gehostetes PostgreSQL statt Supabase-Cloud-Postgres.
|
||
Schema in `db/migrations/*.sql`, wird beim Start automatisch und
|
||
idempotent angewendet (`db/migrate.mjs`).
|
||
- Anmeldung: eigene Session-Verwaltung (opake, in der DB gespeicherte
|
||
Tokens, `httpOnly`/`sameSite=lax`-Cookie) statt Supabase Auth.
|
||
Passwörter werden mit Node-eigenem `crypto.scrypt` gehasht (keine
|
||
neue Abhängigkeit).
|
||
- Passkeys: `@simplewebauthn` ersetzt Supabase's bisher experimentelles
|
||
WebAuthn-API. Die RP-Domain wird direkt aus `APP_URL` abgeleitet –
|
||
kein externer Konfigurationsschritt mehr nötig.
|
||
- Logo/Favicon: lokale Dateiablage (Docker-Volume) statt
|
||
Supabase-Storage-Bucket, ausgeliefert über `/branding/[filename]`.
|
||
- Autorisierung (öffentlich lesbar / Kantinen-Team schreibt / nur
|
||
Admin für Einstellungen & Benutzer) läuft jetzt in den API-Routen
|
||
statt über Postgres-Row-Level-Security.
|
||
- E-Mail-Änderung im eigenen Konto läuft direkt nach
|
||
Passwort-Bestätigung statt über eine Supabase-Bestätigungsmail
|
||
(kein SMTP-Server vorhanden).
|
||
- Datenbank startet beim allerersten Deployment leer; beim ersten Start
|
||
wird automatisch genau ein Admin-Benutzer mit zufällig generiertem
|
||
Passwort angelegt, die Zugangsdaten landen in `ZUGANGSDATEN.md`.
|
||
|
||
### Behoben
|
||
- „Mindestens 1 Passkey nötig, um die Passwort-Anmeldung zu
|
||
deaktivieren" wurde bisher nur clientseitig geprüft; ein manuell
|
||
gebauter Request hätte die Passwort-Anmeldung auch ohne Passkey
|
||
deaktivieren können. Jetzt zusätzlich serverseitig erzwungen.
|
||
- Logo-/Favicon-Upload akzeptierte anhand des vom Browser gemeldeten
|
||
Dateityps auch SVG-Dateien. Da diese (anders als beim vorherigen
|
||
Supabase-Storage-Bucket auf fremder Domain) jetzt auf der eigenen
|
||
Origin ausgeliefert werden, hätte eine SVG mit eingebettetem
|
||
`<script>` bei direktem Aufruf der Datei-URL im Browser eines
|
||
anderen angemeldeten Admins ausgeführt werden können. Upload
|
||
akzeptiert jetzt nur noch eine Whitelist an Rasterformaten
|
||
(png/jpg/webp/gif/ico); vor dem Merge im Rahmen der
|
||
Sicherheitsprüfung gefunden und behoben.
|
||
|
||
### Hinweis für bestehende Docker-Installationen
|
||
Das Docker-Volume `pgdata` diente bisher nur als Lese-Kopie/Backup und
|
||
wird mit v1.5 zur primären Datenbank. Es enthält noch das alte
|
||
Supabase-Mirror-Schema und muss vor dem Upgrade entfernt werden
|
||
(`docker compose down -v`, danach `docker compose up -d --build`), damit
|
||
die neuen Migrationen auf einer leeren Datenbank laufen.
|
||
|
||
## [1.4.0] – 2026-07-18
|
||
|
||
### Hinzugefügt
|
||
- Essenszeiten (Brotzeit/Mittagessen/…) vollständig verwaltbar: anlegen,
|
||
umbenennen (inkl. EN/PL), Uhrzeit ändern, löschen und per Pfeil-Buttons
|
||
neu anordnen – neue Seite „Essenszeiten" im Kantinen-Bereich. Löschen
|
||
entfernt zugewiesene Gerichte automatisch aus allen Wochenplänen.
|
||
|
||
### Geändert
|
||
- „Automatisch übersetzen"-Button bei Gerichten/Allergenen/Zusatzstoffen
|
||
ist nur noch sichtbar, wenn `DEEPL_API_KEY` gesetzt ist, statt erst
|
||
nach Klick auf die fehlende Konfiguration hinzuweisen.
|
||
|
||
### Behoben
|
||
- Sprachumschalter (DE/EN/PL) erschien auf der öffentlichen Speisekarte
|
||
in der mobilen Ansicht doppelt.
|
||
|
||
## [1.3.0] – 2026-07-18
|
||
|
||
### Hinzugefügt
|
||
- Mehrsprachigkeit für die komplette Anwendung (Deutsch, Englisch,
|
||
Polnisch): Sprachumschalter (Cookie-basiert, kein Neuladen der
|
||
Seite nötig), sämtliche Oberflächentexte übersetzt
|
||
- Gerichte, Bereiche, Allergene und Zusatzstoffe zusätzlich mit
|
||
englischem/polnischem Namen; öffentliche Speisekarte zeigt je nach
|
||
gewählter Sprache automatisch den passenden Namen (Fallback:
|
||
Deutsch, falls keine Übersetzung hinterlegt ist)
|
||
- Automatische Übersetzung per DeepL: Button „Automatisch übersetzen“
|
||
beim Anlegen/Bearbeiten von Gerichten, Allergenen und Zusatzstoffen;
|
||
Ergebnis bleibt danach manuell korrigierbar. Aktivierung über die
|
||
neue Docker-Variable `DEEPL_API_KEY` – ohne Key bleibt der Button
|
||
inaktiv, die Felder lassen sich weiterhin von Hand ausfüllen
|
||
- Rezeptvorschläge im öffentlichen Bereich: nicht angemeldete
|
||
Besucher können über „Rezept vorschlagen“ ein fehlendes Gericht
|
||
vorschlagen (Name + optionale Beschreibung), inkl. Dublettenprüfung
|
||
gegen bestehende Gerichte und einfachem Honeypot-Spamschutz
|
||
- Neue Seite „Vorschläge“ im Kantinen-Bereich: eingereichte Vorschläge
|
||
sichten, als Gericht übernehmen oder ablehnen
|
||
|
||
### Behoben
|
||
- Passwort-wiederholen-Feld beim Bearbeiten eines Benutzers erschien
|
||
erst, nachdem im ersten Passwortfeld schon getippt wurde – wirkte
|
||
wie ein einzelnes Pflichtfeld
|
||
- Anmelden-Button überlappte auf Mobilgeräten mit breiten Logos
|
||
(Banner-Format) das Logo, da er absolut in der oberen Ecke
|
||
positioniert war
|
||
|
||
## [1.2.0] – 2026-07-18
|
||
|
||
### Hinzugefügt
|
||
- „Heute"-Button in der Wochennavigation (öffentliche Speisekarte und
|
||
Wochenplan-Editor)
|
||
- Mobile Ansicht der öffentlichen Speisekarte: umschaltbar zwischen
|
||
Tag (Standard) und Woche, unabhängig von der Desktop-Tabelle
|
||
- Allergene und Zusatzstoffe wieder pro Gericht auswählbar (Chip-Auswahl
|
||
im Formular) und als kleine Kürzel neben dem Gerichtnamen sichtbar –
|
||
in Speisekarte, mobiler Ansicht und Wochenplan-Editor
|
||
- Passwort-Wiederholung beim Anlegen neuer Benutzer und beim optionalen
|
||
Passwort-Reset
|
||
- Passwort-Anmeldung pro Konto deaktivierbar (nur wenn mindestens ein
|
||
Passkey registriert ist), Durchsetzung im Login-Flow
|
||
- `SITE_TITLE`-Umgebungsvariable für Browser-Tab-Titel und Überschrift
|
||
ohne Logo
|
||
- Austauschbares Favicon über den Admin-Design-Bereich
|
||
|
||
### Geändert
|
||
- Gemeinsame Navigation für Kantinen- und Admin-Bereich statt zwei
|
||
getrennter Menüs
|
||
- Live-Suche bei den Gerichten
|
||
- Mehrfachauswahl zum Batch-Löschen von Gerichten
|
||
- App erreichbar auf `0.0.0.0` statt nur `localhost` (Docker und
|
||
nativer Betrieb)
|
||
- Projekt umbenannt von „Speisekarte“ zu „canteen-menu“ (Docker-,
|
||
npm- und Supabase-Namen; deutsche In-App-Texte unverändert)
|
||
- Öffentliche URL über `APP_URL` konfigurierbar (CSRF-Origin-Check
|
||
hinter Reverse-Proxy, Passkey-Domain)
|
||
|
||
### Behoben
|
||
- Next.js band `app/favicon.ico` zusätzlich zu einem dynamisch
|
||
gesetzten Favicon ein – Favicon wird jetzt immer explizit gesetzt
|
||
- Weiterleitungen (Logout, Zugriffsschutz) übernahmen nach der
|
||
0.0.0.0-Bindung fälschlich die Server-Adresse statt des
|
||
aufgerufenen Hosts
|
||
|
||
## [1.1.0] – 2026-07-17
|
||
|
||
### Hinzugefügt
|
||
- Versionsnummer im Fußbereich jeder Seite
|
||
|
||
## [1.0.0] – 2026-07-17
|
||
|
||
Erste vollständige Version.
|
||
|
||
### Hinzugefügt
|
||
- Öffentliche Speisekarte ohne Login: Wochenansicht Mo–Fr mit den
|
||
Bereichen Brotzeit, Mittagessen, Mittagessen vegetarisch und Suppe;
|
||
Wochen-Navigation; Logo zentriert; Allergene & Zusatzstoffe unterhalb
|
||
der Karte
|
||
- Anmeldung mit E-Mail/Passwort oder Passkey
|
||
- Kantinen-Bereich: Gerichte anlegen/bearbeiten/löschen, Wochenplan
|
||
pflegen, globale Allergen-/Zusatzstofflisten verwalten
|
||
- Admin-Bereich: Benutzerverwaltung, Farbgebung, Logo-Upload
|
||
- Eigenes Konto verwalten: Name, E-Mail, Passwort, Passkeys
|
||
- Row-Level-Security, HTTP-Security-Header, CSRF-Origin-Check
|
||
- Docker-Setup (App-Image, lokale PostgreSQL-Kopie, Dev-Profil ohne
|
||
lokales Node.js)
|
||
- Lokale PostgreSQL-Kopie mit Sync-Skript
|