feat(planner): lazy-fetch variety suggestions in RecipePicker for empty slots
Derives activePickerDate from mobile pickerOpen/selectedDay and desktop recipe-picker panel state, then uses $effect to fetch /planner?planId&date on demand — wires suggestions and isLoading into both RecipePicker instances. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -63,6 +63,15 @@
|
|||||||
let swapSheetOpen = $state(false);
|
let swapSheetOpen = $state(false);
|
||||||
let swapLoading = $state(false);
|
let swapLoading = $state(false);
|
||||||
|
|
||||||
|
const activePickerDate = $derived(
|
||||||
|
pickerOpen ? selectedDay
|
||||||
|
: panelState.kind === 'recipe-picker' ? panelState.date
|
||||||
|
: null
|
||||||
|
);
|
||||||
|
|
||||||
|
let suggestions: any[] = $state([]);
|
||||||
|
let isLoadingSuggestions = $state(false);
|
||||||
|
|
||||||
// Recipes already in any slot this week — used for ⚠ overlap warnings
|
// Recipes already in any slot this week — used for ⚠ overlap warnings
|
||||||
let currentWeekRecipeIds = $derived(
|
let currentWeekRecipeIds = $derived(
|
||||||
new Set<string>(slots.filter((s: any) => s.recipe?.id).map((s: any) => s.recipe.id))
|
new Set<string>(slots.filter((s: any) => s.recipe?.id).map((s: any) => s.recipe.id))
|
||||||
@@ -91,6 +100,20 @@
|
|||||||
let undoVisible = $state(false);
|
let undoVisible = $state(false);
|
||||||
let undoMessage = $state('');
|
let undoMessage = $state('');
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
if (!activePickerDate || !weekPlan?.id) {
|
||||||
|
suggestions = [];
|
||||||
|
isLoadingSuggestions = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
isLoadingSuggestions = true;
|
||||||
|
fetch(`/planner?planId=${weekPlan.id}&date=${activePickerDate}`)
|
||||||
|
.then((r) => r.json())
|
||||||
|
.then((d) => { suggestions = d.suggestions ?? []; })
|
||||||
|
.catch(() => { suggestions = []; })
|
||||||
|
.finally(() => { isLoadingSuggestions = false; });
|
||||||
|
});
|
||||||
|
|
||||||
function handleSelectDay(day: string) {
|
function handleSelectDay(day: string) {
|
||||||
selectedDay = day;
|
selectedDay = day;
|
||||||
panelState = { kind: 'day-detail', date: day };
|
panelState = { kind: 'day-detail', date: day };
|
||||||
@@ -282,9 +305,9 @@
|
|||||||
planId={weekPlan?.id ?? ''}
|
planId={weekPlan?.id ?? ''}
|
||||||
date={selectedDay}
|
date={selectedDay}
|
||||||
dateLabel={formatDayLabel(selectedDay)}
|
dateLabel={formatDayLabel(selectedDay)}
|
||||||
currentVarietyScore={varietyScore?.score ?? 0}
|
suggestions={suggestions}
|
||||||
suggestions={[]}
|
|
||||||
allRecipes={data.recipes}
|
allRecipes={data.recipes}
|
||||||
|
isLoading={isLoadingSuggestions}
|
||||||
onpick={handleRecipePick}
|
onpick={handleRecipePick}
|
||||||
/>
|
/>
|
||||||
</BottomSheet>
|
</BottomSheet>
|
||||||
@@ -560,9 +583,9 @@
|
|||||||
planId={weekPlan?.id ?? ''}
|
planId={weekPlan?.id ?? ''}
|
||||||
date={pickerDate}
|
date={pickerDate}
|
||||||
dateLabel={formatDayLabel(pickerDate)}
|
dateLabel={formatDayLabel(pickerDate)}
|
||||||
currentVarietyScore={varietyScore?.score ?? 0}
|
suggestions={suggestions}
|
||||||
suggestions={[]}
|
|
||||||
allRecipes={data.recipes}
|
allRecipes={data.recipes}
|
||||||
|
isLoading={isLoadingSuggestions}
|
||||||
onpick={handleRecipePick}
|
onpick={handleRecipePick}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user