From 7084f703dcf7a05cf6c140a1f0f8f72d461f422f Mon Sep 17 00:00:00 2001 From: Rasmus Q Date: Mon, 16 Mar 2026 13:40:48 +0000 Subject: [PATCH] feat: auto-load images when user stops typing link (500ms debounce) --- src/lib/components/wishlist/ItemForm.svelte | 59 +++++++++++++-------- 1 file changed, 36 insertions(+), 23 deletions(-) diff --git a/src/lib/components/wishlist/ItemForm.svelte b/src/lib/components/wishlist/ItemForm.svelte index d57e47c..8057db0 100644 --- a/src/lib/components/wishlist/ItemForm.svelte +++ b/src/lib/components/wishlist/ItemForm.svelte @@ -49,37 +49,50 @@ let color = $state(item?.color || null); let scrapedImages = $state([]); let isLoadingImages = $state(false); + let debounceTimer: ReturnType | null = null; // Form action based on mode const formAction = isEdit ? '?/updateItem' : '?/addItem'; const submitLabel = isEdit ? t.form.saveChanges : t.wishlist.addWish; const titleLabel = isEdit ? t.wishlist.editWish : t.form.addNewWish; - async function handleLinkChange(event: Event) { + async function scrapeImages(url: string) { + if (!url || !url.startsWith('http')) return; + + isLoadingImages = true; + scrapedImages = []; + + try { + const response = await fetch('/api/scrape-images', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ url }) + }); + + if (response.ok) { + const data = await response.json(); + scrapedImages = data.images || []; + } + } catch (error) { + console.error('Failed to scrape images:', error); + } finally { + isLoadingImages = false; + } + } + + function handleLinkInput(event: Event) { const input = event.target as HTMLInputElement; linkUrl = input.value; - - if (linkUrl && linkUrl.startsWith('http')) { - isLoadingImages = true; - scrapedImages = []; - - try { - const response = await fetch('/api/scrape-images', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ url: linkUrl }) - }); - - if (response.ok) { - const data = await response.json(); - scrapedImages = data.images || []; - } - } catch (error) { - console.error('Failed to scrape images:', error); - } finally { - isLoadingImages = false; - } + + // Clear existing timer + if (debounceTimer) { + clearTimeout(debounceTimer); } + + // Set new timer to scrape after user stops typing for 500ms + debounceTimer = setTimeout(() => { + scrapeImages(linkUrl); + }, 500); } function handleColorChange() { @@ -141,7 +154,7 @@ type="url" placeholder="https://..." bind:value={linkUrl} - oninput={handleLinkChange} + oninput={handleLinkInput} />