@mytec Phase 1 - Core UI & Manual Input, Phase 2 - RF Calculation Engine, Phase 3 - Heatmap Visualization

This commit is contained in:
2026-01-30 07:12:00 +02:00
parent 343c8e078d
commit 18a7d6de81
41 changed files with 6014 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
import { RSRP_LEGEND } from '@/constants/rsrp-thresholds.ts';
import { useCoverageStore } from '@/store/coverage.ts';
export default function Legend() {
const result = useCoverageStore((s) => s.result);
const heatmapVisible = useCoverageStore((s) => s.heatmapVisible);
const toggleHeatmap = useCoverageStore((s) => s.toggleHeatmap);
if (!result) return null;
return (
<div className="absolute bottom-6 right-2 z-[1000] bg-white rounded-lg shadow-lg border border-gray-200 p-3 min-w-[160px]">
{/* Header with toggle */}
<div className="flex items-center justify-between mb-2">
<h3 className="text-xs font-semibold text-gray-700">Signal (RSRP)</h3>
<button
onClick={toggleHeatmap}
className={`w-8 h-4 rounded-full transition-colors relative
${heatmapVisible ? 'bg-blue-500' : 'bg-gray-300'}`}
>
<span
className={`absolute top-0.5 w-3 h-3 rounded-full bg-white shadow transition-transform
${heatmapVisible ? 'left-4' : 'left-0.5'}`}
/>
</button>
</div>
{/* Legend items */}
<div className="space-y-1">
{RSRP_LEGEND.map((item) => (
<div key={item.label} className="flex items-center gap-2">
<div
className="w-3 h-3 rounded-sm flex-shrink-0"
style={{ backgroundColor: item.color }}
/>
<span className="text-[10px] text-gray-600">
{item.label}: {item.range}
</span>
</div>
))}
</div>
{/* Stats */}
<div className="mt-2 pt-2 border-t border-gray-100 text-[10px] text-gray-400 space-y-0.5">
<div>Points: {result.totalPoints.toLocaleString()}</div>
<div>
Time: {(result.calculationTime / 1000).toFixed(2)}s
</div>
</div>
</div>
);
}