Rename SearchBar to PostSearchFilters, add sort controls and brand filter, relocate station count display
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.3) (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled

- Move SearchBar.vue to PostSearchFilters.vue and expand to include sort buttons, brand filter dropdown, and station count
- Integrate sort controls (Reliable/Price/Distance/Updated) with icons into filter bar
- Add brand filter dropdown with dynamic brand list from parent, emit update events
- Move station count from StationList to PostSearchFilters, display as "X station(s) found"
- Remove sort tabs and brand filter from StationList component
- Add force-new-line div for mobile layout between Refine and Sort groups
- Include brand filter in hasActive check and resetFilters function
- Update Home.vue to pass brands/brandFilter props and handle brandFilter updates
- Add reset() method to useStations composable to clear state on empty query
- Clear search state when route query is empty instead of attempting search
- Update Fuel Finder API base URL to include /api/v1 path
- Adjust map zoom levels for 10-15 mile radius range
- Update API token request to use retry and increase timeout to 60s
This commit is contained in:
Ovidiu U
2026-04-22 11:50:59 +01:00
parent 8335f49fd6
commit b4bd78ab4c
7 changed files with 96 additions and 95 deletions

View File

@@ -1,47 +1,5 @@
<template>
<div class="space-y-3">
<!-- Sort tabs -->
<div class="flex flex-wrap items-center gap-2 md:gap-2.5 py-3 border-b border-zinc-200">
<span class="hidden md:inline text-xs font-mono uppercase tracking-widest text-zinc-400 mr-1">
Sort
</span>
<button
v-for="option in sortOptions"
:key="option.value"
:class="{ 'is-active': currentSort === option.value }"
class="pill"
type="button"
@click="emit('sort', option.value)"
>
<iconify-icon :icon="option.icon" class="text-sm opacity-70"></iconify-icon>
<span class="text-sm font-medium">{{ option.label }}</span>
</button>
<!-- Brand filter -->
<label
v-if="brands.length > 1"
:class="{ 'is-active': brandFilter }"
class="pill group"
>
<iconify-icon class="text-sm opacity-70" icon="lucide:tag"></iconify-icon>
<span class="text-sm font-medium">{{ brandFilter || 'All brands' }}</span>
<iconify-icon class="text-sm opacity-50 group-hover:opacity-100" icon="lucide:chevron-down"></iconify-icon>
<select
:value="brandFilter"
aria-label="Filter by brand"
class="absolute inset-0 opacity-0 cursor-pointer"
@change="emit('update:brandFilter', $event.target.value)"
>
<option value="">All brands</option>
<option v-for="brand in brands" :key="brand" :value="brand">{{ brand }}</option>
</select>
</label>
<span class="ml-auto text-sm text-zinc-500 font-medium">
{{ stations.length }} station{{ stations.length !== 1 ? 's' : '' }} found
</span>
</div>
<!-- Grouped results when sorting by reliability -->
<template v-if="currentSort === 'reliable'">
<section v-if="reliable.length" class="space-y-2">
@@ -121,19 +79,8 @@ const props = defineProps({
stations: { type: Array, required: true },
currentSort: { type: String, default: 'reliable' },
origin: { type: Object, default: null },
brands: { type: Array, default: () => [] },
brandFilter: { type: String, default: '' },
})
const emit = defineEmits(['sort', 'update:brandFilter'])
const sortOptions = [
{ label: 'Reliable', value: 'reliable', icon: 'lucide:shield-check' },
{ label: 'Price', value: 'price', icon: 'lucide:pound-sterling' },
{ label: 'Distance', value: 'distance', icon: 'lucide:map-pin' },
{ label: 'Updated', value: 'updated', icon: 'lucide:clock' },
]
const reliable = computed(() => props.stations.filter(s => s.reliability === 'reliable'))
const stale = computed(() => props.stations.filter(s => s.reliability === 'stale'))
const outdated = computed(() => props.stations.filter(s => s.reliability === 'outdated'))