From 7e5535f9834fca2594c5bade425ecee00c32bdb8 Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Tue, 28 Jul 2026 22:22:12 +0200 Subject: feat: autocomplete search with datalist to prevent duplicate items --- src/routes/+page.server.ts | 10 +++++++++- src/routes/+page.svelte | 28 ++++++++++++++++++++++------ src/routes/catalog/+page.svelte | 3 ++- 3 files changed, 33 insertions(+), 8 deletions(-) (limited to 'src/routes') diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index b0ddff0..1e6f60b 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -1,6 +1,7 @@ import { fail, redirect, error } from '@sveltejs/kit'; import { loadUnchecked, + loadAll, toggle, addOrUncheck, } from '$lib/server/services/groceries'; @@ -16,10 +17,17 @@ import type { Actions, PageServerLoad } from './$types'; export interface HomeOutput { items: EnrichedGrocery[]; categories: Category[]; + catalog: EnrichedGrocery[]; } export const load: PageServerLoad = async () => { - return loadUnchecked(); + const unchecked = await loadUnchecked(); + const all = await loadAll(); + return { + items: unchecked.items, + categories: unchecked.categories, + catalog: all.items, + }; }; export const actions: Actions = { diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index e4f78c5..a151a9b 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -9,7 +9,6 @@ // eslint-disable-next-line svelte/prefer-writable-derived let localItems = $state(data?.items ?? []); let addError = $state(''); - // Sync local list with server data when it changes externally (toggle, navigation) $effect(() => { localItems = data?.items ?? []; @@ -81,13 +80,29 @@ bind:value={name} placeholder="Ajouter un article..." autocomplete="off" + list="item-suggestions" onkeydown={(e) => { if (e.key === 'Enter') { e.preventDefault(); handleAdd(false); } }} + oninput={(e) => { + const val = e.currentTarget.value.trim().toLowerCase(); + const match = data.catalog.find( + (item) => item.name.toLowerCase() === val, + ); + if (match) { + name = match.name; + handleAdd(false); + } + }} /> + + {#each data.catalog as item (item.id)} + + {/each} + @@ -123,7 +138,8 @@ {item.bestRef.reference} {#if item.bestRef.price && item.bestRef.unit} -  {item.bestRef.price.toFixed(2)} {item.bestRef.unit} +  {item.bestRef.price.toFixed(2)} + {item.bestRef.unit} {/if} {#if item.bestRef.qualityScore != null}  ({item.bestRef.qualityScore}/100) @@ -175,25 +191,25 @@ transition: all 0.2s ease; } - .add-bar button:nth-child(2) { + .add-bar > button:nth-of-type(1) { background: var(--accent); color: var(--white); box-shadow: 0 1px 2px var(--shadow); } - .add-bar button:nth-child(2):hover { + .add-bar > button:nth-of-type(1):hover { background: var(--accent-hover); transform: translateY(-1px); box-shadow: 0 4px 8px var(--shadow-accent-lg); } - .add-bar button:nth-child(3) { + .add-bar > button:nth-of-type(2) { background: var(--surface); color: var(--text-secondary); border: 1.5px solid var(--border); } - .add-bar button:nth-child(3):hover { + .add-bar > button:nth-of-type(2):hover { border-color: var(--accent); color: var(--text); } diff --git a/src/routes/catalog/+page.svelte b/src/routes/catalog/+page.svelte index 525c2ed..7d3ebbe 100644 --- a/src/routes/catalog/+page.svelte +++ b/src/routes/catalog/+page.svelte @@ -38,7 +38,8 @@ {item.bestRef.reference} {#if item.bestRef.price && item.bestRef.unit} -  {item.bestRef.price.toFixed(2)} {item.bestRef.unit} +  {item.bestRef.price.toFixed(2)} + {item.bestRef.unit} {/if} {#if item.bestRef.qualityScore != null}  ({item.bestRef.qualityScore}/100) -- cgit v1.3