feat(recipe): Edit-Modus für Zutaten, Schritte und Meta
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 1m18s
All checks were successful
Build & Publish Docker Image / build-and-push (push) Successful in 1m18s
Auf der Rezept-Detail-Seite ein neuer „Bearbeiten"-Button (Pencil-Icon) in der Action-Bar. Klick schaltet RecipeView auf RecipeEditor um. Im Editor: - Titel, Beschreibung, Portionen, Vorbereitungs-/Koch-/Gesamtzeit als inline-Inputs. - Zutaten: pro Zeile Menge, Einheit, Name, Notiz + Trash-Icon zum Entfernen. „+ Zutat hinzufügen"-Dashed-Button am Listenende. - Schritte: nummerierte Textareas, Trash-Icon, „+ Schritt hinzufügen". - Mengen akzeptieren Komma- oder Punkt-Dezimalen. - Empty-Items werden beim Speichern automatisch aussortiert. Backend: - Neue Repo-Funktionen updateRecipeMeta(id, patch), replaceIngredients, replaceSteps — letztere in einer Transaction mit delete+insert und FTS-Refresh. - PATCH /api/recipes/[id] akzeptiert jetzt zusätzlich description, servings_default, servings_unit, prep_time_min, cook_time_min, total_time_min, cuisine, category, ingredients[], steps[]. Vorher nur title/hidden_from_recent; diese beiden bleiben als Kurz-Fall erhalten, damit bestehende Aufrufer unverändert laufen. - Zod-Schema mit expliziten Grenzen (max-Länge, positive Mengen). Tests: 3 neue Cases für updateRecipeMeta, replaceIngredients (inkl. FTS-Update), replaceSteps. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -155,3 +155,79 @@ export function getRecipeIdBySourceUrl(
|
||||
export function deleteRecipe(db: Database.Database, id: number): void {
|
||||
db.prepare('DELETE FROM recipe WHERE id = ?').run(id);
|
||||
}
|
||||
|
||||
export type RecipeMetaPatch = {
|
||||
title?: string;
|
||||
description?: string | null;
|
||||
servings_default?: number | null;
|
||||
servings_unit?: string | null;
|
||||
prep_time_min?: number | null;
|
||||
cook_time_min?: number | null;
|
||||
total_time_min?: number | null;
|
||||
cuisine?: string | null;
|
||||
category?: string | null;
|
||||
};
|
||||
|
||||
export function updateRecipeMeta(
|
||||
db: Database.Database,
|
||||
id: number,
|
||||
patch: RecipeMetaPatch
|
||||
): void {
|
||||
const fields: string[] = [];
|
||||
const values: unknown[] = [];
|
||||
for (const key of [
|
||||
'title',
|
||||
'description',
|
||||
'servings_default',
|
||||
'servings_unit',
|
||||
'prep_time_min',
|
||||
'cook_time_min',
|
||||
'total_time_min',
|
||||
'cuisine',
|
||||
'category'
|
||||
] as const) {
|
||||
if (patch[key] !== undefined) {
|
||||
fields.push(`${key} = ?`);
|
||||
values.push(patch[key]);
|
||||
}
|
||||
}
|
||||
if (fields.length === 0) return;
|
||||
fields.push('updated_at = CURRENT_TIMESTAMP');
|
||||
db.prepare(`UPDATE recipe SET ${fields.join(', ')} WHERE id = ?`).run(...values, id);
|
||||
}
|
||||
|
||||
export function replaceIngredients(
|
||||
db: Database.Database,
|
||||
recipeId: number,
|
||||
ingredients: Ingredient[]
|
||||
): void {
|
||||
const tx = db.transaction(() => {
|
||||
db.prepare('DELETE FROM ingredient WHERE recipe_id = ?').run(recipeId);
|
||||
const ins = db.prepare(
|
||||
`INSERT INTO ingredient(recipe_id, position, quantity, unit, name, note, raw_text)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)`
|
||||
);
|
||||
for (const ing of ingredients) {
|
||||
ins.run(recipeId, ing.position, ing.quantity, ing.unit, ing.name, ing.note, ing.raw_text);
|
||||
}
|
||||
refreshFts(db, recipeId);
|
||||
});
|
||||
tx();
|
||||
}
|
||||
|
||||
export function replaceSteps(
|
||||
db: Database.Database,
|
||||
recipeId: number,
|
||||
steps: Step[]
|
||||
): void {
|
||||
const tx = db.transaction(() => {
|
||||
db.prepare('DELETE FROM step WHERE recipe_id = ?').run(recipeId);
|
||||
const ins = db.prepare(
|
||||
'INSERT INTO step(recipe_id, position, text) VALUES (?, ?, ?)'
|
||||
);
|
||||
for (const step of steps) {
|
||||
ins.run(recipeId, step.position, step.text);
|
||||
}
|
||||
});
|
||||
tx();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user