Replace store dropdown with checkbox toggle chips
Each store appears as a clickable chip with a checkmark. Click to exclude a store from results (greys out with strikethrough). Click again to re-include. Multiple stores can be toggled independently. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@
|
|||||||
let sortBy = $state('price');
|
let sortBy = $state('price');
|
||||||
let sortAsc = $state(true);
|
let sortAsc = $state(true);
|
||||||
let filterText = $state('');
|
let filterText = $state('');
|
||||||
let filterStore = $state('');
|
let excludedStores = $state(new Set());
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const params = $page.url.searchParams;
|
const params = $page.url.searchParams;
|
||||||
@@ -72,8 +72,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store filter
|
// Store filter
|
||||||
if (filterStore) {
|
if (excludedStores.size > 0) {
|
||||||
items = items.filter(r => r.storeName === filterStore);
|
items = items.filter(r => !excludedStores.has(r.storeName));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort
|
// Sort
|
||||||
@@ -102,6 +102,13 @@
|
|||||||
catch { return `${currency} ${price.toFixed(2)}`; }
|
catch { return `${currency} ${price.toFixed(2)}`; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleStore(name) {
|
||||||
|
const next = new Set(excludedStores);
|
||||||
|
if (next.has(name)) next.delete(name);
|
||||||
|
else next.add(name);
|
||||||
|
excludedStores = next;
|
||||||
|
}
|
||||||
|
|
||||||
function sortIcon(column) {
|
function sortIcon(column) {
|
||||||
if (sortBy !== column) return '';
|
if (sortBy !== column) return '';
|
||||||
return sortAsc ? '\u2191' : '\u2193';
|
return sortAsc ? '\u2191' : '\u2193';
|
||||||
@@ -154,15 +161,32 @@
|
|||||||
text-text-primary placeholder-text-tertiary focus:border-accent/50 focus:outline-none transition-colors" />
|
text-text-primary placeholder-text-tertiary focus:border-accent/50 focus:outline-none transition-colors" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<select bind:value={filterStore} class="input-field w-auto text-xs py-1 px-2">
|
<div class="flex items-center gap-1.5">
|
||||||
<option value="">All stores</option>
|
|
||||||
{#each storeNames() as name}
|
{#each storeNames() as name}
|
||||||
<option value={name}>{name}</option>
|
<button
|
||||||
|
onclick={() => toggleStore(name)}
|
||||||
|
class="flex items-center gap-1.5 text-2xs px-2 py-1 rounded border transition-colors duration-100
|
||||||
|
{excludedStores.has(name)
|
||||||
|
? 'bg-surface border-surface-border text-text-tertiary line-through opacity-50 hover:opacity-75'
|
||||||
|
: 'bg-accent-muted border-accent/30 text-accent-text hover:bg-accent/20'}"
|
||||||
|
>
|
||||||
|
<span class="w-3 h-3 rounded-sm border flex items-center justify-center flex-shrink-0
|
||||||
|
{excludedStores.has(name)
|
||||||
|
? 'border-text-tertiary/30'
|
||||||
|
: 'border-accent/50 bg-accent/20'}">
|
||||||
|
{#if !excludedStores.has(name)}
|
||||||
|
<svg class="w-2 h-2 text-accent-text" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="3">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" d="M4.5 12.75l6 6 9-13.5" />
|
||||||
|
</svg>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
{name}
|
||||||
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</div>
|
||||||
|
|
||||||
<span class="text-2xs text-text-tertiary">
|
<span class="text-2xs text-text-tertiary whitespace-nowrap">
|
||||||
{filteredAndSorted().length} of {results.length} shown
|
{filteredAndSorted().length} of {results.length}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user