- Fix logic bug `{#if !isPlanner === false}` - view/cook buttons now visible for all roles, swap only for planner
- Convert Tauschen from dead button to link with suggestions href
- Add week.ts unit tests (23 tests covering getWeekStart Sunday edge case, prevWeek/nextWeek, weekDays, isToday, formatWeekRange)
- Fix isToday to use UTC consistently (.toISOString().slice(0,10)) instead of local date
- Add server-side role guard to createPlan action (403 for members)
- Add weekStart format validation in createPlan action
- Add isSelected prop to DayMealCard with green treatment
- Make variety banner sticky on mobile (always visible per spec)
- Add day name abbreviation above date badge in desktop column headers
- Remove placeholder Navigation text from desktop sidebar
- Add aria-label to desktop empty tile buttons
- Add variety score partial failure test, multiple overlaps test, WeekStrip today+selected test
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
56 lines
1.5 KiB
TypeScript
56 lines
1.5 KiB
TypeScript
import type { PageServerLoad, Actions } from './$types';
|
|
import { apiClient } from '$lib/server/api';
|
|
import { getWeekStart } from '$lib/planner/week';
|
|
|
|
export const load: PageServerLoad = async ({ fetch, url }) => {
|
|
const weekParam = url.searchParams.get('week');
|
|
const weekStart = weekParam ?? getWeekStart(new Date());
|
|
|
|
const api = apiClient(fetch);
|
|
const { data: weekPlan, error } = await api.GET('/v1/week-plans', {
|
|
params: { query: { weekStart } }
|
|
});
|
|
|
|
if (error || !weekPlan?.id) {
|
|
return { weekPlan: null, varietyScore: null, weekStart };
|
|
}
|
|
|
|
const { data: varietyScore } = await api.GET('/v1/week-plans/{id}/variety-score', {
|
|
params: { path: { id: weekPlan.id } }
|
|
});
|
|
|
|
return {
|
|
weekPlan,
|
|
varietyScore: varietyScore ?? null,
|
|
weekStart
|
|
};
|
|
};
|
|
|
|
export const actions: Actions = {
|
|
createPlan: async ({ fetch, request, locals }) => {
|
|
// Role guard: only planners may create week plans
|
|
if (locals.benutzer?.rolle !== 'planer') {
|
|
return { success: false, error: 'Keine Berechtigung.' };
|
|
}
|
|
|
|
const formData = await request.formData();
|
|
const weekStart = formData.get('weekStart') as string;
|
|
|
|
// Validate weekStart format: must be YYYY-MM-DD
|
|
if (!weekStart || !/^\d{4}-\d{2}-\d{2}$/.test(weekStart)) {
|
|
return { success: false, error: 'Ungültiges Datum.' };
|
|
}
|
|
|
|
const api = apiClient(fetch);
|
|
const { data, error } = await api.POST('/v1/week-plans', {
|
|
body: { weekStart }
|
|
});
|
|
|
|
if (error || !data) {
|
|
return { success: false, error: 'Plan konnte nicht erstellt werden.' };
|
|
}
|
|
|
|
return { success: true };
|
|
}
|
|
};
|