More fixes
This commit is contained in:
parent
15fa09430b
commit
6b12e21d50
54 changed files with 1665 additions and 630 deletions
|
|
@ -17,6 +17,8 @@ export interface AiFiltersResult {
|
|||
notes: string;
|
||||
/** Human-readable summary of what was set */
|
||||
summary: string;
|
||||
/** The listing mode used (historical/buy/rent) */
|
||||
listingType: string;
|
||||
}
|
||||
|
||||
export type AiFilterErrorType = 'auth' | 'limit' | 'error';
|
||||
|
|
@ -28,7 +30,11 @@ export interface AiFiltersContext {
|
|||
}
|
||||
|
||||
interface UseAiFiltersResult {
|
||||
fetchAiFilters: (query: string, context?: AiFiltersContext) => Promise<AiFiltersResult | null>;
|
||||
fetchAiFilters: (
|
||||
query: string,
|
||||
context?: AiFiltersContext,
|
||||
listingType?: string
|
||||
) => Promise<AiFiltersResult | null>;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
errorType: AiFilterErrorType | null;
|
||||
|
|
@ -41,6 +47,8 @@ function buildSummary(filters: FeatureFilters, travelTimeFilters: AiTravelTimeFi
|
|||
const parts: string[] = [];
|
||||
|
||||
for (const [name, value] of Object.entries(filters)) {
|
||||
// Skip Listing status — shown via the mode selector UI
|
||||
if (name === 'Listing status') continue;
|
||||
if (Array.isArray(value) && value.length === 2 && typeof value[0] === 'number') {
|
||||
parts.push(name);
|
||||
} else if (Array.isArray(value)) {
|
||||
|
|
@ -67,7 +75,11 @@ export function useAiFilters(): UseAiFiltersResult {
|
|||
const abortRef = useRef<AbortController | null>(null);
|
||||
|
||||
const fetchAiFilters = useCallback(
|
||||
async (query: string, context?: AiFiltersContext): Promise<AiFiltersResult | null> => {
|
||||
async (
|
||||
query: string,
|
||||
context?: AiFiltersContext,
|
||||
listingType?: string
|
||||
): Promise<AiFiltersResult | null> => {
|
||||
abortRef.current?.abort();
|
||||
const controller = new AbortController();
|
||||
abortRef.current = controller;
|
||||
|
|
@ -81,6 +93,7 @@ export function useAiFilters(): UseAiFiltersResult {
|
|||
try {
|
||||
const url = apiUrl('ai-filters');
|
||||
const bodyObj: Record<string, unknown> = { query };
|
||||
if (listingType) bodyObj.listing_type = listingType;
|
||||
if (context) {
|
||||
bodyObj.context = {
|
||||
filters: context.filters,
|
||||
|
|
@ -130,6 +143,7 @@ export function useAiFilters(): UseAiFiltersResult {
|
|||
travelTimeFilters,
|
||||
notes: json.notes || '',
|
||||
summary: summaryText,
|
||||
listingType: json.listing_type || 'historical',
|
||||
};
|
||||
setNotes(result.notes || null);
|
||||
setSummary(summaryText);
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ export function useDeckLayers({
|
|||
useEffect(() => {
|
||||
if (!hasSelection) return;
|
||||
setMarchTime(0);
|
||||
const id = setInterval(() => setMarchTime((t) => t + 0.3), 50);
|
||||
const id = setInterval(() => setMarchTime((t) => (t + 0.3) % 10000), 50);
|
||||
return () => clearInterval(id);
|
||||
}, [hasSelection]);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
import { useState, useCallback, useMemo } from 'react';
|
||||
import type { ComponentType } from 'react';
|
||||
import { CarIcon, BicycleIcon, WalkingIcon, TransitIcon } from '../components/ui/icons';
|
||||
|
||||
export type TransportMode = 'car' | 'bicycle' | 'walking' | 'transit';
|
||||
|
||||
|
|
@ -18,6 +20,13 @@ export const MODE_DESCRIPTIONS: Record<TransportMode, string> = {
|
|||
transit: 'Journey time by train, tube, and bus',
|
||||
};
|
||||
|
||||
export const MODE_ICONS: Record<TransportMode, ComponentType<{ className?: string }>> = {
|
||||
car: CarIcon,
|
||||
bicycle: BicycleIcon,
|
||||
walking: WalkingIcon,
|
||||
transit: TransitIcon,
|
||||
};
|
||||
|
||||
export interface TravelTimeEntry {
|
||||
mode: TransportMode;
|
||||
slug: string;
|
||||
|
|
|
|||
|
|
@ -59,13 +59,13 @@ const STEPS: Step[] = [
|
|||
},
|
||||
];
|
||||
|
||||
export function useTutorial(initialLoading: boolean, isMobile: boolean) {
|
||||
export function useTutorial(initialLoading: boolean, isMobile: boolean, blocked = false) {
|
||||
const [run, setRun] = useState(() => {
|
||||
if (isMobile) return false;
|
||||
return !localStorage.getItem(STORAGE_KEY);
|
||||
});
|
||||
|
||||
const shouldRun = run && !initialLoading && !isMobile;
|
||||
const shouldRun = run && !initialLoading && !isMobile && !blocked;
|
||||
|
||||
const handleCallback = useCallback((data: CallBackProps) => {
|
||||
const { status, action, type } = data;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue