From 113415ce357a9cea1759d0452ebae6352f8fe36b Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Mon, 7 Sep 2026 10:55:06 +0200 Subject: Split groceries domain out of the app root Move the grocery list, catalog, and categories routes under /groceries/ so the app home can host the projects/routines overview next. Update nav to exact-path matching, login redirect default, and layout title. --- src/routes/groceries/catalog/+page.server.ts | 49 +++++++ src/routes/groceries/catalog/+page.svelte | 211 +++++++++++++++++++++++++++ 2 files changed, 260 insertions(+) create mode 100644 src/routes/groceries/catalog/+page.server.ts create mode 100644 src/routes/groceries/catalog/+page.svelte (limited to 'src/routes/groceries/catalog') diff --git a/src/routes/groceries/catalog/+page.server.ts b/src/routes/groceries/catalog/+page.server.ts new file mode 100644 index 0000000..22464dc --- /dev/null +++ b/src/routes/groceries/catalog/+page.server.ts @@ -0,0 +1,49 @@ +import { fail } from '@sveltejs/kit'; +import { + loadAll, + toggle, + bulkUpdateGroceryCategory, +} from '$lib/server/services/groceries'; +import { + numericId, + parseOptionalNumber, +} from '$lib/server/services/validation'; +import type { EnrichedGrocery } from '$lib/server/services/groceries'; +import type { Category } from '$lib/server/services/types'; +import type { Actions, PageServerLoad } from './$types'; + +export interface CatalogOutput { + items: EnrichedGrocery[]; + categories: Category[]; +} + +export const load: PageServerLoad = async () => { + return loadAll(); +}; + +export const actions: Actions = { + toggle: async ({ request }) => { + const data = await request.formData(); + try { + const id = numericId(data.get('id')); + await toggle(id); + } catch { + return fail(400, { error: 'ID invalide' }); + } + return { success: true }; + }, + + bulkUpdateCategory: async ({ request }) => { + const data = await request.formData(); + const ids = data.getAll('ids').map(numericId); + const rawCategoryId = parseOptionalNumber(data.get('category_id')); + const categoryId = rawCategoryId === -1 ? null : rawCategoryId; + + if (ids.length === 0) { + return fail(400, { error: 'Aucun article sélectionné' }); + } + + await bulkUpdateGroceryCategory(ids, categoryId); + return { success: true, type: 'bulkUpdate' as const }; + }, +}; diff --git a/src/routes/groceries/catalog/+page.svelte b/src/routes/groceries/catalog/+page.svelte new file mode 100644 index 0000000..4cbcc27 --- /dev/null +++ b/src/routes/groceries/catalog/+page.svelte @@ -0,0 +1,211 @@ + + +{#if catalogItems.length > 0} +
+
{ + return async ({ update }) => { + await update({ reset: false }); + selectedIds.clear(); + }; + }} + > + {#each Array.from(selectedIds) as id (id)} + + {/each} + + +
+
+{/if} + +
+ {#if form?.error} +

{form.error}

+ {/if} + + {#if catalogItems.length === 0} +

Aucun article

+ {:else} + + + {#if filteredItems.length === 0} +

Aucun résultat

+ {:else} +
+ {#each groupByCategory(filteredItems) as [cat, items] (cat)} +

{cat}

+
    + {#each items as item (item.id)} +
  • + toggleId(item.id)} + /> + + → +
  • + {/each} +
+ {/each} +
+ {/if} + {/if} +
+ + -- cgit v1.3