Small fixes & fmt
This commit is contained in:
parent
6b12e21d50
commit
f32a552f46
23 changed files with 347 additions and 99 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useCallback, useMemo, useRef } from 'react';
|
||||
import { useState, useCallback, useMemo, useRef, useEffect } from 'react';
|
||||
import type { FeatureMeta, FeatureFilters } from '../types';
|
||||
import { trackEvent } from '../lib/analytics';
|
||||
|
||||
|
|
@ -15,6 +15,7 @@ export function useFilters({ initialFilters, features }: UseFiltersOptions) {
|
|||
const pendingDragRef = useRef<string | null>(null);
|
||||
const dragActiveRef = useRef<string | null>(null);
|
||||
const dragValueRef = useRef<[number, number] | null>(null);
|
||||
const undoStackRef = useRef<FeatureFilters[]>([]);
|
||||
|
||||
const enabledFeatures = useMemo(() => new Set(Object.keys(filters)), [filters]);
|
||||
|
||||
|
|
@ -34,17 +35,41 @@ export function useFilters({ initialFilters, features }: UseFiltersOptions) {
|
|||
const meta = features.find((f) => f.name === name);
|
||||
if (!meta) return;
|
||||
trackEvent('Filter Add', { feature: name });
|
||||
if (meta.type === 'enum' && meta.values) {
|
||||
setFilters((prev) => ({ ...prev, [name]: [...meta.values!] }));
|
||||
} else if (meta.type === 'numeric' && meta.histogram) {
|
||||
setFilters((prev) => ({ ...prev, [name]: [meta.histogram!.min, meta.histogram!.max] }));
|
||||
} else if (meta.min != null && meta.max != null) {
|
||||
setFilters((prev) => ({ ...prev, [name]: [meta.min!, meta.max!] }));
|
||||
}
|
||||
setFilters((prev) => {
|
||||
undoStackRef.current.push(prev);
|
||||
if (undoStackRef.current.length > 50) undoStackRef.current.shift();
|
||||
if (meta.type === 'enum' && meta.values) {
|
||||
return { ...prev, [name]: [...meta.values!] };
|
||||
} else if (meta.type === 'numeric' && meta.histogram) {
|
||||
return { ...prev, [name]: [meta.histogram!.min, meta.histogram!.max] };
|
||||
} else if (meta.min != null && meta.max != null) {
|
||||
return { ...prev, [name]: [meta.min!, meta.max!] };
|
||||
}
|
||||
return prev;
|
||||
});
|
||||
},
|
||||
[features]
|
||||
);
|
||||
|
||||
const handleUndo = useCallback(() => {
|
||||
const prev = undoStackRef.current.pop();
|
||||
if (prev) setFilters(prev);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const handler = (e: KeyboardEvent) => {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === 'z' && !e.shiftKey) {
|
||||
const target = e.target as HTMLElement;
|
||||
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA' || target.isContentEditable)
|
||||
return;
|
||||
e.preventDefault();
|
||||
handleUndo();
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', handler);
|
||||
return () => window.removeEventListener('keydown', handler);
|
||||
}, [handleUndo]);
|
||||
|
||||
const handleFilterChange = useCallback((name: string, value: [number, number] | string[]) => {
|
||||
setFilters((prev) => ({ ...prev, [name]: value }));
|
||||
}, []);
|
||||
|
|
|
|||
|
|
@ -167,6 +167,15 @@ export function useSavedSearches(userId: string | null) {
|
|||
}
|
||||
}, []);
|
||||
|
||||
const updateSearchName = useCallback(async (id: string, name: string) => {
|
||||
try {
|
||||
await pb.collection('saved_searches').update(id, { name });
|
||||
setSearches((prev) => prev.map((s) => (s.id === id ? { ...s, name } : s)));
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : 'Failed to update name');
|
||||
}
|
||||
}, []);
|
||||
|
||||
return {
|
||||
searches,
|
||||
loading,
|
||||
|
|
@ -176,5 +185,6 @@ export function useSavedSearches(userId: string | null) {
|
|||
saveSearch,
|
||||
deleteSearch,
|
||||
updateSearchNotes,
|
||||
updateSearchName,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,12 @@ export function useTravelDestinations(mode: TransportMode) {
|
|||
return res.json();
|
||||
})
|
||||
.then((data: { destinations: Destination[] }) => {
|
||||
cacheRef.current[mode] = data.destinations;
|
||||
setDestinations(data.destinations);
|
||||
const normalized = data.destinations.map((d) => ({
|
||||
...d,
|
||||
city: d.city === 'City of London' ? 'London' : d.city,
|
||||
}));
|
||||
cacheRef.current[mode] = normalized;
|
||||
setDestinations(normalized);
|
||||
})
|
||||
.catch((err) => logNonAbortError('travel destinations', err))
|
||||
.finally(() => setLoading(false));
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue