diff --git a/src/client/src/routes/results/+page.svelte b/src/client/src/routes/results/+page.svelte index 2c7f7c3..b281081 100644 --- a/src/client/src/routes/results/+page.svelte +++ b/src/client/src/routes/results/+page.svelte @@ -9,6 +9,9 @@ let meta = $state(null); let loading = $state(true); let sortBy = $state('price'); + let sortAsc = $state(true); + let filterText = $state(''); + let filterStore = $state(''); onMount(async () => { const params = $page.url.searchParams; @@ -44,15 +47,53 @@ doSearch(); } - let sortedResults = $derived(() => { - const sorted = [...results]; - switch (sortBy) { - case 'price': sorted.sort((a, b) => (a.price ?? Infinity) - (b.price ?? Infinity)); break; - case 'price-desc': sorted.sort((a, b) => (b.price ?? -Infinity) - (a.price ?? -Infinity)); break; - case 'name': sorted.sort((a, b) => a.name.localeCompare(b.name)); break; - case 'store': sorted.sort((a, b) => a.storeName.localeCompare(b.storeName)); break; + function handleSort(column) { + if (sortBy === column) { + sortAsc = !sortAsc; + } else { + sortBy = column; + sortAsc = column === 'name' || column === 'store'; } - return sorted; + } + + // Unique store names for the filter dropdown + let storeNames = $derived(() => { + const names = [...new Set(results.map(r => r.storeName))]; + return names.sort(); + }); + + let filteredAndSorted = $derived(() => { + let items = [...results]; + + // Text filter + if (filterText) { + const lower = filterText.toLowerCase(); + items = items.filter(r => r.name.toLowerCase().includes(lower)); + } + + // Store filter + if (filterStore) { + items = items.filter(r => r.storeName === filterStore); + } + + // Sort + items.sort((a, b) => { + let cmp = 0; + switch (sortBy) { + case 'price': + cmp = (a.price ?? Infinity) - (b.price ?? Infinity); + break; + case 'name': + cmp = a.name.localeCompare(b.name); + break; + case 'store': + cmp = a.storeName.localeCompare(b.storeName); + break; + } + return sortAsc ? cmp : -cmp; + }); + + return items; }); function formatPrice(price, currency) { @@ -60,6 +101,11 @@ try { return new Intl.NumberFormat('en-US', { style: 'currency', currency }).format(price); } catch { return `${currency} ${price.toFixed(2)}`; } } + + function sortIcon(column) { + if (sortBy !== column) return ''; + return sortAsc ? '\u2191' : '\u2193'; + }
| + | + + | ++ + | ++ + | ++ Link + | +
|---|---|---|---|---|
|
+ {#if product.image}
+
+
+ {:else}
+
+
+
+ {/if}
+ |
- + + {product.name} + + | + + ++ + {formatPrice(product.price, product.currency)} + + | + + ++ + {product.storeName} + + | + + ++ + Open → + + | +