perfect-postcode/frontend/src/lib/travel-params.ts
2026-05-15 08:17:05 +01:00

66 lines
1.8 KiB
TypeScript

import type { TravelTimeEntry } from '../hooks/useTravelTime';
function mergeTimeRanges(
current: [number, number] | null,
next: [number, number] | null
): [number, number] | null {
if (!current) return next;
if (!next) return current;
return [Math.max(current[0], next[0]), Math.min(current[1], next[1])];
}
export function dedupeTravelTimeEntries(entries: TravelTimeEntry[]): TravelTimeEntry[] {
const result: TravelTimeEntry[] = [];
const indexByKey = new Map<string, number>();
for (const entry of entries) {
if (!entry.slug) {
result.push(entry);
continue;
}
const key = `${entry.mode}:${entry.slug}`;
const existingIndex = indexByKey.get(key);
if (existingIndex == null) {
indexByKey.set(key, result.length);
result.push({ ...entry });
continue;
}
const existing = result[existingIndex];
result[existingIndex] = {
...existing,
label: existing.label || entry.label,
timeRange: mergeTimeRanges(existing.timeRange, entry.timeRange),
useBest: existing.useBest || entry.useBest,
};
}
return result;
}
export function buildTravelParam(
entries: TravelTimeEntry[],
excludeFieldKey?: string,
includeUnboundedExcludedRange = false
): string {
const segments: string[] = [];
for (const entry of dedupeTravelTimeEntries(entries)) {
if (!entry.slug) continue;
let segment = `${entry.mode}:${entry.slug}`;
if (entry.useBest) segment += ':best';
const isExcluded = excludeFieldKey === `tt_${entry.mode}_${entry.slug}`;
if (isExcluded && includeUnboundedExcludedRange) {
segment += ':0:1440';
} else if (!isExcluded && entry.timeRange) {
segment += `:${entry.timeRange[0]}:${entry.timeRange[1]}`;
}
segments.push(segment);
}
return segments.join('|');
}