From 9f7b45751ed5b5647b350ed0f181931d5c495116 Mon Sep 17 00:00:00 2001 From: Ovidiu U Date: Sat, 11 Apr 2026 17:15:23 +0100 Subject: [PATCH] docs: add homepage search design spec --- .../2026-04-11-homepage-search-design.md | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 docs/superpowers/specs/2026-04-11-homepage-search-design.md diff --git a/docs/superpowers/specs/2026-04-11-homepage-search-design.md b/docs/superpowers/specs/2026-04-11-homepage-search-design.md new file mode 100644 index 0000000..0d52d39 --- /dev/null +++ b/docs/superpowers/specs/2026-04-11-homepage-search-design.md @@ -0,0 +1,70 @@ +# Homepage Search — Design Spec + +**Date:** 2026-04-11 +**Status:** Approved + +## Overview + +Wire up the `SearchBar` on the homepage so it performs a live station search and renders a map + station list inline, below the search bar. No navigation away from the page. All existing components (`LeafletMap`, `StationList`, `useStations`) are reused as-is, with minimal targeted changes. + +--- + +## Component Changes + +### `SearchBar.vue` + +- Add a **fuel type** `` with options: 2, 5, 10, 20 miles (default: 10) +- Change the `search` emit payload from a bare postcode string to `{ postcode, fuelType, radius }` +- **Remove** the debounced `onInput` handler — search fires on button click only (debounce on a multi-param form causes confusing mid-type fetches) +- Button stays disabled when postcode is empty + +### `LeafletMap.vue` + +- Add a `defaultOpen` Boolean prop (default `false`) for backwards compatibility +- When `defaultOpen` is `true`, initialise the map on `onMounted` instead of waiting for the toggle +- Toggle button remains so users can collapse the map +- Auto-renders markers when `stations` prop is populated after mount + +### `Home.vue` + +- Import `useStations` and hold `sort` ref (default `'price'`) +- On `@search` from `SearchBar`, call `useStations.search({ postcode, fuelType, radius, sort })` +- Add a results `
` directly below the hero section — full width, `max-w-7xl` container, `px-6 py-10` padding +- Results section only renders when a search has been attempted (`stations.length || loading || error`) +- Results layout (top to bottom): + 1. `LeafletMap` with `:stations="stations"` and `:default-open="true"` — `h-80` height + 2. `StationList` with `:stations="stations"` `:current-sort="sort"` `@sort="onSort"` +- **Loading state:** spinner centred in the results section, replaces map+list +- **Error state:** inline error message (`error.general[0]` or fallback text), replaces map+list +- `onSort` handler updates `sort` ref and re-runs `search()` with last used params (store params in a `lastParams` ref) + +--- + +## Data Flow + +``` +SearchBar emits { postcode, fuelType, radius } + → Home.vue calls useStations.search({ ...params, sort }) + → API GET /stations?postcode=...&fuel_type=...&radius=...&sort=... + → stations ref populated + → LeafletMap renders markers (auto-open) + → StationList renders cards +``` + +--- + +## What Is Not Changing + +- `StationCard.vue` — no changes +- `useStations.js` — no changes +- API layer — no changes +- Dashboard usage of `LeafletMap` and `StationList` — unaffected (defaultOpen defaults to false) + +--- + +## Out of Scope + +- Saving/favouriting stations from homepage (dashboard feature) +- Geolocation "use my location" button +- Pagination of results