feat(recipes): add /recipes/new route with create action

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-03 10:19:27 +02:00
parent 2cef8a1169
commit 4e2b0b5727
3 changed files with 131 additions and 0 deletions

View File

@@ -0,0 +1,61 @@
import { redirect, fail } from '@sveltejs/kit';
import type { PageServerLoad, Actions } from './$types';
import { apiClient } from '$lib/server/api';
export const load: PageServerLoad = async ({ fetch }) => {
const api = apiClient(fetch);
const { data, error } = await api.GET('/v1/tags', {});
const allTags = error || !data ? [] : data;
const categories = allTags
.filter((t) => t.tagType === 'category')
.map((t) => ({ id: t.id!, name: t.name!, tagType: t.tagType }));
return { recipe: null, categories };
};
export const actions: Actions = {
create: async ({ request, fetch }) => {
const formData = await request.formData();
const name = formData.get('name') as string;
const serves = formData.get('serves');
const cookTimeMin = formData.get('cookTimeMin');
const effort = formData.get('effort') as string;
const ingredientsJson = formData.get('ingredientsJson') as string;
const stepsJson = formData.get('stepsJson') as string;
const tagIds = formData.getAll('tagIds') as string[];
if (!name?.trim()) return fail(422, { error: 'Name ist erforderlich' });
if (!effort) return fail(422, { error: 'Schwierigkeitsgrad ist erforderlich' });
if (!tagIds.length) return fail(422, { error: 'Mindestens eine Kategorie ist erforderlich' });
const parsedIngredients = JSON.parse(ingredientsJson || '[]');
const parsedSteps = JSON.parse(stepsJson || '[]');
const api = apiClient(fetch);
const { error: apiError } = await api.POST('/v1/recipes', {
body: {
name: name.trim(),
serves: serves ? Number(serves) : undefined,
cookTimeMin: cookTimeMin ? Number(cookTimeMin) : undefined,
effort,
ingredients: parsedIngredients
.filter((ing: { name: string }) => ing.name?.trim())
.map((ing: { name: string; quantity: string; unit: string }, i: number) => ({
newIngredientName: ing.name.trim(),
quantity: Number(ing.quantity) || 0,
unit: ing.unit || '',
sortOrder: i
})),
steps: parsedSteps
.filter((s: string) => s?.trim())
.map((s: string, i: number) => ({ stepNumber: i + 1, instruction: s.trim() })),
tagIds
}
});
if (apiError) return fail(500, { error: 'Fehler beim Speichern' });
redirect(303, '/recipes');
}
};