ScheduleFilter: wire time range slider to schedule URL + seed from URL
This commit is contained in:
@@ -26,6 +26,12 @@ function minutesToTime(minutes: number): string {
|
||||
return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
function minutesToHhmm(minutes: number): string {
|
||||
const h = Math.floor(minutes / 60);
|
||||
const m = minutes % 60;
|
||||
return `${String(h).padStart(2, "0")}${String(m).padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
function dateToYyyymmdd(value: Date): string {
|
||||
const y = value.getFullYear().toString();
|
||||
const m = (value.getMonth() + 1).toString().padStart(2, "0");
|
||||
@@ -46,15 +52,27 @@ export interface ScheduleFilterProps {
|
||||
initialArrival?: string;
|
||||
initialDateFrom?: string;
|
||||
initialDateTo?: string;
|
||||
initialTimeFrom?: string;
|
||||
initialTimeTo?: string;
|
||||
initialDirectOnly?: boolean;
|
||||
initialReturnFlights?: boolean;
|
||||
}
|
||||
|
||||
function hhmmToMinutes(value: string | undefined, fallback: number): number {
|
||||
if (!value || value.length !== 4) return fallback;
|
||||
const h = Number(value.slice(0, 2));
|
||||
const m = Number(value.slice(2, 4));
|
||||
if (Number.isNaN(h) || Number.isNaN(m)) return fallback;
|
||||
return h * 60 + m;
|
||||
}
|
||||
|
||||
export const ScheduleFilter: FC<ScheduleFilterProps> = ({
|
||||
initialDeparture,
|
||||
initialArrival,
|
||||
initialDateFrom,
|
||||
initialDateTo,
|
||||
initialTimeFrom,
|
||||
initialTimeTo,
|
||||
initialDirectOnly = false,
|
||||
initialReturnFlights = false,
|
||||
}) => {
|
||||
@@ -70,7 +88,10 @@ export const ScheduleFilter: FC<ScheduleFilterProps> = ({
|
||||
const [dateRange, setDateRange] = useState<(Date | null)[]>(
|
||||
initFrom && initTo ? [initFrom, initTo] : [null, null],
|
||||
);
|
||||
const [timeRange, setTimeRange] = useState<[number, number]>([0, 1440]);
|
||||
const [timeRange, setTimeRange] = useState<[number, number]>([
|
||||
hhmmToMinutes(initialTimeFrom, 0),
|
||||
hhmmToMinutes(initialTimeTo, 1440),
|
||||
]);
|
||||
const [directOnly, setDirectOnly] = useState(initialDirectOnly);
|
||||
const [returnFlights, setReturnFlights] = useState(initialReturnFlights);
|
||||
|
||||
@@ -97,20 +118,28 @@ export const ScheduleFilter: FC<ScheduleFilterProps> = ({
|
||||
const from = dateRange[0] ?? monday;
|
||||
const to = dateRange[1] ?? sunday;
|
||||
|
||||
const params: ScheduleParams = {
|
||||
type: "route",
|
||||
outbound: {
|
||||
departure: dep,
|
||||
arrival: arr,
|
||||
dateFrom: dateToYyyymmdd(from),
|
||||
dateTo: dateToYyyymmdd(to),
|
||||
...(directOnly ? { connections: 0 } : {}),
|
||||
},
|
||||
const outbound = {
|
||||
departure: dep,
|
||||
arrival: arr,
|
||||
dateFrom: dateToYyyymmdd(from),
|
||||
dateTo: dateToYyyymmdd(to),
|
||||
// Only include time range when it's been narrowed from the full
|
||||
// day — Angular spreads `...this.timeRange` which is undefined
|
||||
// until the user interacts with the slider, so the URL stays
|
||||
// clean for the default 00:00–24:00 case.
|
||||
...(timeRange[0] !== 0 || timeRange[1] !== 1440
|
||||
? {
|
||||
timeFrom: minutesToHhmm(timeRange[0]),
|
||||
timeTo: minutesToHhmm(timeRange[1]),
|
||||
}
|
||||
: {}),
|
||||
...(directOnly ? { connections: 0 } : {}),
|
||||
};
|
||||
const params: ScheduleParams = { type: "route", outbound };
|
||||
const url = buildScheduleUrl(params);
|
||||
void navigate(`/${locale}/${url}`);
|
||||
},
|
||||
[departure, arrival, dateRange, directOnly, navigate, locale],
|
||||
[departure, arrival, dateRange, timeRange, directOnly, navigate, locale],
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -285,6 +285,8 @@ export const ScheduleSearchPage: FC<ScheduleSearchPageProps> = ({ params }) => {
|
||||
initialArrival={outbound.arrival}
|
||||
initialDateFrom={outbound.dateFrom}
|
||||
initialDateTo={outbound.dateTo}
|
||||
{...(outbound.timeFrom ? { initialTimeFrom: outbound.timeFrom } : {})}
|
||||
{...(outbound.timeTo ? { initialTimeTo: outbound.timeTo } : {})}
|
||||
initialDirectOnly={outbound.connections === 0}
|
||||
initialReturnFlights={Boolean(inbound)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user