diff options
Diffstat (limited to 'src/routes/+page.svelte')
| -rw-r--r-- | src/routes/+page.svelte | 99 |
1 files changed, 82 insertions, 17 deletions
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 7a367c1..6d9d85f 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -1,45 +1,110 @@ <script lang="ts"> + import { deserialize } from '$app/forms'; + import { goto } from '$app/navigation'; import { enhance } from '$app/forms'; let { data, form } = $props(); let name = $state(''); + let inputRef: HTMLInputElement; + // eslint-disable-next-line svelte/prefer-writable-derived + let localItems = $state(data?.items ?? []); + let addError = $state(''); - let listItems = $derived(data?.items ?? []); + // Sync local list with server data when it changes externally (toggle, navigation) + $effect(() => { + localItems = data?.items ?? []; + }); - function groupByCategory(items: typeof listItems) { - const groups: Record<string, typeof listItems> = {}; + function groupByCategory(items: typeof localItems) { + const groups: Record<string, typeof localItems> = {}; for (const item of items) { const key = item.categoryName ?? 'Non catégorisé'; (groups[key] ??= []).push(item); } return Object.entries(groups); } + + async function handleAdd(redirectToEdit: boolean) { + if (!name.trim()) { + addError = 'Le nom est requis'; + return; + } + addError = ''; + + const formData = new FormData(); + formData.append('name', name); + + const action = redirectToEdit ? '?/addAndEdit' : '?/add'; + name = ''; + inputRef.focus(); + + try { + const response = await fetch(action, { + method: 'POST', + headers: { + accept: 'application/json', + 'x-sveltekit-action': 'true', + }, + body: formData, + }); + + const result = deserialize(await response.text()); + + if (result.type === 'error') { + addError = + typeof result.error === 'string' + ? result.error + : result.error?.message || 'Erreur'; + return; + } + + if (result.type === 'redirect') { + goto(result.location); + return; + } + + if (result.type === 'success' && result.data?.items) { + localItems = result.data.items; + } + } catch (err) { + addError = 'Erreur réseau'; + console.error(err); + } + } </script> -<form class="add-bar" method="POST" action="?/add" use:enhance> +<div class="add-bar"> <input + bind:this={inputRef} class="form-input" type="text" - name="name" bind:value={name} placeholder="Ajouter un article..." autocomplete="off" + onkeydown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); + handleAdd(false); + } + }} /> - <button type="submit" aria-label="Ajouter">+</button> - <button type="submit" formaction="?/addAndEdit" aria-label="Modifier" - >→</button + <button type="button" aria-label="Ajouter" onclick={() => handleAdd(false)} + >+</button + > + <button type="button" aria-label="Modifier" onclick={() => handleAdd(true)} + >→</button > -</form> +</div> -{#if form?.error} - <p class="error">{form.error}</p> +{#if addError || form?.error} + <p class="error">{addError || form?.error}</p> {/if} -{#if listItems.length === 0} +{#if localItems.length === 0} <p class="empty">Rien à acheter</p> {:else} <form method="POST" action="?/toggle" use:enhance> - {#each groupByCategory(listItems) as [cat, items] (cat)} + {#each groupByCategory(localItems) as [cat, items] (cat)} <h3 class="category-name">{cat}</h3> <ul class="item-list"> {#each items as item (item.id)} @@ -107,25 +172,25 @@ transition: all 0.2s ease; } - .add-bar button[type='submit']:not([formaction]) { + .add-bar button:nth-child(2) { background: var(--accent); color: var(--white); box-shadow: 0 1px 2px var(--shadow); } - .add-bar button[type='submit']:not([formaction]):hover { + .add-bar button:nth-child(2):hover { background: var(--accent-hover); transform: translateY(-1px); box-shadow: 0 4px 8px var(--shadow-accent-lg); } - .add-bar button[formaction] { + .add-bar button:nth-child(3) { background: var(--surface); color: var(--text-secondary); border: 1.5px solid var(--border); } - .add-bar button[formaction]:hover { + .add-bar button:nth-child(3):hover { border-color: var(--accent); color: var(--text); } |
