fix: meal planner auto-selects current week on load, + New week idempotent
- Add autoSelectPlan() to the store: after loadPlans() resolves, set activePlan to the current week's plan (or most recent) without a second API round-trip -- list already returns full PlanSummary with slots - Call autoSelectPlan(mondayOfCurrentWeek()) in onMounted so the grid populates immediately without the user touching the dropdown - Make onNewPlan idempotent: if a 409 comes back, activate the existing plan for that week instead of surfacing an error to the user
This commit is contained in:
parent
dbaf2b6ac8
commit
de0008f5c7
2 changed files with 29 additions and 7 deletions
|
|
@ -101,7 +101,10 @@ const canAddMealType = computed(() =>
|
||||||
(activePlan.value?.meal_types.length ?? 0) < 4
|
(activePlan.value?.meal_types.length ?? 0) < 4
|
||||||
)
|
)
|
||||||
|
|
||||||
onMounted(() => store.loadPlans())
|
onMounted(async () => {
|
||||||
|
await store.loadPlans()
|
||||||
|
store.autoSelectPlan(mondayOfCurrentWeek())
|
||||||
|
})
|
||||||
|
|
||||||
function mondayOfCurrentWeek(): string {
|
function mondayOfCurrentWeek(): string {
|
||||||
const today = new Date()
|
const today = new Date()
|
||||||
|
|
@ -116,15 +119,20 @@ function mondayOfCurrentWeek(): string {
|
||||||
async function onNewPlan() {
|
async function onNewPlan() {
|
||||||
planError.value = null
|
planError.value = null
|
||||||
planCreating.value = true
|
planCreating.value = true
|
||||||
|
const weekStart = mondayOfCurrentWeek()
|
||||||
try {
|
try {
|
||||||
const weekStart = mondayOfCurrentWeek()
|
|
||||||
await store.createPlan(weekStart, ['dinner'])
|
await store.createPlan(weekStart, ['dinner'])
|
||||||
} catch (err: unknown) {
|
} catch (err: unknown) {
|
||||||
const msg = err instanceof Error ? err.message : String(err)
|
const msg = err instanceof Error ? err.message : String(err)
|
||||||
// 409 means a plan for this week already exists — surface it helpfully
|
if (msg.includes('409') || msg.toLowerCase().includes('already exists')) {
|
||||||
planError.value = msg.includes('409') || msg.toLowerCase().includes('already exists')
|
// Plan for this week exists — just activate it instead of erroring
|
||||||
? 'A plan for this week already exists. Select it from the dropdown above.'
|
const existing = plans.value.find(p => p.week_start === weekStart)
|
||||||
: `Couldn't create plan: ${msg}`
|
if (existing) {
|
||||||
|
await store.setActivePlan(existing.id)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
planError.value = `Couldn't create plan: ${msg}`
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
planCreating.value = false
|
planCreating.value = false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,20 @@ export const useMealPlanStore = defineStore('mealPlan', () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Auto-select the best available plan without a round-trip.
|
||||||
|
* Prefers the plan whose week_start matches preferredWeekStart (current week's Monday).
|
||||||
|
* Falls back to the first plan in the list (most recent, since list is DESC).
|
||||||
|
* No-ops if a plan is already active or no plans exist.
|
||||||
|
*/
|
||||||
|
function autoSelectPlan(preferredWeekStart?: string) {
|
||||||
|
if (activePlan.value || plans.value.length === 0) return
|
||||||
|
const match = preferredWeekStart
|
||||||
|
? (plans.value.find(p => p.week_start === preferredWeekStart) ?? plans.value[0])
|
||||||
|
: plans.value[0]
|
||||||
|
if (match) activePlan.value = match ?? null
|
||||||
|
}
|
||||||
|
|
||||||
async function createPlan(weekStart: string, mealTypes: string[]): Promise<MealPlan> {
|
async function createPlan(weekStart: string, mealTypes: string[]): Promise<MealPlan> {
|
||||||
const plan = await mealPlanAPI.create(weekStart, mealTypes)
|
const plan = await mealPlanAPI.create(weekStart, mealTypes)
|
||||||
plans.value = [plan, ...plans.value]
|
plans.value = [plan, ...plans.value]
|
||||||
|
|
@ -129,7 +143,7 @@ export const useMealPlanStore = defineStore('mealPlan', () => {
|
||||||
return {
|
return {
|
||||||
plans, activePlan, shoppingList, prepSession,
|
plans, activePlan, shoppingList, prepSession,
|
||||||
loading, shoppingListLoading, prepLoading, slots,
|
loading, shoppingListLoading, prepLoading, slots,
|
||||||
getSlot, loadPlans, createPlan, setActivePlan,
|
getSlot, loadPlans, autoSelectPlan, createPlan, setActivePlan,
|
||||||
upsertSlot, clearSlot, loadShoppingList, loadPrepSession, updatePrepTask,
|
upsertSlot, clearSlot, loadShoppingList, loadPrepSession, updatePrepTask,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue