This commit is contained in:
Andras Schmelczer 2026-02-14 12:53:29 +00:00
parent 3a3f899ea2
commit 128b3191e7
68 changed files with 28060 additions and 1152 deletions

View file

@ -1,67 +1,83 @@
import { useState, useCallback } from 'react';
import { useState, useCallback, useMemo } from 'react';
export type TransportMode = 'car' | 'bicycle' | 'walking' | 'transit';
export interface TravelTimeState {
enabled: boolean;
export const TRANSPORT_MODES: TransportMode[] = ['car', 'bicycle', 'walking', 'transit'];
export const MODE_LABELS: Record<TransportMode, string> = {
car: 'Car',
bicycle: 'Bicycle',
walking: 'Walking',
transit: 'Transit',
};
export interface TravelTimeEntry {
destination: [number, number] | null; // [lat, lon]
destinationLabel: string;
mode: TransportMode;
timeRange: [number, number] | null;
}
export type TravelTimeEntries = Partial<Record<TransportMode, TravelTimeEntry>>;
export interface TravelTimeInitial {
destination?: [number, number];
destinationLabel?: string;
mode?: TransportMode;
timeRange?: [number, number];
entries?: TravelTimeEntries;
}
export function useTravelTime(initial?: TravelTimeInitial) {
const [enabled, setEnabled] = useState(!!initial?.destination);
const [destination, setDestination] = useState<[number, number] | null>(
initial?.destination ?? null
);
const [destinationLabel, setDestinationLabel] = useState(initial?.destinationLabel ?? '');
const [mode, setMode] = useState<TransportMode>(initial?.mode ?? 'car');
const [timeRange, setTimeRange] = useState<[number, number] | null>(
initial?.timeRange ?? null
const [entries, setEntries] = useState<TravelTimeEntries>(initial?.entries ?? {});
const activeModes = useMemo(
() => TRANSPORT_MODES.filter((m) => m in entries),
[entries]
);
const handleEnable = useCallback(() => {
setEnabled(true);
const modesWithDestination = useMemo(
() => TRANSPORT_MODES.filter((m) => entries[m]?.destination != null),
[entries]
);
const handleEnableMode = useCallback((mode: TransportMode) => {
setEntries((prev) => ({
...prev,
[mode]: { destination: null, destinationLabel: '', timeRange: null },
}));
}, []);
const handleDisable = useCallback(() => {
setEnabled(false);
setDestination(null);
setDestinationLabel('');
setTimeRange(null);
const handleDisableMode = useCallback((mode: TransportMode) => {
setEntries((prev) => {
const next = { ...prev };
delete next[mode];
return next;
});
}, []);
const handleSetDestination = useCallback((lat: number, lon: number, label: string) => {
setDestination([lat, lon]);
setDestinationLabel(label);
}, []);
const handleSetDestination = useCallback(
(mode: TransportMode, lat: number, lon: number, label: string) => {
setEntries((prev) => ({
...prev,
[mode]: { ...prev[mode], destination: [lat, lon] as [number, number], destinationLabel: label },
}));
},
[]
);
const handleModeChange = useCallback((newMode: TransportMode) => {
setMode(newMode);
}, []);
const handleTimeRangeChange = useCallback((range: [number, number]) => {
setTimeRange(range);
}, []);
const handleTimeRangeChange = useCallback(
(mode: TransportMode, range: [number, number]) => {
setEntries((prev) => ({
...prev,
[mode]: { ...prev[mode], timeRange: range },
}));
},
[]
);
return {
enabled,
destination,
destinationLabel,
mode,
timeRange,
handleEnable,
handleDisable,
entries,
activeModes,
modesWithDestination,
handleEnableMode,
handleDisableMode,
handleSetDestination,
handleModeChange,
handleTimeRangeChange,
};
}