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:
56
frontend/src/lib/planner/VarietyScoreHero.svelte
Normal file
56
frontend/src/lib/planner/VarietyScoreHero.svelte
Normal file
@@ -0,0 +1,56 @@
|
||||
<script lang="ts">
|
||||
let {
|
||||
score
|
||||
}: {
|
||||
score: number;
|
||||
} = $props();
|
||||
|
||||
let percentage = $derived(Math.round((score / 10) * 100));
|
||||
|
||||
let description = $derived(
|
||||
score >= 9
|
||||
? { label: 'Ausgezeichnet', colorClass: 'text-[var(--green-dark)]' }
|
||||
: score >= 7
|
||||
? { label: 'Gut', colorClass: 'text-[var(--color-text)]' }
|
||||
: score >= 4
|
||||
? { label: 'Verbesserbar', colorClass: 'text-[var(--yellow-text)]' }
|
||||
: { label: 'Unzureichend', colorClass: 'text-[var(--color-error)]' }
|
||||
);
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<!-- Score number + out of 10 -->
|
||||
<div class="flex items-baseline gap-2">
|
||||
<span
|
||||
data-testid="score-value"
|
||||
class="font-[var(--font-display)] text-[56px] font-[300] leading-none text-[var(--color-text)] lg:text-[72px]"
|
||||
>
|
||||
{score}
|
||||
</span>
|
||||
<span
|
||||
data-testid="score-label"
|
||||
class="font-[var(--font-sans)] text-[16px] text-[var(--color-text-muted)]"
|
||||
>
|
||||
/ 10
|
||||
</span>
|
||||
<span
|
||||
data-testid="score-description"
|
||||
class="ml-1 font-[var(--font-sans)] text-[14px] font-medium {description.colorClass}"
|
||||
>
|
||||
{description.label}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- Progress bar -->
|
||||
<div class="mt-3 h-[6px] w-[120px] overflow-hidden rounded-full bg-[var(--color-border)] lg:w-[200px]">
|
||||
<div
|
||||
role="progressbar"
|
||||
aria-valuenow={score}
|
||||
aria-valuemin={0}
|
||||
aria-valuemax={10}
|
||||
aria-label="Abwechslungs-Score"
|
||||
class="h-full rounded-full bg-[var(--yellow)] transition-all"
|
||||
style="width: {percentage}%"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user