From 660bcd1953be322711ac67bee428e62a6d8f965f Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 14 Apr 2026 19:02:05 +0000 Subject: [PATCH] docs: add mealplanner design spec Co-Authored-By: Claude Opus 4.6 (1M context) --- .../specs/2026-04-14-mealplanner-design.md | 208 ++++++++++++++++++ 1 file changed, 208 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-14-mealplanner-design.md diff --git a/docs/superpowers/specs/2026-04-14-mealplanner-design.md b/docs/superpowers/specs/2026-04-14-mealplanner-design.md new file mode 100644 index 0000000..95f0060 --- /dev/null +++ b/docs/superpowers/specs/2026-04-14-mealplanner-design.md @@ -0,0 +1,208 @@ +# Mealplanner — Design Spec + +**Datum:** 2026-04-14 +**Domain:** `essen.kuns.dev` +**Repo:** `kuns/mealplanner` + +## Zusammenfassung + +Webapp zur Wochenplanung von Mahlzeiten. Generiert automatisch einen Wochenplan (7 Tage, je 1 Hauptmahlzeit), der bearbeitbar ist. Aus dem Plan wird eine intelligente Einkaufsliste generiert (Zutaten zusammengefasst, abhakbar). Rezepte kommen aus einer externen API + eigene Rezepte. + +## Anforderungen + +- **Haushalt:** Feste Personenzahl in Einstellungen (Standard: 2) +- **Mahlzeiten:** 1 pro Tag (Abendessen) +- **Wochenplan:** Auto-generiert, voll editierbar (Gericht austauschen, neu generieren) +- **Rezepte:** Externe DB (TheMealDB, kostenlos, kein API-Key nötig) + eigene Rezepte +- **Einkaufsliste:** Zutaten aggregiert, nach Kategorie gruppiert, abhakbar +- **Ernährungspräferenzen:** Keine +- **Auth:** Zitadel (manueller OIDC PKCE Flow, kein oidc-client-ts) + +## Architektur + +``` +Vue 3 SPA (Tailwind 4, Bun, Vite) + ↓ REST API (/api/*) +.NET 8 Web API + ├── Auth (Zitadel JWT Bearer + NuGet-Paket) + ├── RecipeService (TheMealDB Client + eigene Rezepte CRUD) + ├── MealPlanService (Generierung + CRUD) + └── ShoppingListService (Aggregation aus Wochenplan) + ↓ +Shared PostgreSQL (DB: mealplanner) +``` + +### Projektstruktur + +``` +mealplanner/ +├── backend/ +│ ├── Controllers/ +│ │ ├── RecipeController.cs +│ │ ├── MealPlanController.cs +│ │ ├── ShoppingListController.cs +│ │ └── SettingsController.cs +│ ├── Models/ +│ │ ├── Recipe.cs +│ │ ├── MealPlan.cs +│ │ ├── MealPlanEntry.cs +│ │ ├── ShoppingItem.cs +│ │ └── UserSettings.cs +│ ├── Services/ +│ │ ├── TheMealDbClient.cs +│ │ ├── RecipeService.cs +│ │ ├── MealPlanService.cs +│ │ └── ShoppingListService.cs +│ ├── Data/ +│ │ └── AppDbContext.cs +│ ├── Program.cs +│ └── backend.csproj +├── frontend/ +│ ├── src/ +│ │ ├── views/ +│ │ │ ├── WeekPlanView.vue (Hauptansicht) +│ │ │ ├── ShoppingListView.vue +│ │ │ ├── RecipesView.vue (Eigene Rezepte verwalten) +│ │ │ └── SettingsView.vue +│ │ ├── components/ +│ │ │ ├── MealCard.vue +│ │ │ ├── RecipeDetail.vue +│ │ │ ├── ShoppingItem.vue +│ │ │ └── WeekDay.vue +│ │ ├── composables/ +│ │ │ └── useApi.ts +│ │ ├── auth.ts (Manueller OIDC PKCE Flow) +│ │ ├── router.ts +│ │ ├── App.vue +│ │ └── main.ts +│ ├── index.html +│ └── package.json +├── Dockerfile +├── docker-compose.yml +└── docs/ +``` + +## Datenmodell + +### Recipe +| Feld | Typ | Beschreibung | +|------|-----|-------------| +| id | UUID | PK | +| user_id | string | Zitadel User ID (null = extern) | +| external_id | string? | TheMealDB ID | +| title | string | Name des Gerichts | +| instructions | text | Zubereitungsanleitung | +| image_url | string? | Bild-URL | +| source | enum | `own`, `themealdb` | +| created_at | timestamp | | + +### RecipeIngredient +| Feld | Typ | Beschreibung | +|------|-----|-------------| +| id | UUID | PK | +| recipe_id | UUID | FK → Recipe | +| name | string | Zutat | +| amount | decimal? | Menge | +| unit | string? | Einheit (g, ml, Stück, etc.) | +| category | string? | Gemüse, Fleisch, Milch, etc. | + +### MealPlan +| Feld | Typ | Beschreibung | +|------|-----|-------------| +| id | UUID | PK | +| user_id | string | Zitadel User ID | +| week_start | date | Montag der Woche | +| created_at | timestamp | | + +### MealPlanEntry +| Feld | Typ | Beschreibung | +|------|-----|-------------| +| id | UUID | PK | +| meal_plan_id | UUID | FK → MealPlan | +| date | date | Tag | +| recipe_id | UUID | FK → Recipe | + +### UserSettings +| Feld | Typ | Beschreibung | +|------|-----|-------------| +| user_id | string | PK, Zitadel User ID | +| household_size | int | Anzahl Personen (Default: 2) | + +## API Endpoints + +### Wochenplan +- `POST /api/mealplan/generate` — Neuen Wochenplan generieren (ab nächstem Montag) +- `GET /api/mealplan/current` — Aktuellen Wochenplan laden +- `GET /api/mealplan/{weekStart}` — Plan für bestimmte Woche +- `PUT /api/mealplan/{id}/entry/{date}` — Gericht für einen Tag austauschen +- `POST /api/mealplan/{id}/entry/{date}/reroll` — Neues zufälliges Gericht für Tag + +### Rezepte +- `GET /api/recipes` — Eigene Rezepte auflisten +- `GET /api/recipes/{id}` — Rezeptdetails +- `POST /api/recipes` — Eigenes Rezept anlegen +- `PUT /api/recipes/{id}` — Eigenes Rezept bearbeiten +- `DELETE /api/recipes/{id}` — Eigenes Rezept löschen +- `GET /api/recipes/search?q=` — Suche (eigene + TheMealDB) + +### Einkaufsliste +- `GET /api/shoppinglist/{mealPlanId}` — Aggregierte Einkaufsliste für Wochenplan +- `PUT /api/shoppinglist/{mealPlanId}/check/{itemId}` — Item abhaken/enthaken + +### Einstellungen +- `GET /api/settings` — User-Einstellungen laden +- `PUT /api/settings` — User-Einstellungen speichern + +## Wochenplan-Generierung + +1. Alle verfügbaren Rezepte sammeln (eigene + TheMealDB Random) +2. 7 zufällige, unterschiedliche Gerichte auswählen +3. Montag bis Sonntag zuweisen +4. In DB speichern + +**Reroll:** Einzelnes Gericht durch neues zufälliges ersetzen (nicht doppelt im Plan). + +## Einkaufslisten-Logik + +1. Alle Rezepte des Wochenplans laden +2. Zutaten sammeln, gleiche Zutaten zusammenfassen (Name-Match, Mengen addieren) +3. Mengen × Haushaltsgröße skalieren +4. Nach Kategorie gruppieren (Gemüse, Fleisch, Milchprodukte, Gewürze, Sonstiges) +5. Check-Status pro User in DB persistieren + +## Frontend Design + +**Theme:** Dark Mode (wie task-scheduler-v2) +- **Hintergrund:** zinc-950 (#09090b) +- **Cards:** zinc-900 (#18181b) +- **Borders:** zinc-800 (#27272a) +- **Primary Text:** zinc-100 (#f5f5f5) +- **Secondary Text:** zinc-500 (#71717a) +- **Accent:** emerald (#10b981) +- **Accent Hover:** #059669 + +### Hauptansichten + +1. **Wochenplan** (Startseite) — 7 Cards (Mo-So), je mit Gerichtname + Bild. Buttons: "Austauschen" (Rezeptsuche), "Neu würfeln" (Random). Button oben: "Neue Woche generieren". +2. **Einkaufsliste** — Gruppiert nach Kategorie, Checkboxen zum Abhaken. Badge mit Anzahl offener Items. +3. **Rezepte** — Eigene Rezepte CRUD. Karten-Ansicht. Formular zum Anlegen/Bearbeiten mit dynamischer Zutatenliste. +4. **Einstellungen** — Haushaltsgröße anpassen. + +### Navigation +Sidebar oder Bottom-Nav mit 4 Tabs: Wochenplan, Einkaufsliste, Rezepte, Einstellungen. + +## Deployment + +- **Coolify** via Git Push (wie alle anderen Projekte) +- **Dockerfile:** Multi-stage (Bun Frontend Build → .NET Publish → Runtime) +- **DB:** `mealplanner` auf Shared PostgreSQL +- **Domain:** `essen.kuns.dev` +- **Env-Vars in Coolify:** `DATABASE_URL`, `ZITADEL_ISSUER`, `ZITADEL_CLIENT_ID` + +## Externe Abhängigkeiten + +- **TheMealDB API** (`www.themealdb.com/api/json/v1/1/`) — kostenlos, kein Key nötig + - `random.php` — Zufälliges Rezept + - `search.php?s=` — Suche + - `lookup.php?i=` — Details per ID +- Rezepte auf Englisch — akzeptabel für MVP