diff options
Diffstat (limited to 'src/routes/categories')
| -rw-r--r-- | src/routes/categories/+page.server.ts | 32 | ||||
| -rw-r--r-- | src/routes/categories/+page.svelte | 146 |
2 files changed, 36 insertions, 142 deletions
diff --git a/src/routes/categories/+page.server.ts b/src/routes/categories/+page.server.ts index 7cedd98..ac53ca8 100644 --- a/src/routes/categories/+page.server.ts +++ b/src/routes/categories/+page.server.ts @@ -1,38 +1,38 @@ import { fail } from '@sveltejs/kit'; -import { db } from '$lib/server/db'; -import { categories } from '$lib/server/db/schema'; -import { eq, asc } from 'drizzle-orm'; +import { loadAll, add, deleteCategory } from '$lib/server/services/categories'; +import { numericId, parseFormString } from '$lib/server/services/validation'; +import type { Category } from '$lib/server/services/types'; import type { Actions, PageServerLoad } from './$types'; -export const load: PageServerLoad = async () => { - const items = await db - .select() - .from(categories) - .orderBy(asc(categories.name)); +export interface CategoriesOutput { + categories: Category[]; +} - return { categories: items }; +export const load: PageServerLoad = async () => { + return { categories: await loadAll() }; }; export const actions: Actions = { add: async ({ request }) => { const data = await request.formData(); - const name = data.get('name')?.toString().trim(); + const name = parseFormString(data.get('name')); if (!name) { return fail(400, { error: 'Le nom est requis' }); } - await db.insert(categories).values({ name }); - + await add(name); return { success: true }; }, delete: async ({ request }) => { const data = await request.formData(); - const id = Number(data.get('id')); - - await db.delete(categories).where(eq(categories.id, id)); - + try { + const id = numericId(data.get('id')); + await deleteCategory(id); + } catch { + return fail(400, { error: 'ID invalide' }); + } return { success: true }; }, }; diff --git a/src/routes/categories/+page.svelte b/src/routes/categories/+page.svelte index eab0219..41b40c5 100644 --- a/src/routes/categories/+page.svelte +++ b/src/routes/categories/+page.svelte @@ -1,15 +1,20 @@ <script lang="ts"> - import '../../app.css'; import { enhance } from '$app/forms'; let { data, form } = $props(); let name = $state(''); </script> -<form class="add-form" method="POST" action="?/add" use:enhance> +<form + class="form-card form-card--compact" + method="POST" + action="?/add" + use:enhance +> <label> - <span class="label">Nouvelle catégorie</span> + <span class="form-label">Nouvelle catégorie</span> <input + class="form-input" type="text" name="name" bind:value={name} @@ -17,7 +22,7 @@ autocomplete="off" /> </label> - <button type="submit">Ajouter</button> + <button class="btn-primary" type="submit">Ajouter</button> </form> {#if form?.error} @@ -27,9 +32,15 @@ <form method="POST" action="?/delete" use:enhance> <ul class="item-list"> {#each data?.categories ?? [] as cat (cat.id)} - <li class="catalog-item"> + <li class="item-row item-row--card"> <span class="cat-name">{cat.name}</span> - <button class="delete-btn" name="id" value={cat.id} type="submit"> + <button + class="btn-ghost" + name="id" + value={cat.id} + type="submit" + aria-label="Supprimer" + > × </button> </li> @@ -42,136 +53,19 @@ {/if} <style> - .add-form { - display: flex; - flex-direction: column; - gap: 0.5rem; - margin-bottom: 1.5rem; - padding: 1rem; - background: var(--surface); - border-radius: 0.75rem; - box-shadow: 0 1px 2px var(--shadow); - } - - .add-form label { - display: flex; - flex-direction: column; - gap: 0.375rem; - } - - .label { - font-size: 0.75rem; - font-weight: 700; - text-transform: uppercase; - letter-spacing: 0.06em; - color: var(--text-secondary); - } - - input { - padding: 0.75rem 1rem; - border: 1.5px solid var(--border); - border-radius: 0.75rem; - font-size: 1rem; - font-family: inherit; - background: var(--bg); - transition: border-color 0.2s, box-shadow 0.2s; - } - - input:focus { - outline: none; - border-color: var(--accent); - box-shadow: 0 0 0 3px rgba(217, 119, 87, 0.15); - } - - .add-form button[type='submit'] { - padding: 0.75rem 1.5rem; - border: none; - border-radius: 0.75rem; - background: var(--accent); - color: #fff; - font-size: 0.9375rem; - font-weight: 500; - align-self: flex-start; - cursor: pointer; - transition: all 0.2s ease; - box-shadow: 0 1px 2px var(--shadow); - } - - .add-form button[type='submit']:hover { - background: var(--accent-hover); - transform: translateY(-1px); - box-shadow: 0 4px 8px rgba(217, 119, 87, 0.2); - } - - .error { - color: var(--danger); - font-size: 0.875rem; - margin-top: -0.25rem; - margin-bottom: 0.5rem; - padding: 0.5rem 0.75rem; - background: rgba(217, 83, 79, 0.08); - border-radius: 0.5rem; - } - - .item-list { - list-style: none; - display: flex; - flex-direction: column; - gap: 0.375rem; - } - - .catalog-item { - display: flex; - gap: 0.5rem; - align-items: center; - padding: 0.5rem 0.75rem; - background: var(--surface); - border-radius: 0.75rem; - box-shadow: 0 1px 2px var(--shadow); - transition: all 0.2s ease; - } - - .catalog-item:hover { - box-shadow: 0 2px 6px var(--shadow); - transform: translateY(-1px); - } - .cat-name { flex-grow: 1; font-weight: 500; color: var(--text); } - .delete-btn { - border: none; - border-radius: 0.625rem; - background: transparent; - color: var(--text-secondary); - transition: all 0.2s ease; - width: 2rem; - aspect-ratio: 1; - padding: 0; - display: flex; - align-items: center; - justify-content: center; - font-size: 1.25rem; - cursor: pointer; - flex-shrink: 0; - } - - .delete-btn:hover { - background: rgba(217, 83, 79, 0.1); - color: var(--danger); + .error { + margin-top: -0.25rem; + margin-bottom: 0.5rem; } .empty { - color: var(--text-secondary); - font-size: 0.9375rem; margin-top: 1rem; - text-align: center; padding: 2rem; - background: var(--surface); - border-radius: 0.75rem; - box-shadow: 0 1px 2px var(--shadow); } </style> |
