lmao
This commit is contained in:
parent
03445188ea
commit
524580eb25
102 changed files with 36625 additions and 1295 deletions
|
|
@ -12,71 +12,73 @@ export const MODE_LABELS: Record<TransportMode, string> = {
|
|||
};
|
||||
|
||||
export interface TravelTimeEntry {
|
||||
destination: [number, number] | null; // [lat, lon]
|
||||
destinationLabel: string;
|
||||
mode: TransportMode;
|
||||
slug: string;
|
||||
label: string;
|
||||
timeRange: [number, number] | null;
|
||||
}
|
||||
|
||||
export type TravelTimeEntries = Partial<Record<TransportMode, TravelTimeEntry>>;
|
||||
/** Unique key for a travel time entry */
|
||||
export function travelEntryKey(entry: TravelTimeEntry): string {
|
||||
return `${entry.mode}:${entry.slug}`;
|
||||
}
|
||||
|
||||
/** Field key matching the backend response: tt_{mode}_{slug} */
|
||||
export function travelFieldKey(entry: TravelTimeEntry): string {
|
||||
return `tt_${entry.mode}_${entry.slug}`;
|
||||
}
|
||||
|
||||
export interface TravelTimeInitial {
|
||||
entries?: TravelTimeEntries;
|
||||
entries?: TravelTimeEntry[];
|
||||
}
|
||||
|
||||
export function useTravelTime(initial?: TravelTimeInitial) {
|
||||
const [entries, setEntries] = useState<TravelTimeEntries>(initial?.entries ?? {});
|
||||
const [entries, setEntries] = useState<TravelTimeEntry[]>(initial?.entries ?? []);
|
||||
|
||||
const activeModes = useMemo(
|
||||
() => TRANSPORT_MODES.filter((m) => m in entries),
|
||||
[entries]
|
||||
);
|
||||
|
||||
const modesWithDestination = useMemo(
|
||||
() => TRANSPORT_MODES.filter((m) => entries[m]?.destination != null),
|
||||
[entries]
|
||||
);
|
||||
|
||||
const handleEnableMode = useCallback((mode: TransportMode) => {
|
||||
setEntries((prev) => ({
|
||||
const handleAddEntry = useCallback((mode: TransportMode) => {
|
||||
setEntries((prev) => [
|
||||
...prev,
|
||||
[mode]: { destination: null, destinationLabel: '', timeRange: null },
|
||||
}));
|
||||
{ mode, slug: '', label: '', timeRange: null },
|
||||
]);
|
||||
}, []);
|
||||
|
||||
const handleDisableMode = useCallback((mode: TransportMode) => {
|
||||
setEntries((prev) => {
|
||||
const next = { ...prev };
|
||||
delete next[mode];
|
||||
return next;
|
||||
});
|
||||
const handleRemoveEntry = useCallback((index: number) => {
|
||||
setEntries((prev) => prev.filter((_, i) => i !== index));
|
||||
}, []);
|
||||
|
||||
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 },
|
||||
}));
|
||||
(index: number, slug: string, label: string) => {
|
||||
setEntries((prev) =>
|
||||
prev.map((entry, i) =>
|
||||
i === index ? { ...entry, slug, label, timeRange: null } : entry
|
||||
)
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
const handleTimeRangeChange = useCallback(
|
||||
(mode: TransportMode, range: [number, number]) => {
|
||||
setEntries((prev) => ({
|
||||
...prev,
|
||||
[mode]: { ...prev[mode], timeRange: range },
|
||||
}));
|
||||
(index: number, range: [number, number]) => {
|
||||
setEntries((prev) =>
|
||||
prev.map((entry, i) =>
|
||||
i === index ? { ...entry, timeRange: range } : entry
|
||||
)
|
||||
);
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
/** Entries that have a destination selected (slug is set) */
|
||||
const activeEntries = useMemo(
|
||||
() => entries.filter((e) => e.slug !== ''),
|
||||
[entries]
|
||||
);
|
||||
|
||||
return {
|
||||
entries,
|
||||
activeModes,
|
||||
modesWithDestination,
|
||||
handleEnableMode,
|
||||
handleDisableMode,
|
||||
activeEntries,
|
||||
handleAddEntry,
|
||||
handleRemoveEntry,
|
||||
handleSetDestination,
|
||||
handleTimeRangeChange,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue