docs: add mealplanner design spec

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-14 19:02:05 +00:00
commit 660bcd1953

View File

@@ -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