getLocale() fiel bei fehlendem/ungültigem Cookie bisher immer fest auf Deutsch zurück, auch wenn Deutsch im Sprachen-Admin deaktiviert wurde. Da der Sprachumschalter sich bei nur einer aktiven Sprache zusätzlich ausblendet, gab es keine Möglichkeit, das über die Oberfläche zu korrigieren. Fallback nutzt jetzt Deutsch nur noch, wenn es aktiv ist.
414 lines
20 KiB
Markdown
414 lines
20 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.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
|