feat(variety): implement C3 variety review screen (Issue #28)

- Add /planner/variety route with mobile stacked + desktop 2-column layout
- Implement VarietyScoreHero: Fraunces score display + progress bar + color-coded description
- Implement ScoreBreakdownList: 3 sub-score rows (protein diversity, ingredient overlap, effort balance)
- Implement VarietyWarningCards: yellow-tint warning cards derived from API tagRepeats/ingredientOverlaps
- Implement EffortBar: proportional colored segments (Easy/Medium/Hard) with ×N labels
- Desktop: protein grid (7 columns, repeat highlight with yellow ring) + effort bar in right panel
- Client-side sub-score derivation from VarietyScoreResponse (tagged for TODO to move to API)
- 26 new tests across 5 components + server load function; 455 tests total, 0 type errors

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 11:23:29 +02:00
parent 7c07bc443b
commit 8ad636f825
11 changed files with 727 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
<script lang="ts">
let {
easy,
medium,
hard
}: {
easy: number;
medium: number;
hard: number;
} = $props();
let total = $derived(easy + medium + hard);
</script>
<!-- Labels below the bar -->
<div class="space-y-2">
<!-- Bar segments -->
<div class="flex h-[10px] overflow-hidden rounded-full">
{#if easy > 0}
<div
class="h-full bg-[var(--green)]"
style="flex: {easy}"
></div>
{/if}
{#if medium > 0}
<div
class="h-full bg-[var(--yellow)]"
style="flex: {medium}"
></div>
{/if}
{#if hard > 0}
<div
class="h-full bg-[var(--color-error)]"
style="flex: {hard}"
></div>
{/if}
</div>
<!-- Labels -->
<div class="flex gap-4">
{#if easy > 0}
<span
data-testid="effort-easy"
class="font-[var(--font-sans)] text-[12px] text-[var(--green-dark)]"
>
Einfach ×{easy}
</span>
{/if}
{#if medium > 0}
<span
data-testid="effort-medium"
class="font-[var(--font-sans)] text-[12px] text-[var(--yellow-text)]"
>
Mittel ×{medium}
</span>
{/if}
{#if hard > 0}
<span
data-testid="effort-hard"
class="font-[var(--font-sans)] text-[12px] text-[var(--color-error)]"
>
Aufwändig ×{hard}
</span>
{/if}
</div>
</div>