feat(planner): implement C1 weekly planner home screen (#26)

Three-breakpoint layout (mobile/tablet/desktop) with VarietyScoreCard,
WeekStrip, DayMealCard components. Server loads week plan and variety
score via API; read-only role behavior derived from benutzer.rolle.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 11:01:17 +02:00
parent 0511a735a5
commit e3f8d8ad73
10 changed files with 976 additions and 1 deletions

View File

@@ -0,0 +1,45 @@
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 }) => {
const formData = await request.formData();
const weekStart = formData.get('weekStart') as string;
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 };
}
};