This commit is contained in:
Andras Schmelczer 2026-07-12 20:37:39 +01:00
parent 9e4e65fa2a
commit ca771a7edf
32 changed files with 1467 additions and 109 deletions

View file

@ -93,23 +93,23 @@ interface UseFiltersOptions {
onFilterLimitReached?: () => void;
}
// Applied in order: each normalizer folds its own raw feature names into a single
// folded filter. Council folds AFTER tenure so a bare "% Social rent" is claimed by
// tenure first.
const FILTER_NORMALIZERS: Array<(filters: FeatureFilters) => FeatureFilters> = [
normalizeSchoolFilters,
normalizeSpecificCrimeFilters,
normalizeCrimeSeverityFilters,
normalizeElectionVoteShareFilters,
normalizeEthnicityFilters,
normalizeQualificationFilters,
normalizeTenureFilters,
normalizeCouncilFilters,
normalizePoiDistanceFilters,
];
function normalizeFilters(filters: FeatureFilters): FeatureFilters {
return normalizePoiDistanceFilters(
// Council folds AFTER tenure so a bare "% Social rent" is claimed by tenure.
normalizeCouncilFilters(
normalizeTenureFilters(
normalizeQualificationFilters(
normalizeEthnicityFilters(
normalizeElectionVoteShareFilters(
normalizeCrimeSeverityFilters(
normalizeSpecificCrimeFilters(normalizeSchoolFilters(filters))
)
)
)
)
)
)
);
return FILTER_NORMALIZERS.reduce((acc, normalize) => normalize(acc), filters);
}
function getBackendFeatureName(name: string): string {

View file

@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
import pb from '../lib/pocketbase';
import { apiUrl, authHeaders } from '../lib/api';
import { trackEvent } from '../lib/analytics';
import { stripSelectedPostcodeParam } from '../lib/url-state';
export interface SavedSearch {
id: string;
@ -141,7 +142,11 @@ export function useSavedSearches(userId: string | null) {
setSaving(true);
setError(null);
try {
const params = paramsOverride ?? window.location.search.replace(/^\?/, '');
// A saved search stores filter criteria, so drop the transient
// selected-postcode param (a search/map-click leaves it in the URL).
const params = stripSelectedPostcodeParam(
paramsOverride ?? window.location.search.replace(/^\?/, '')
);
// Create record immediately without screenshot
const formData = new FormData();
@ -220,11 +225,14 @@ export function useSavedSearches(userId: string | null) {
);
const updateSearchParams = useCallback(
async (id: string, params: string) => {
async (id: string, rawParams: string) => {
if (!userId) return;
setSaving(true);
setError(null);
try {
// Match saveSearch: a saved search never carries the transient
// selected-postcode param.
const params = stripSelectedPostcodeParam(rawParams);
const record = await pb.collection('saved_searches').update(id, { params });
trackEvent('Search Update');
setSearches((prev) =>