Fixes
This commit is contained in:
parent
d3418c67cc
commit
5135429d91
13 changed files with 383 additions and 276 deletions
|
|
@ -15,6 +15,13 @@ export interface AiTravelTimeFilter {
|
|||
max?: number;
|
||||
}
|
||||
|
||||
export interface AiMatchBounds {
|
||||
south: number;
|
||||
west: number;
|
||||
north: number;
|
||||
east: number;
|
||||
}
|
||||
|
||||
export interface AiFiltersResult {
|
||||
filters: FeatureFilters;
|
||||
travelTimeFilters: AiTravelTimeFilter[];
|
||||
|
|
@ -23,6 +30,8 @@ export interface AiFiltersResult {
|
|||
summary: string;
|
||||
/** Number of properties matching the proposed filters (excludes travel time) */
|
||||
matchCount: number;
|
||||
/** Bounding box of the matching properties, if any matched */
|
||||
matchBounds: AiMatchBounds | null;
|
||||
}
|
||||
|
||||
export type AiFilterErrorType = 'auth' | 'limit' | 'error';
|
||||
|
|
@ -152,6 +161,7 @@ export function useAiFilters(): UseAiFiltersResult {
|
|||
notes: json.notes || '',
|
||||
summary: summaryText,
|
||||
matchCount,
|
||||
matchBounds: (json.match_bounds as AiMatchBounds | undefined) ?? null,
|
||||
};
|
||||
setNotes(result.notes || null);
|
||||
setSummary(summaryText);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@ interface FilterCountsResponse {
|
|||
}
|
||||
|
||||
/**
|
||||
* Fetches per-filter rejection counts: for each active filter,
|
||||
* how many in-bounds properties that filter removes.
|
||||
* Single source of truth for the in-view property count. Returns:
|
||||
* - `total`: exact count of in-bounds properties passing the active filters
|
||||
* (or the full in-bounds total when there are none); null until first load.
|
||||
* - `impacts`: per-filter rejection counts — how many in-bounds properties
|
||||
* each active filter removes.
|
||||
*/
|
||||
export function useFilterCounts(
|
||||
filters: FeatureFilters,
|
||||
|
|
@ -23,7 +26,10 @@ export function useFilterCounts(
|
|||
shareCode?: string
|
||||
) {
|
||||
const [impacts, setImpacts] = useState<Record<string, number>>({});
|
||||
const [total, setTotal] = useState<number>(0);
|
||||
// null = not loaded yet for the current bounds (hide the counter until the
|
||||
// first response). The number is the exact count of in-bounds properties
|
||||
// passing the active filters — and, with no filters, the total in bounds.
|
||||
const [total, setTotal] = useState<number | null>(null);
|
||||
const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const abortRef = useRef<AbortController | null>(null);
|
||||
|
||||
|
|
@ -39,16 +45,7 @@ export function useFilterCounts(
|
|||
if (!bounds) {
|
||||
abortRef.current?.abort();
|
||||
setImpacts({});
|
||||
setTotal(0);
|
||||
return;
|
||||
}
|
||||
|
||||
const filterCount = Object.keys(filters).length;
|
||||
const hasTravelFilters = travelTimeEntries.some((e) => e.slug && e.timeRange);
|
||||
if (filterCount === 0 && !hasTravelFilters) {
|
||||
abortRef.current?.abort();
|
||||
setImpacts({});
|
||||
setTotal(0);
|
||||
setTotal(null);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,7 +31,9 @@ export function useTutorial(initialLoading: boolean, isMobile: boolean, blocked
|
|||
target: '[data-tutorial="map"]',
|
||||
title: t('tutorial.step3Title'),
|
||||
content: t('tutorial.step3Content'),
|
||||
placement: 'top' as const,
|
||||
// The map fills the viewport; directional placements push the tooltip
|
||||
// off-screen. Center it over the map instead.
|
||||
placement: 'center' as const,
|
||||
skipBeacon: true,
|
||||
},
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue