has issues

This commit is contained in:
Andras Schmelczer 2026-05-25 13:20:17 +01:00
parent 2e112d7398
commit c645b0f1d4
96 changed files with 2147083 additions and 5787 deletions

View file

@ -1,7 +1,8 @@
import type { FeatureMeta, FeatureFilters, ViewState } from '../types';
import {
TRANSPORT_MODES,
type TransportMode,
MAX_TRAVEL_MINUTES,
parseServerMode,
resolveTransitVariant,
type TravelTimeEntry,
type TravelTimeInitial,
} from '../hooks/useTravelTime';
@ -48,6 +49,7 @@ import {
type PoiFilterName,
} from './poi-distance-filter';
import { dedupeTravelTimeEntries } from './travel-params';
import { isOverlayId, type OverlayId } from './overlays';
const POI_NONE_PARAM = '__none';
@ -55,6 +57,7 @@ export interface UrlState {
viewState: ViewState;
filters: FeatureFilters;
poiCategories: Set<string>;
overlays: Set<OverlayId>;
tab: 'properties' | 'area';
travelTime?: TravelTimeInitial;
postcode?: string;
@ -209,6 +212,7 @@ export function parseUrlState(): UrlState {
viewState: INITIAL_VIEW_STATE,
filters: parseFilters(params),
poiCategories: new Set(),
overlays: new Set(),
tab: 'area',
};
@ -244,6 +248,11 @@ export function parseUrlState(): UrlState {
}
}
const overlayParams = params.getAll('overlay');
if (overlayParams.length > 0) {
result.overlays = new Set(overlayParams.filter(isOverlayId));
}
// Tab: full name
const tab = params.get('tab');
if (tab === 'properties' || tab === 'area') {
@ -257,15 +266,19 @@ export function parseUrlState(): UrlState {
}
// Travel time: repeated `tt` params
// Format: mode:slug:label or mode:slug:label:b or mode:slug:label:min:max or mode:slug:label:b:min:max
// Format: serverMode:slug:label[:b][:min:max]
// serverMode is one of: car | bicycle | walking | transit | transit-no-bus
// | transit-no-change | transit-no-change-no-bus. transit-one-change[-no-bus]
// variants are server-side only and will cause the entry to be dropped here
// (parseServerMode returns null) so we don't silently broaden the user's filter.
const ttParams = params.getAll('tt');
if (ttParams.length > 0) {
const entries: TravelTimeEntry[] = [];
for (const tt of ttParams) {
const parts = tt.split(':');
if (parts.length < 3) continue;
const mode = parts[0] as TransportMode;
if (!TRANSPORT_MODES.includes(mode)) continue;
const parsedMode = parseServerMode(parts[0]);
if (!parsedMode) continue;
const slug = parts[1];
const label = decodeURIComponent(parts[2]);
const useBest = parts.length >= 4 && parts[3] === 'b';
@ -275,10 +288,21 @@ export function parseUrlState(): UrlState {
const min = Number(parts[3 + rangeOffset]);
const max = Number(parts[4 + rangeOffset]);
if (!isNaN(min) && !isNaN(max)) {
timeRange = [min, max];
// Clamp loaded max-time to the data ceiling. Older shared URLs
// may have max=120 from the previous slider range; no data exists
// above MAX_TRAVEL_MINUTES so the result is identical.
timeRange = [min, Math.min(max, MAX_TRAVEL_MINUTES)];
}
}
entries.push({ mode, slug, label, timeRange, useBest });
entries.push({
mode: parsedMode.mode,
slug,
label,
timeRange,
useBest,
noChange: parsedMode.noChange,
noBuses: parsedMode.noBuses,
});
}
if (entries.length > 0) {
result.travelTime = { entries: dedupeTravelTimeEntries(entries) };
@ -295,7 +319,8 @@ export function stateToParams(
selectedPOICategories: Set<string>,
rightPaneTab: 'properties' | 'area',
travelTimeEntries?: TravelTimeEntry[],
share?: string
share?: string,
selectedOverlays?: Set<OverlayId>
): URLSearchParams {
const params = new URLSearchParams();
@ -378,11 +403,18 @@ export function stateToParams(
params.set('tab', 'properties');
}
if (selectedOverlays) {
for (const overlay of selectedOverlays) {
params.append('overlay', overlay);
}
}
// Travel time: repeated `tt` params
if (travelTimeEntries) {
for (const entry of dedupeTravelTimeEntries(travelTimeEntries)) {
if (!entry.slug) continue;
let val = `${entry.mode}:${entry.slug}:${encodeURIComponent(entry.label)}`;
const serverMode = resolveTransitVariant(entry);
let val = `${serverMode}:${entry.slug}:${encodeURIComponent(entry.label)}`;
if (entry.useBest) val += ':b';
if (entry.timeRange) {
val += `:${entry.timeRange[0]}:${entry.timeRange[1]}`;