9e461aab1a
Switch mobile app to dark theme and fix calendar filtering - Default to dark theme in mobile app, matching web app style - Filter native calendar events by location to exclude empty ones - Add batch edit panel for destinations on web calendar - Add edit support to AddEventModal - Update notification trigger input type export
64 lines
2.2 KiB
TypeScript
64 lines
2.2 KiB
TypeScript
import { useMemo } from 'react';
|
|
import type { Journey } from '@timetoleave/core';
|
|
|
|
interface DepartureTimeResult {
|
|
departureTime: Date | null;
|
|
arrivalTime: Date | null;
|
|
mode: 'train' | 'bike' | null;
|
|
}
|
|
|
|
/**
|
|
* Calculate departure time based on selected transport mode.
|
|
* Mirrors the web app's useDepartureTime hook.
|
|
*/
|
|
export function useDepartureTime(
|
|
eventTime: Date,
|
|
journeys: Journey[] | null,
|
|
bikeDurationSeconds: number | null,
|
|
activeMode: 'train' | 'bike' | null,
|
|
arrivalBufferMinutes: number,
|
|
): DepartureTimeResult {
|
|
return useMemo(() => {
|
|
// Calculate target arrival time (event time minus buffer)
|
|
const targetArrivalTime = new Date(eventTime);
|
|
targetArrivalTime.setMinutes(targetArrivalTime.getMinutes() - arrivalBufferMinutes);
|
|
|
|
// Filter out cancelled journeys
|
|
const validJourneys = journeys?.filter((journey) => !journey.cancelled) || [];
|
|
|
|
let departureTime: Date | null = null;
|
|
let arrivalTime: Date | null = null;
|
|
let mode: 'train' | 'bike' | null = null;
|
|
|
|
if (activeMode === 'train' && validJourneys.length > 0) {
|
|
// Find journeys that arrive by target time
|
|
const onTimeJourneys = validJourneys.filter(
|
|
(journey) => journey.rA.getTime() <= targetArrivalTime.getTime(),
|
|
);
|
|
|
|
if (onTimeJourneys.length > 0) {
|
|
// Pick the journey with the latest departure that still arrives on time
|
|
const bestJourney = onTimeJourneys.reduce((latest, current) =>
|
|
current.rD.getTime() > latest.rD.getTime() ? current : latest,
|
|
);
|
|
|
|
departureTime = new Date(bestJourney.rD);
|
|
arrivalTime = new Date(bestJourney.rA);
|
|
mode = 'train';
|
|
}
|
|
}
|
|
|
|
if (activeMode === 'bike' && bikeDurationSeconds !== null && bikeDurationSeconds > 0) {
|
|
const bikeDurationMs = bikeDurationSeconds * 1000;
|
|
const totalBufferMs = arrivalBufferMinutes * 60 * 1000;
|
|
const targetArrivalMs = eventTime.getTime() - totalBufferMs;
|
|
|
|
departureTime = new Date(targetArrivalMs - bikeDurationMs);
|
|
arrivalTime = new Date(targetArrivalMs);
|
|
mode = 'bike';
|
|
}
|
|
|
|
return { departureTime, arrivalTime, mode };
|
|
}, [eventTime, journeys, bikeDurationSeconds, activeMode, arrivalBufferMinutes]);
|
|
}
|