Files
mealplanner/docs/superpowers/specs/2026-04-14-mealplanner-design.md
Claude 660bcd1953 docs: add mealplanner design spec
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 19:02:05 +00:00

209 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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