Replace the single global max travel time filter with per-POI filters. Each POI gets its own travel mode selector and max minutes input in the filter panel. Listings must satisfy ALL active filters (AND logic). Fix Mapbox "Input is not a number" error by ensuring color stops are always strictly monotonic (guard min === max) and always set (even when no valid metric values exist). Also filter Infinity values from the color scale computation. Widen the filter panel from w-64 to w-80.
41 lines
1.2 KiB
TypeScript
41 lines
1.2 KiB
TypeScript
import type { PropertyFeature, POIDistanceInfo } from '@/types';
|
|
|
|
/**
|
|
* Build the flat property name used by the hexgrid heatmap to read
|
|
* travel-time values directly from feature.properties.
|
|
*/
|
|
export function poiMetricPropertyName(poiId: number, travelMode: string): string {
|
|
return `poi_travel_${poiId}_${travelMode}`;
|
|
}
|
|
|
|
/**
|
|
* Shallow-copy every feature and inject a flat numeric property
|
|
* (e.g. `poi_travel_7_TRANSIT = 1800`) so the heatmap can color by it.
|
|
*
|
|
* Features without matching POI distance data get `undefined` for that property,
|
|
* which the heatmap will skip (same as a listing with no sqm value).
|
|
*/
|
|
export function injectPoiMetricProperty(
|
|
features: PropertyFeature[],
|
|
poiId: number,
|
|
travelMode: string,
|
|
): PropertyFeature[] {
|
|
const propName = poiMetricPropertyName(poiId, travelMode);
|
|
|
|
return features.map((feature) => {
|
|
const distances: POIDistanceInfo[] | undefined = feature.properties.poi_distances;
|
|
const match = distances?.find(
|
|
(d) => d.poi_id === poiId && d.travel_mode === travelMode,
|
|
);
|
|
|
|
if (match === undefined) return feature;
|
|
|
|
return {
|
|
...feature,
|
|
properties: {
|
|
...feature.properties,
|
|
[propName]: match.duration_seconds,
|
|
},
|
|
};
|
|
});
|
|
}
|