feat(11-06): SavedSearchBar UI — save/load/rename/delete profiles (FILTER-06)

GREEN phase — extends tender-radar-api.ts with listSavedSearches/
createSavedSearch/updateSavedSearch/deleteSavedSearch (plain fetch,
credentials: include), adds SavedSearchBar with the
serializeFiltersFromSearchParams/filtersToSearchParams round-trip helpers
(URL searchParams <-> filters JSON, deliberately excluding page/tender —
navigation state, not filter state), and mounts it above FilterPanel in
page.tsx. Hardcoded German UI per phase convention.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-21 16:50:55 +02:00
parent ca843ab134
commit dd3ff9ea30
3 changed files with 408 additions and 0 deletions
@@ -5,6 +5,7 @@ import { useRouter, useSearchParams } from 'next/navigation';
import { CoverageBanner } from './components/CoverageBanner';
import { FilterPanel } from './components/FilterPanel';
import { ResultsList } from './components/ResultsList';
import { SavedSearchBar } from './components/SavedSearchBar';
import { TenderDetail } from './components/TenderDetail';
/**
@@ -28,6 +29,11 @@ import { TenderDetail } from './components/TenderDetail';
* `dynamic(..., { ssr: false })` (module-loader.ts), per the plan's
* explicit Next 16 guidance.
*
* Plan 11-06 (FILTER-06, D-08/D-11): SavedSearchBar renders above
* FilterPanel — it reads/writes the same URL searchParams FilterPanel
* uses, so saving/loading a profile is congruent with the filter state the
* user currently sees.
*
* Intentional hardcoded German strings: full i18n (next-intl message
* keys) is CONFIG-03, planned for Phase 14 (Research Open Question 3,
* RESOLVED).
@@ -52,6 +58,7 @@ function TenderRadarContent() {
</div>
<CoverageBanner />
<SavedSearchBar />
<FilterPanel />
<ResultsList />