84 lines
2.7 KiB
TypeScript
84 lines
2.7 KiB
TypeScript
"use client";
|
|
|
|
import type { OverlayMode } from "./location-score-panel";
|
|
|
|
interface MapLegendProps {
|
|
overlayMode: OverlayMode;
|
|
threshold: number;
|
|
hasPinData: boolean;
|
|
}
|
|
|
|
// Shared score ramp stops — matches makeColorExpr in map-view.tsx
|
|
const SCORE_STOPS: [number, string][] = [
|
|
[0, "#d73027"],
|
|
[0.25, "#fc8d59"],
|
|
[0.5, "#fee08b"],
|
|
[0.75, "#d9ef8b"],
|
|
[1, "#1a9850"],
|
|
];
|
|
|
|
function gradientCss(stops: [number, string][]): string {
|
|
return `linear-gradient(to right, ${stops.map(([p, c]) => `${c} ${p * 100}%`).join(", ")})`;
|
|
}
|
|
|
|
export function MapLegend({ overlayMode, threshold, hasPinData }: MapLegendProps) {
|
|
if (overlayMode === "isochrone" && hasPinData) {
|
|
// Travel-time legend: green (near) → red (far)
|
|
const stops: [number, string][] = [
|
|
[0, "#1a9850"],
|
|
[0.5, "#fee08b"],
|
|
[1, "#d73027"],
|
|
];
|
|
return (
|
|
<div className="absolute bottom-8 left-4 z-20 bg-white/90 backdrop-blur-sm rounded-lg shadow border border-gray-100 px-3 py-2 text-xs text-gray-600">
|
|
<div className="font-medium mb-1.5">Travel time</div>
|
|
<div className="flex items-center gap-2">
|
|
<span className="shrink-0">0 min</span>
|
|
<div
|
|
className="h-2.5 w-28 rounded-full"
|
|
style={{ background: gradientCss(stops) }}
|
|
/>
|
|
<span className="shrink-0">{threshold} min</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
if (overlayMode === "relative" && hasPinData) {
|
|
const stops: [number, string][] = [
|
|
[0, "#d73027"],
|
|
[0.25, "#fc8d59"],
|
|
[0.5, "#ffffbf"],
|
|
[0.75, "#91cf60"],
|
|
[1, "#1a9850"],
|
|
];
|
|
return (
|
|
<div className="absolute bottom-8 left-4 z-20 bg-white/90 backdrop-blur-sm rounded-lg shadow border border-gray-100 px-3 py-2 text-xs text-gray-600">
|
|
<div className="font-medium mb-1.5">vs. pin</div>
|
|
<div className="flex items-center gap-2">
|
|
<span className="shrink-0">Worse</span>
|
|
<div
|
|
className="h-2.5 w-28 rounded-full"
|
|
style={{ background: gradientCss(stops) }}
|
|
/>
|
|
<span className="shrink-0">Better</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
// Default: absolute accessibility score
|
|
return (
|
|
<div className="absolute bottom-8 left-4 z-20 bg-white/90 backdrop-blur-sm rounded-lg shadow border border-gray-100 px-3 py-2 text-xs text-gray-600">
|
|
<div className="font-medium mb-1.5">Accessibility</div>
|
|
<div className="flex items-center gap-2">
|
|
<span className="shrink-0">Low</span>
|
|
<div
|
|
className="h-2.5 w-28 rounded-full"
|
|
style={{ background: gradientCss(SCORE_STOPS) }}
|
|
/>
|
|
<span className="shrink-0">High</span>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|