feat(planner): add EmptyDayTile component
Dashed-border empty slot tile with + Gericht wählen CTA and lazy reasoning tags (Neues Protein, Aufwand: leicht) derived from topSuggestion prop via computeReasoningTags. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
89
frontend/src/lib/planner/EmptyDayTile.svelte
Normal file
89
frontend/src/lib/planner/EmptyDayTile.svelte
Normal file
@@ -0,0 +1,89 @@
|
||||
<script lang="ts">
|
||||
import { computeReasoningTags } from './reasoningTags';
|
||||
|
||||
interface TagItem {
|
||||
id?: string;
|
||||
name?: string;
|
||||
tagType?: string;
|
||||
}
|
||||
|
||||
interface SuggestionRecipe {
|
||||
id: string;
|
||||
name: string;
|
||||
cookTimeMin?: number;
|
||||
effort?: string;
|
||||
tags?: TagItem[];
|
||||
}
|
||||
|
||||
interface TopSuggestion {
|
||||
recipe: SuggestionRecipe;
|
||||
scoreDelta: number;
|
||||
hasConflict: boolean;
|
||||
}
|
||||
|
||||
interface Slot {
|
||||
id?: string;
|
||||
slotDate?: string;
|
||||
recipe?: any | null;
|
||||
}
|
||||
|
||||
let {
|
||||
slotDate,
|
||||
slotId,
|
||||
isPlanner,
|
||||
slotMap,
|
||||
topSuggestion,
|
||||
onaddrecipe
|
||||
}: {
|
||||
slotDate: string;
|
||||
slotId: string;
|
||||
isPlanner: boolean;
|
||||
slotMap: Record<string, Slot>;
|
||||
topSuggestion?: TopSuggestion;
|
||||
onaddrecipe?: () => void;
|
||||
} = $props();
|
||||
|
||||
let reasoningTags = $derived(
|
||||
topSuggestion ? computeReasoningTags(slotMap, topSuggestion.recipe) : []
|
||||
);
|
||||
</script>
|
||||
|
||||
<div
|
||||
data-testid="empty-day-tile"
|
||||
role="group"
|
||||
class="h-full flex flex-col gap-2 p-3"
|
||||
style="border: 1px dashed var(--color-border);"
|
||||
>
|
||||
{#if isPlanner}
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Gericht wählen"
|
||||
onclick={() => onaddrecipe?.()}
|
||||
class="self-start font-[var(--font-sans)] text-[13px] text-[var(--color-text-muted)] hover:text-[var(--color-text)] transition-colors"
|
||||
>
|
||||
+ Gericht wählen
|
||||
</button>
|
||||
{/if}
|
||||
|
||||
{#if topSuggestion}
|
||||
<p class="font-[var(--font-display)] text-[12px] text-[var(--color-text-muted)] leading-snug">
|
||||
{topSuggestion.recipe.name}
|
||||
</p>
|
||||
|
||||
{#if reasoningTags.length > 0}
|
||||
<div class="flex flex-wrap gap-1">
|
||||
{#each reasoningTags as tag (tag.id)}
|
||||
<span
|
||||
data-testid="reasoning-tag"
|
||||
class="inline-block rounded px-1.5 py-0.5 font-[var(--font-sans)] text-[11px] font-medium"
|
||||
style={tag.color === 'green'
|
||||
? 'background: var(--green-tint); color: var(--green-dark);'
|
||||
: 'background: var(--yellow-tint); color: var(--yellow-text);'}
|
||||
>
|
||||
{tag.label}
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
</div>
|
||||
Reference in New Issue
Block a user