feat(suggestions): implement C2 meal suggestion screen (Issue #27) Co-authored-by: Marcel Raddatz <marcel@raddatz.cloud> Co-committed-by: Marcel Raddatz <marcel@raddatz.cloud>
84 lines
2.4 KiB
Svelte
84 lines
2.4 KiB
Svelte
<script lang="ts">
|
|
interface SlotRecipe {
|
|
id?: string;
|
|
name?: string;
|
|
effort?: string;
|
|
cookTimeMin?: number;
|
|
}
|
|
|
|
interface Suggestion {
|
|
recipe?: SlotRecipe;
|
|
simulatedScore?: number;
|
|
reasoningType?: 'good' | 'warning';
|
|
reasoningLabel?: string;
|
|
}
|
|
|
|
let {
|
|
suggestion,
|
|
rank,
|
|
planId,
|
|
slotDate,
|
|
weekStart
|
|
}: {
|
|
suggestion: Suggestion;
|
|
rank: number;
|
|
planId: string;
|
|
slotDate: string;
|
|
weekStart: string;
|
|
} = $props();
|
|
|
|
let metadata = $derived(
|
|
[
|
|
suggestion.recipe?.cookTimeMin != null ? `${suggestion.recipe.cookTimeMin} Min` : null,
|
|
suggestion.recipe?.effort ?? null
|
|
]
|
|
.filter(Boolean)
|
|
.join(' · ')
|
|
);
|
|
</script>
|
|
|
|
<div class="flex items-start gap-3 rounded-[var(--radius-md)] border border-[var(--color-border)] bg-[var(--color-surface)] px-4 py-3 shadow-[var(--shadow-card)]">
|
|
<!-- Rank number -->
|
|
<div class="w-10 flex-shrink-0 self-start text-right">
|
|
<span class="font-[var(--font-display)] text-[32px] font-[300] leading-none text-[var(--color-text-muted)]">{rank}</span>
|
|
</div>
|
|
|
|
<!-- Card content -->
|
|
<div class="flex-1 min-w-0">
|
|
<p class="font-[var(--font-sans)] text-[15px] font-medium text-[var(--color-text)] line-clamp-2">
|
|
{suggestion.recipe?.name ?? 'Unbekanntes Rezept'}
|
|
</p>
|
|
{#if metadata}
|
|
<p class="mt-0.5 font-[var(--font-sans)] text-[12px] text-[var(--color-text-muted)]">{metadata}</p>
|
|
{/if}
|
|
|
|
<!-- Reasoning badge -->
|
|
{#if suggestion.reasoningType && suggestion.reasoningLabel}
|
|
<div
|
|
data-testid="reasoning-badge"
|
|
data-type={suggestion.reasoningType}
|
|
class="mt-2 inline-flex items-center rounded-full px-2 py-0.5 font-[var(--font-sans)] text-[11px] font-medium
|
|
{suggestion.reasoningType === 'good'
|
|
? 'bg-[var(--green-tint)] text-[var(--green-dark)]'
|
|
: 'bg-[var(--yellow-tint)] text-[var(--yellow-text)]'}"
|
|
>
|
|
{suggestion.reasoningType === 'good' ? '✓' : '⚠'} {suggestion.reasoningLabel}
|
|
</div>
|
|
{/if}
|
|
</div>
|
|
|
|
<!-- Pick action -->
|
|
<form method="POST" action="?/pickSuggestion" class="flex-shrink-0">
|
|
<input type="hidden" name="planId" value={planId} />
|
|
<input type="hidden" name="recipeId" value={suggestion.recipe?.id} />
|
|
<input type="hidden" name="slotDate" value={slotDate} />
|
|
<input type="hidden" name="weekStart" value={weekStart} />
|
|
<button
|
|
type="submit"
|
|
class="font-[var(--font-sans)] text-[13px] font-medium tracking-[0.04em] text-[var(--green-dark)] hover:underline"
|
|
>
|
|
Wählen
|
|
</button>
|
|
</form>
|
|
</div>
|