diff --git a/specs/frontend/c3-variety-rework-v1-spec.html b/specs/frontend/c3-variety-rework-v1-spec.html
new file mode 100644
index 0000000..bc80f9e
--- /dev/null
+++ b/specs/frontend/c3-variety-rework-v1-spec.html
@@ -0,0 +1,625 @@
+
+
+
+
+
+
+
+
+
+
+
+
1 · Überblick
+
Die Seite /planner/variety zeigt derzeit Warnkarten mit technischen Tages-Codes (MON, WED — erwäge einen Tausch). Der Planer muss manuell nachschlagen, welches Gericht an diesen Tagen eingeplant ist, und dann zurück zum Planer navigieren um es zu tauschen.
+
V1 "Erweiterte Karten" löst dies mit minimalem Umbauaufwand: Die Warnkarten erhalten eine strukturierte Zeile pro betroffenem Tag — mit Wochentag-Abkürzung, Rezeptname und direktem "Tauschen →" Link. Score-Hero, Bewertungsdetails und das Gesamt-Layout bleiben unverändert.
+
+
+
Scope
+
+ - Kein neues Backend-Endpoint — alle nötigen Daten sind bereits im weekPlan-Load vorhanden
+ - Kein Layout-Umbau — nur VarietyWarningCards.svelte und die Datenvorbereitung in +page.svelte ändern sich
+ - Protein-Grid und EffortBar bleiben wie bisher (Desktop)
+
+
+
+
+
+
+
+
2 · Aktueller Ist-Zustand und Problem
+
+
+ | Element | Aktuell | Soll (V1) |
+
+
+ | Warnkarte Inhalt |
+ title + explanation (String) |
+ Strukturierte Zeilen: Wochentag · Rezeptname · Tauschen-Link |
+
+
+ | Tages-Angabe |
+ API-Code MON, WED |
+ Abkürzung Mo, Mi |
+
+
+ | Rezeptname |
+ Fehlt |
+ Aus weekPlan.slots[].recipe.name |
+
+
+ | Tausch-Navigation |
+ Fehlt — Nutzer verlässt die Seite manuell |
+ /planner?week={weekStart}&swap={slotId} |
+
+
+ | Datenbasis |
+ computeWarnings() aus variety.ts |
+ Inline $derived.by() in +page.svelte, direkt aus API-Daten |
+
+
+
+
+
+
+
+
+
3 · Datenfluss
+
+
Alle nötigen Daten werden bereits im Server-Load geladen. Kein neuer API-Call erforderlich.
+
+
+ | Quelle | Feld | Verwendung |
+
+
+ | weekPlan.slots[] |
+ { id, dayOfWeek, recipe: { id, name } } |
+ Aufbau der slotsByDay-Map: DayCode → { slotId, recipeName } |
+
+
+ | varietyScore.tagRepeats[] |
+ { tagType, tagName, days: string[] } |
+ Warnkarten für wiederholte Tags (Protein, Cuisine). days[] enthält API-Codes: "MON", "TUE" … |
+
+
+ | varietyScore.ingredientOverlaps[] |
+ { ingredientName, days: string[] } |
+ Warnkarten für Zutaten-Überschneidungen |
+
+
+ | varietyScore.duplicatesInPlan[] |
+ string[] (Rezeptnamen) |
+ Warnkarte: "X doppelt geplant". Alle Slots mit diesem Rezeptnamen liefern die Items. |
+
+
+ | data.weekStart |
+ string (YYYY-MM-DD) |
+ Swap-URL-Parameter |
+
+
+
+
+
Tag-Code → Abkürzung Mapping (konstant):
+
// Day code → German short label
+const DAY_SHORT: Record<string, string> = {
+ MON: 'Mo', TUE: 'Di', WED: 'Mi',
+ THU: 'Do', FRI: 'Fr', SAT: 'Sa', SUN: 'So'
+};
+
+
+
+
+
+
4 · Typen
+
+
Die bestehende VarietyWarningCards.svelte definiert bereits die korrekten Interfaces. Diese bleiben unverändert:
+
+
// In VarietyWarningCards.svelte (bereits vorhanden, nicht ändern)
+interface WarningItem {
+ dayShort: string; // 'Mo', 'Di', …
+ recipeName: string; // aus weekPlan.slots[].recipe.name
+ slotId: number; // für Swap-Link
+}
+
+interface ActionWarning {
+ title: string; // z.B. "Tofu mehrfach diese Woche"
+ items: WarningItem[]; // eine Zeile pro betroffenem Tag
+}
+
+
Die alte Warning-Schnittstelle aus variety.ts ({ title, explanation }) wird nicht mehr verwendet.
+
+
+
+
+
+
5 · Implementierung
+
+
Es gibt drei Änderungen:
+
+
+
+
+
5.1
+
+page.svelte — slotsByDay Map aufbauen
+
+
+
Füge direkt nach den bestehenden $derived-Deklarationen hinzu:
+
const DAY_SHORT: Record<string, string> = {
+ MON: 'Mo', TUE: 'Di', WED: 'Mi',
+ THU: 'Do', FRI: 'Fr', SAT: 'Sa', SUN: 'So'
+};
+
+// dayOfWeek (API code) → { slotId, recipeName }
+let slotsByDay = $derived.by(() => {
+ const map: Record<string, { slotId: number; recipeName: string }> = {};
+ for (const slot of weekPlan?.slots ?? []) {
+ if (slot.dayOfWeek && slot.recipe?.name && slot.id) {
+ map[slot.dayOfWeek] = { slotId: slot.id, recipeName: slot.recipe.name };
+ }
+ }
+ return map;
+});
+
+
+
+
+
+
+
5.2
+
+page.svelte — actionWarnings ersetzen computeWarnings()
+
+
+
Ersetze den bestehenden let warnings = $derived.by(() => computeWarnings(…))-Block vollständig:
+
interface WarningItem { dayShort: string; recipeName: string; slotId: number; }
+interface ActionWarning { title: string; items: WarningItem[]; }
+
+let actionWarnings = $derived.by((): ActionWarning[] => {
+ const result: ActionWarning[] = [];
+ const vs = varietyScore;
+ if (!vs) return result;
+
+ // Tag repeats (protein, cuisine, …)
+ for (const repeat of vs.tagRepeats ?? []) {
+ if ((repeat.days?.length ?? 0) < 2) continue;
+ const items: WarningItem[] = (repeat.days ?? [])
+ .map((day) => {
+ const slot = slotsByDay[day];
+ return slot
+ ? { dayShort: DAY_SHORT[day] ?? day, recipeName: slot.recipeName, slotId: slot.slotId }
+ : null;
+ })
+ .filter((x): x is WarningItem => x !== null);
+ if (items.length > 0) {
+ result.push({ title: `${repeat.tagName} mehrfach diese Woche`, items });
+ }
+ }
+
+ // Ingredient overlaps
+ for (const overlap of vs.ingredientOverlaps ?? []) {
+ if ((overlap.days?.length ?? 0) < 2) continue;
+ const items: WarningItem[] = (overlap.days ?? [])
+ .map((day) => {
+ const slot = slotsByDay[day];
+ return slot
+ ? { dayShort: DAY_SHORT[day] ?? day, recipeName: slot.recipeName, slotId: slot.slotId }
+ : null;
+ })
+ .filter((x): x is WarningItem => x !== null);
+ if (items.length > 0) {
+ result.push({ title: `${overlap.ingredientName} in mehreren Gerichten`, items });
+ }
+ }
+
+ // Duplicate recipes — find all slots with that recipe name
+ for (const name of vs.duplicatesInPlan ?? []) {
+ const items: WarningItem[] = Object.entries(slotsByDay)
+ .filter(([, s]) => s.recipeName === name)
+ .map(([day, s]) => ({ dayShort: DAY_SHORT[day] ?? day, recipeName: s.recipeName, slotId: s.slotId }));
+ if (items.length > 0) {
+ result.push({ title: `${name} doppelt geplant`, items });
+ }
+ }
+
+ return result;
+});
+
+
+
+
+
+
+
5.3
+
+page.svelte — Template: warnings → actionWarnings, weekStart übergeben
+
+
+
An beiden Stellen im Template (Mobile + Desktop) ersetzen:
+
+
+page.svelte (Mobile, ~Zeile 110 / Desktop, ~Zeile 222)
+
- {#if warnings.length > 0}
+- <VarietyWarningCards {warnings} />
++ {#if actionWarnings.length > 0}
++ <VarietyWarningCards warnings={actionWarnings} {weekStart} />
+
+
Achtung: weekStart ist für die Swap-URL erforderlich und muss explizit übergeben werden.
+
+
+
+
+
+
+
5.4
+
+page.svelte — Import aufräumen
+
+
+
Entferne den nicht mehr genutzten Import:
+
+
+page.svelte (Script-Block, oben)
+
- import { computeSubScores, computeWarnings } from '$lib/planner/variety';
++ import { computeSubScores } from '$lib/planner/variety';
+
+
computeSubScores wird noch für die Score-Breakdown-Anzeige genutzt.
+
+
+
+
+
+
+
+
6 · VarietyWarningCards.svelte — bereits korrekt
+
+
Die Komponente wurde bereits auf das neue ActionWarning-Format aktualisiert. Keine Änderung erforderlich. Zur Referenz die erwartete Props-Schnittstelle:
+
+
// Props (bereits implementiert)
+let { warnings, weekStart }: {
+ warnings: ActionWarning[];
+ weekStart: string;
+} = $props();
+
+
Die Komponente rendert für jede Warnung:
+
+ - Gelbe Karte (
border: yellow-light, bg: yellow-tint) mit Header-Zeile (Titel)
+ - Pro Item: Zeile mit Wochentag-Abkürzung (W=20px, fixed) · Rezeptname (truncate) · "Tauschen →" Link (rechts)
+ - Swap-URL:
/planner?week={weekStart}&swap={item.slotId}
+
+
+
+
+
+
Warnkarte · Referenz-Darstellung
+
+
+
Tofu mehrfach diese Woche
+
+
MoTofu-Gemüse-Pfanne
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
Paprika in mehreren Gerichten
+
+
DiPaprika-Linsen-Eintopf
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
+
+
+
+
+
+
+
7 · Edge Cases
+
+
+ | Fall | Verhalten |
+
+
+ | Tag im tagRepeat hat keinen Slot |
+ Filter-Schritt (.filter(x => x !== null)) entfernt das Item. Warnkarte erscheint nur wenn ≥1 Item vorhanden. |
+
+
+ | weekPlan hat keine Slots (leere Woche) |
+ slotsByDay ist {}, actionWarnings ist []. Keine Warnkarten sichtbar. |
+
+
+ | varietyScore ist null |
+ Bestehende {#if !varietyScore}-Guard greift — actionWarnings wird nie gerendert. |
+
+
+ | Slot hat kein Rezept (slot.recipe === null) |
+ slot.recipe?.name ist undefined → Slot wird nicht in slotsByDay aufgenommen. |
+
+
+ | duplicatesInPlan: Rezeptname kommt in slotsByDay nicht vor |
+ items ist leer → Warnkarte wird nicht gepusht. |
+
+
+ | Unbekannter Tag-Code (z.B. zukünftige API-Erweiterung) |
+ DAY_SHORT[day] ?? day — Fallback auf den rohen Code. |
+
+
+ | Sehr langer Rezeptname |
+ CSS truncate auf .wcard-recipe — kein Überlauf, Swap-Link bleibt sichtbar. |
+
+
+
+
+
+
+
+
+
8 · Abnahmekriterien
+
+
+
Acceptance Criteria
+
+ - AC-1: Warnkarte zeigt pro betroffenem Tag eine eigene Zeile (nicht mehr einen langen Erklärungstext)
+ - AC-2: Jede Zeile enthält die deutsche Wochentag-Abkürzung (Mo, Di, Mi, Do, Fr, Sa, So)
+ - AC-3: Jede Zeile enthält den Namen des eingeplanten Rezepts
+ - AC-4: Jede Zeile enthält einen "Tauschen →" Link, der zu /planner?week={weekStart}&swap={slotId} führt
+ - AC-5: Tags mit nur einem betroffenen Tag (days.length < 2) erzeugen keine Warnkarte
+ - AC-6: Score-Hero, Bewertungsdetails und Protein-Grid (Desktop) bleiben unverändert
+ - AC-7: Wenn varietyScore null ist, werden keine Warnkarten gerendert (leere-Woche-State bleibt)
+ - AC-8: Der Import von computeWarnings ist entfernt, TypeScript kompiliert fehlerfrei
+ - AC-9: Auf Mobilgerät sind Tausch-Links touch-freundlich (mind. 44px Zeilenhöhe)
+
+
+
+
+
Nicht in Scope
+
+ - Neues Backend-Endpoint — alle Daten kommen aus dem bestehenden Load
+ - Layout-Umbau der Seite — Score bleibt oben, Warnungen unten wie bisher
+ - Protein-Grid oder EffortBar Änderungen
+ - computeSubScores aus variety.ts — bleibt unverändert
+ - Entfernen von computeWarnings aus variety.ts (Funktion bleibt, wird nur nicht mehr aufgerufen)
+
+
+
+
+
+
+
+
9 · Betroffene Dateien
+
+
+ | Datei | Änderung |
+
+
+ | frontend/src/routes/(app)/planner/variety/+page.svelte |
+ DAY_SHORT-Konstante, slotsByDay-Derived, actionWarnings-Derived, Template-Update (2×), Import-Bereinigung |
+
+
+ | frontend/src/lib/planner/VarietyWarningCards.svelte |
+ Keine — bereits auf ActionWarning-Format aktualisiert |
+
+
+ | frontend/src/lib/planner/variety.ts |
+ Keine — computeWarnings bleibt (ungenutzt, aber nicht entfernen um Regressions-Risiko zu vermeiden) |
+
+
+
+
+
+
+
+
+
LLM-Agent-Lesbereich
+
Dieser Abschnitt enthält maschinenlesbare Regeln für einen KI-Agenten der die Implementierung durchführt.
+
+
SCREEN: C3 /planner/variety
+VARIATION: V1 "Erweiterte Karten"
+STATUS: Final spec — ready for implementation
+
+FILES TO MODIFY:
+ frontend/src/routes/(app)/planner/variety/+page.svelte
+
+FILES NOT TO MODIFY:
+ frontend/src/lib/planner/VarietyWarningCards.svelte (already correct)
+ frontend/src/lib/planner/variety.ts (keep computeWarnings, remove only import)
+
+STEP 1 — Add DAY_SHORT constant (in <script> block, after imports):
+ const DAY_SHORT: Record<string, string> = {
+ MON: 'Mo', TUE: 'Di', WED: 'Mi',
+ THU: 'Do', FRI: 'Fr', SAT: 'Sa', SUN: 'So'
+ };
+
+STEP 2 — Add slotsByDay derived (after $derived declarations for weekPlan, etc.):
+ let slotsByDay = $derived.by(() => {
+ const map: Record<string, { slotId: number; recipeName: string }> = {};
+ for (const slot of weekPlan?.slots ?? []) {
+ if (slot.dayOfWeek && slot.recipe?.name && slot.id) {
+ map[slot.dayOfWeek] = { slotId: slot.id, recipeName: slot.recipe.name };
+ }
+ }
+ return map;
+ });
+
+STEP 3 — Define inline interfaces + actionWarnings derived:
+ interface WarningItem { dayShort: string; recipeName: string; slotId: number; }
+ interface ActionWarning { title: string; items: WarningItem[]; }
+
+ let actionWarnings = $derived.by((): ActionWarning[] => {
+ const result: ActionWarning[] = [];
+ const vs = varietyScore;
+ if (!vs) return result;
+
+ for (const repeat of vs.tagRepeats ?? []) {
+ if ((repeat.days?.length ?? 0) < 2) continue;
+ const items: WarningItem[] = (repeat.days ?? [])
+ .map((day) => {
+ const slot = slotsByDay[day];
+ return slot ? { dayShort: DAY_SHORT[day] ?? day, recipeName: slot.recipeName, slotId: slot.slotId } : null;
+ })
+ .filter((x): x is WarningItem => x !== null);
+ if (items.length > 0) result.push({ title: `${repeat.tagName} mehrfach diese Woche`, items });
+ }
+
+ for (const overlap of vs.ingredientOverlaps ?? []) {
+ if ((overlap.days?.length ?? 0) < 2) continue;
+ const items: WarningItem[] = (overlap.days ?? [])
+ .map((day) => {
+ const slot = slotsByDay[day];
+ return slot ? { dayShort: DAY_SHORT[day] ?? day, recipeName: slot.recipeName, slotId: slot.slotId } : null;
+ })
+ .filter((x): x is WarningItem => x !== null);
+ if (items.length > 0) result.push({ title: `${overlap.ingredientName} in mehreren Gerichten`, items });
+ }
+
+ for (const name of vs.duplicatesInPlan ?? []) {
+ const items: WarningItem[] = Object.entries(slotsByDay)
+ .filter(([, s]) => s.recipeName === name)
+ .map(([day, s]) => ({ dayShort: DAY_SHORT[day] ?? day, recipeName: s.recipeName, slotId: s.slotId }));
+ if (items.length > 0) result.push({ title: `${name} doppelt geplant`, items });
+ }
+
+ return result;
+ });
+
+STEP 4 — Replace template occurrences (both mobile and desktop sections):
+ OLD: {#if warnings.length > 0} / <VarietyWarningCards {warnings} />
+ NEW: {#if actionWarnings.length > 0} / <VarietyWarningCards warnings={actionWarnings} {weekStart} />
+
+STEP 5 — Fix import:
+ OLD: import { computeSubScores, computeWarnings } from '$lib/planner/variety';
+ NEW: import { computeSubScores } from '$lib/planner/variety';
+
+INVARIANTS (do not change):
+ - VarietyScoreHero, ScoreBreakdownList, EffortBar remain untouched
+ - Desktop protein grid (proteinByDay) remains untouched
+ - Layout structure (score top, warnings bottom) stays identical
+ - No new server load or API calls
+
+
+
+
+
diff --git a/specs/frontend/c3-variety-rework.html b/specs/frontend/c3-variety-rework.html
new file mode 100644
index 0000000..cc51098
--- /dev/null
+++ b/specs/frontend/c3-variety-rework.html
@@ -0,0 +1,790 @@
+
+
+
+
+
+
+
+
+
+
+
Problem
+
Die aktuelle Seite zeigt Warnungen wie "MON, WED — erwäge einen Tausch". Der Planer muss selbst nachschlagen, welches Gericht an Montag und Mittwoch geplant ist, und dann manuell zum Planer navigieren um zu tauschen. Zwei Probleme:
+
1. Keine Rezeptnamen — Tag-Codes statt echter Gerichte. 2. Kein direkter Tausch — der Planer muss die Seite verlassen, zurück zum Planer, das richtige Gericht suchen und dann tauschen.
+
+
+
+
+
+
+
V1
+
+
Variation 1
+
Erweiterte Karten
+
Minimale Änderung: bestehende gelbe Karten bleiben, aber der Text wird durch strukturierte Zeilen ersetzt — eine pro betroffenem Gericht, mit Wochentag, Rezeptname und "Tauschen →" Link. Score-Bereich und Layout bleiben unverändert.
+
+
+
+
+
+
+
+
Mobile · 320px
+
+
9:41●●●
+
+
+
‹
+
Abwechslungs-Analyse
+
+
+
+
+
+
+ 5.8
+ / 10
+ Verbesserbar
+
+
+
+
+
+
+
Bewertung im Detail
+
Quellen-Vielfalt4 / 10
+
Zutaten-Überschneidung7 / 10
+
Aufwandsbalance8 / 10
+
+
+
+
Hinweise
+
+
+
Tofu mehrfach diese Woche
+
+
MoTofu-Gemüse-Pfanne
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
+
Paprika in mehreren Gerichten
+
+
DiPaprika-Linsen-Eintopf
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
+
+
+
+
+
+
+
Desktop · 1040px
+
+
+
+
+
Planung
+
📅 Wochenplan
+
🛒 Einkaufsliste
+
🍳 Rezepte
+
Haushalt
+
⚙️ Einstellungen
+
+
+
+
+ Planer /
+ Abwechslungs-Analyse
+
+
+
+
+
+
+
+ 5.8
+ / 10
+ Verbesserbar
+
+
+
+
Bewertung im Detail
+
Quellen-Vielfalt4 / 10
+
Zutaten-Überschneidung7 / 10
+
Aufwandsbalance8 / 10
+
+
+
+
+
Hinweise
+
+
Tofu mehrfach diese Woche
+
+
MoTofu-Gemüse-Pfanne
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
Paprika in mehreren Gerichten
+
+
DiPaprika-Linsen-Eintopf
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
+
+
+
+
+
+
+
+
Design-Notizen V1
+
+ - Geringster Umbauaufwand — nur VarietyWarningCards.svelte ändert sich, keine Layout-Umstrukturierung.
+ - Behält die bekannte Score-Hierarchie bei: Zahl oben, dann Detail, dann Hinweise.
+ - Schwachstelle: Hinweise sind trotzdem am Ende der Seite versteckt — auf kurzen Telefon-Bildschirmen muss gescrollt werden, bevor der Planer die Tausch-Links sieht.
+ - Die Sub-Scores bleiben immer sichtbar, auch wenn der Planer nur die Tausch-Aktionen braucht.
+
+
+
+
+
+
+
+
+
+
+
V2
+
+
Variation 2 · Empfohlen
+
Aktions-Liste
+
Hinweise rücken nach oben — direkt unter dem Score. Der Planer sieht sofort, was zu tun ist. Sub-Scores wandern in ein ausklappbares "Bewertung im Detail" (native <details>, kein JS). Kompakterer Score-Hero gibt Hinweisen mehr Raum.
+
+
+
+
+
+
+
+
Mobile · 320px
+
+
9:41●●●
+
+
‹
+
Abwechslungs-Analyse
+
+
+
+
+
+
+
+
2 Hinweise
+
+
+
Tofu mehrfach diese Woche
+
+
MoTofu-Gemüse-Pfanne
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
+
Paprika in mehreren Gerichten
+
+
DiPaprika-Linsen-Eintopf
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
+
+ Bewertung im Detail
+
+
Quellen-Vielfalt4 / 10
+
Zutaten-Überschneidung7 / 10
+
Aufwandsbalance8 / 10
+
+
+
+
+
+
+
+
+
+
+
Desktop · 1040px
+
+
+
+
+
Planung
+
📅 Wochenplan
+
🛒 Einkaufsliste
+
🍳 Rezepte
+
Haushalt
+
⚙️ Einstellungen
+
+
+
+
+ Planer /
+ Abwechslungs-Analyse
+
+
+
+
+
+ 5.8
+ / 10
+
+
+
Verbesserbar — 2 Hinweise
+
+
+
+
+
+
+
Hinweise
+
+
+
Tofu mehrfach diese Woche
+
+
MoTofu-Gemüse-Pfanne
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
Paprika in mehreren Gerichten
+
+
DiPaprika-Linsen-Eintopf
+
Tauschen →
+
+
+
MiTofu-Curry mit Reis
+
Tauschen →
+
+
+
+
+
+
+
+
+
+
+
Design-Notizen V2
+
+ - Hinweise erscheinen direkt unter dem Score — kein Scrollen nötig auf typischen Telefon-Bildschirmen.
+ - Kompakter Score-Strip auf Mobile spart ~80px gegenüber dem aktuellen großen Hero — mehr Raum für die eigentlichen Tausch-Aktionen.
+ - Desktop: Sub-Scores werden als kompakte Zahlen-Spalte in die Score-Leiste integriert — kein separater Abschnitt mehr nötig.
+ - Native <details> auf Mobile braucht kein JavaScript; funktioniert auch ohne hydration.
+ - "2 Hinweise" im Score-Strip auf Desktop gibt dem Planer sofort Kontext, ohne zu scrollen.
+
+
+
+
+
+
+
+
+
+
+
V3
+
+
Variation 3
+
Hinweise zuerst
+
Invertiertes Layout: die Seite öffnet mit den konkreten Problem-Karten — groß und klar. Score und Breakdown erscheinen darunter als unterstützende Information. Jede Warnung ist eine eigenständige "Aufgaben-Karte" mit prominentem Tausch-Button statt Link.
+
+
+
+
+
+
+
+
Mobile · 320px
+
+
9:41●●●
+
+
‹
+
Abwechslungs-Analyse
+
+
+
+
+
Was zu tun ist
+
+
+
+
+
Quellen-Wiederholung
+
Tofu an 2 Tagen
+
+
+
+
+
Montag
+
Tofu-Gemüse-Pfanne
+
+
Tauschen
+
+
+
+
+
Mittwoch
+
Tofu-Curry mit Reis
+
+
Tauschen
+
+
+
+
+
+
+
Zutaten-Überschneidung
+
Paprika an 2 aufeinanderfolgenden Tagen
+
+
+
+
Dienstag
+
Paprika-Linsen-Eintopf
+
+
Tauschen
+
+
+
+
Mittwoch
+
Tofu-Curry mit Reis
+
+
Tauschen
+
+
+
+
+
+
Gesamt-Score
+
+ 5.8
+ / 10 · Verbesserbar
+
+
+
+
+ Aufschlüsselung anzeigen
+
+
Quellen-Vielfalt4 / 10
+
Zutaten-Überschneidung7 / 10
+
Aufwandsbalance8 / 10
+
+
+
+
+
+
+
+
+
+
+
+
+
Desktop · 1040px
+
+
+
+
+
Planung
+
📅 Wochenplan
+
🛒 Einkaufsliste
+
🍳 Rezepte
+
Haushalt
+
⚙️ Einstellungen
+
+
+
+
+ Planer /
+ Abwechslungs-Analyse
+
+
+
+
+
+
Was zu tun ist
+
+
+
+
Quellen-Wiederholung
+
Tofu an 2 Tagen
+
+
+
+ Montag
+ Tofu-Gemüse-Pfanne
+
+
Tauschen
+
+
+
+ Mittwoch
+ Tofu-Curry mit Reis
+
+
Tauschen
+
+
+
+
+
+
Zutaten-Überschneidung
+
Paprika an 2 aufeinanderfolgenden Tagen
+
+
+
+ Dienstag
+ Paprika-Linsen-Eintopf
+
+
Tauschen
+
+
+
+ Mittwoch
+ Tofu-Curry mit Reis
+
+
Tauschen
+
+
+
+
+
+
+
+
Score
+
+ 5.8
+ / 10
+
+
Verbesserbar
+
+
+
+
Aufschlüsselung
+
Quellen4 / 10
+
Zutaten7 / 10
+
Aufwand8 / 10
+
+
+
+
+
+
+
+
+
+
+
Design-Notizen V3
+
+ - Klarer Fokus: Das erste, was der Planer sieht, ist "Was zu tun ist" — keine Score-Hierarchie die von der Aktion ablenkt.
+ - Prominente "Tauschen"-Buttons (gefüllt, dunkelgelb) statt Links — erhöht die Tipp-Fläche auf Mobile und macht die Aktion offensichtlicher.
+ - Voller Wochentag ("Montag" statt "Mo") — lesbarer, besonders auf Desktop.
+ - Schwachstelle: Wenn es keine Hinweise gibt (Score ≥ 9), wirkt die Seite leer — der Score müsste dann nach oben rücken. Erfordert einen separaten Empty-State.
+ - Höherer Umbauaufwand gegenüber V1 und V2 — die Page-Struktur ändert sich grundlegend.
+
+
+
+
+
+
+
+
+
Vergleich
+
+
+
+ | Kriterium |
+ V1 Erweiterte Karten |
+ V2 Aktions-Liste ★ |
+ V3 Hinweise zuerst |
+
+
+
+
+ | Rezeptnamen sichtbar |
+ ✓ Ja |
+ ✓ Ja |
+ ✓ Ja, prominent |
+
+
+ | Direkter Tausch |
+ Link |
+ Link |
+ Button (größere Tap-Fläche) |
+
+
+ | Hinweise sichtbar ohne Scrollen |
+ Nein (Score + Breakdown zuerst) |
+ Ja (direkt unter kompaktem Score) |
+ Ja (ganz oben) |
+
+
+ | Umbauaufwand |
+ Niedrig |
+ Mittel |
+ Hoch |
+
+
+ | Layout-Änderung |
+ Keine |
+ Score kompakter, Details kollabierbar |
+ Grundlegende Umstrukturierung |
+
+
+ | Empfehlung |
+ Wenn schnelle Lieferung Prio |
+ Empfohlen ★ |
+ Wenn Aktions-Fokus Prio |
+
+
+
+
+
+
+
+