From 71ca66bcba70f7a463df6ee9bdcb0e14b8e60595 Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Mon, 27 Jul 2026 16:54:28 +0200 Subject: feat: minimal grocery list — add items, check them off MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Groceries DB schema (id, name, checked, created_at) with Drizzle + libsql - /+page.server.ts: load (unchecked items, newest first), add & toggle actions - /+page.svelte: text input + Add button, item list with toggle buttons - Mobile-first styling with scoped CSS classes - AGENTS.md: project-specific rules including UI validation --- src/routes/+page.server.ts | 53 ++++++++++++++++++++++++++ src/routes/+page.svelte | 95 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 src/routes/+page.server.ts (limited to 'src/routes') diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts new file mode 100644 index 0000000..e6f3b0f --- /dev/null +++ b/src/routes/+page.server.ts @@ -0,0 +1,53 @@ +import { fail } from '@sveltejs/kit'; +import { db } from '$lib/server/db'; +import { groceries } from '$lib/server/db/schema'; +import { eq, desc } from 'drizzle-orm'; +import type { Actions, PageServerLoad } from './$types'; + +export const load: PageServerLoad = async () => { + const items = await db + .select() + .from(groceries) + .where(eq(groceries.checked, false)) + .orderBy(desc(groceries.createdAt)); + + return { items }; +}; + +export const actions: Actions = { + add: async ({ request }) => { + const data = await request.formData(); + const name = data.get('name')?.toString().trim(); + + if (!name) { + return fail(400, { error: 'Name is required' }); + } + + await db.insert(groceries).values({ + name, + createdAt: new Date().toISOString(), + }); + + return { success: true }; + }, + + toggle: async ({ request }) => { + const data = await request.formData(); + const id = Number(data.get('id')); + + const [item] = await db + .select() + .from(groceries) + .where(eq(groceries.id, id)); + if (!item) { + return fail(404, { error: 'Item not found' }); + } + + await db + .update(groceries) + .set({ checked: !item.checked }) + .where(eq(groceries.id, id)); + + return { success: true }; + }, +}; diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 1b6e963..fc56140 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,6 +1,97 @@ -

Home

-

Welcome! Groceries and chores coming soon.

+

Groceries

+ +
+ + +
+ +{#if form?.error} +

{form.error}

+{/if} + +
+ +
+ +
+ + -- cgit v1.3