From db2f142aaf98ba36d1e9b17ce8a4299268d1b69b Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Tue, 28 Jul 2026 15:29:32 +0200 Subject: feat: editable name and category in grocery detail page --- README.md | 4 +--- src/lib/server/services/groceries.ts | 12 ++++++++++++ src/routes/grocery/[id]/+page.server.ts | 23 +++++++++++++++++++++-- src/routes/grocery/[id]/+page.svelte | 30 ++++++++++++++++++------------ 4 files changed, 52 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 5046e06..7101a5b 100644 --- a/README.md +++ b/README.md @@ -55,12 +55,10 @@ efficient shopping walk. ## TODO +- [ ] Weird form stickyness that collapse the gap with the navbar - [ ] Edit grocery category -- [x] Global code review (services, validation, tests, aria) - [ ] Keyboard focus -- [ ] Bug: list and catalog show the same items - [ ] PWA -- [ ] Weird form stickyness that collapse the gap with the navbar - [ ] Live updates from server - [ ] Extract color palette diff --git a/src/lib/server/services/groceries.ts b/src/lib/server/services/groceries.ts index fb42224..db9e736 100644 --- a/src/lib/server/services/groceries.ts +++ b/src/lib/server/services/groceries.ts @@ -97,6 +97,18 @@ export async function addOrUncheck( return { item: inserted, created: true }; } +export async function updateGrocery( + id: number, + name: string, + categoryId: number | null, + db = defaultDb, +): Promise { + await db + .update(groceries) + .set({ name, categoryId }) + .where(eq(groceries.id, id)); +} + export async function deleteGrocery(id: number, db = defaultDb): Promise { await db.delete(groceries).where(eq(groceries.id, id)); } diff --git a/src/routes/grocery/[id]/+page.server.ts b/src/routes/grocery/[id]/+page.server.ts index 3c3967a..cf8a949 100644 --- a/src/routes/grocery/[id]/+page.server.ts +++ b/src/routes/grocery/[id]/+page.server.ts @@ -2,23 +2,25 @@ import { error, fail, redirect } from '@sveltejs/kit'; import { db } from '$lib/server/db'; import { groceries, categories } from '$lib/server/db/schema'; import { eq } from 'drizzle-orm'; +import { loadAll as loadCategories } from '$lib/server/services/categories'; import { loadForGrocery, add as addRef, deleteReference, } from '$lib/server/services/references'; -import { deleteGrocery } from '$lib/server/services/groceries'; +import { updateGrocery, deleteGrocery } from '$lib/server/services/groceries'; import { numericId, parseFormString, parseOptionalNumber, } from '$lib/server/services/validation'; -import type { Grocery, Reference } from '$lib/server/services/types'; +import type { Category, Grocery, Reference } from '$lib/server/services/types'; import type { Actions, PageServerLoad } from './$types'; export interface GroceryDetailOutput { item: Grocery & { categoryName: string | null }; references: Reference[]; + categories: Category[]; } export const load: PageServerLoad = async ({ params }) => { @@ -35,6 +37,7 @@ export const load: PageServerLoad = async ({ params }) => { : [null]; const refs = await loadForGrocery(id); + const cats = await loadCategories(); return { item: { @@ -42,6 +45,7 @@ export const load: PageServerLoad = async ({ params }) => { categoryName: cat?.name ?? null, }, references: refs, + categories: cats, }; }; @@ -73,6 +77,21 @@ export const actions: Actions = { return { success: true }; }, + update: async ({ request, params }) => { + const data = await request.formData(); + const groceryId = numericId(params.id); + const name = parseFormString(data.get('name')); + const rawCategoryId = parseOptionalNumber(data.get('category_id')); + const categoryId = rawCategoryId === -1 ? null : rawCategoryId; + + if (!name) { + return fail(400, { error: 'Le nom est requis' }); + } + + await updateGrocery(groceryId, name, categoryId); + return { success: true }; + }, + deleteItem: async ({ params }) => { const groceryId = numericId(params.id); await deleteGrocery(groceryId); diff --git a/src/routes/grocery/[id]/+page.svelte b/src/routes/grocery/[id]/+page.svelte index a49d037..a7e0bc9 100644 --- a/src/routes/grocery/[id]/+page.svelte +++ b/src/routes/grocery/[id]/+page.svelte @@ -2,17 +2,30 @@ import { enhance } from '$app/forms'; let { data, form } = $props(); + let name = $state(data.item.name); + let categoryId = $state(data.item.categoryId ?? -1); let reference = $state(''); let price = $state(''); let unit = $state('€/kg'); let qualityScore = $state(''); -

{data.item.name}

- -{#if data.item.categoryName} -

{data.item.categoryName}

-{/if} +
+ + + +

@@ -110,13 +123,6 @@ ← Retour à la liste