fix(parcel-sync): red parcel fill for buildings without legal docs

Instead of trying to color buildings directly (which requires an
unreliable cadastralRef join), the parcel itself gets a strong red fill
(opacity 0.45) when has_building=1 AND build_legal=0. Buildings sitting
on these parcels are visually on a red background.

Color scheme:
- Red fill: building without legal docs
- Light blue fill: building with legal
- Green fill: enriched, no building
- Yellow/amber fill: no enrichment

Removed broken gis_cladiri_status overlay. Simplified legend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
AI Assistant
2026-03-24 16:33:57 +02:00
parent 3f5eed25f4
commit ab35fc4df7
@@ -203,7 +203,7 @@ export function MapTab({ siruta, sirutaValid }: MapTabProps) {
maxzoom: 18,
});
// Data-driven fill: yellowish = no enrichment, dark green = enriched
// Data-driven fill: red = building no legal, green = enriched, yellow = no enrichment
map.addLayer(
{
id: "l-ps-terenuri-fill",
@@ -215,11 +215,33 @@ export function MapTab({ siruta, sirutaValid }: MapTabProps) {
paint: {
"fill-color": [
"case",
// Building without legal docs: RED fill (covers building too)
[
"all",
["==", ["get", "has_building"], 1],
["==", ["get", "build_legal"], 0],
],
"#ef4444",
// Building with legal: light blue
["==", ["get", "has_building"], 1],
"#93c5fd",
// Enriched, no building: green
["==", ["get", "has_enrichment"], 1],
"#22c55e", // green: enriched
"#fbbf24", // amber/yellow: no enrichment
"#22c55e",
// No enrichment: amber/yellow
"#fbbf24",
],
"fill-opacity": [
"case",
// Stronger opacity for building issues so it shows through
[
"all",
["==", ["get", "has_building"], 1],
["==", ["get", "build_legal"], 0],
],
0.45,
0.25,
],
"fill-opacity": 0.3,
},
},
"l-terenuri-fill", // below the transparent click-catcher
@@ -268,77 +290,7 @@ export function MapTab({ siruta, sirutaValid }: MapTabProps) {
}
}
// ── Enrichment overlay for BUILDINGS ──
if (!map.getSource("gis_cladiri_status")) {
map.addSource("gis_cladiri_status", {
type: "vector",
tiles: [`${martinBase}/gis_cladiri_status/{z}/{x}/{y}`],
minzoom: 12,
maxzoom: 18,
});
// Hide base cladiri layers
try {
if (map.getLayer("l-cladiri-fill"))
map.setPaintProperty("l-cladiri-fill", "fill-opacity", 0);
} catch {
/* noop */
}
// Buildings: red fill = no legal, blue fill = legal, gray = unknown
map.addLayer(
{
id: "l-ps-cladiri-fill",
type: "fill",
source: "gis_cladiri_status",
"source-layer": "gis_cladiri_status",
minzoom: 14,
filter,
paint: {
"fill-color": [
"case",
["==", ["get", "build_legal"], 0],
"#ef4444", // red: no legal
["==", ["get", "build_legal"], 1],
"#3b82f6", // blue: legal
"#6b7280", // gray: unknown (-1)
],
"fill-opacity": 0.5,
},
},
"l-cladiri-line",
);
map.addLayer(
{
id: "l-ps-cladiri-line",
type: "line",
source: "gis_cladiri_status",
"source-layer": "gis_cladiri_status",
minzoom: 14,
filter,
paint: {
"line-color": [
"case",
["==", ["get", "build_legal"], 0],
"#dc2626", // dark red
"#1e3a5f", // dark blue
],
"line-width": 0.8,
},
},
"l-cladiri-line",
);
} else {
try {
if (map.getLayer("l-ps-cladiri-fill"))
map.setFilter("l-ps-cladiri-fill", filter);
if (map.getLayer("l-ps-cladiri-line"))
map.setFilter("l-ps-cladiri-line", filter);
} catch {
/* noop */
}
}
// Buildings: keep base layer visible with siruta filter (already applied above)
}, [mapReady, siruta, sirutaValid]);
/* ── Boundary cross-check: load mismatched parcels ─────────── */
@@ -525,23 +477,22 @@ export function MapTab({ siruta, sirutaValid }: MapTabProps) {
{/* Bottom-right: legend */}
<div className="absolute bottom-3 right-3 z-10 rounded-lg bg-background/90 border p-2 text-[10px] space-y-1">
<div className="font-semibold text-[11px] mb-1">Parcele</div>
<div className="flex items-center gap-1.5">
<span
className="inline-block h-3 w-3 rounded-sm border"
className="inline-block h-3 w-3 rounded-sm"
style={{
backgroundColor: "rgba(251,191,36,0.3)",
borderColor: "#15803d",
backgroundColor: "rgba(251,191,36,0.25)",
border: "1px solid #15803d",
}}
/>
Fără enrichment
</div>
<div className="flex items-center gap-1.5">
<span
className="inline-block h-3 w-3 rounded-sm border"
className="inline-block h-3 w-3 rounded-sm"
style={{
backgroundColor: "rgba(34,197,94,0.3)",
borderColor: "#15803d",
backgroundColor: "rgba(34,197,94,0.25)",
border: "1px solid #15803d",
}}
/>
Cu enrichment
@@ -549,32 +500,23 @@ export function MapTab({ siruta, sirutaValid }: MapTabProps) {
<div className="flex items-center gap-1.5">
<span
className="inline-block h-3 w-3 rounded-sm"
style={{ border: "2px solid #3b82f6" }}
style={{
backgroundColor: "rgba(147,197,253,0.25)",
border: "2px solid #3b82f6",
}}
/>
Cu clădire (legal)
</div>
<div className="flex items-center gap-1.5">
<span
className="inline-block h-3 w-3 rounded-sm"
style={{ border: "2px solid #ef4444" }}
style={{
backgroundColor: "rgba(239,68,68,0.45)",
border: "2px solid #ef4444",
}}
/>
Clădire fără acte
</div>
<div className="font-semibold text-[11px] mt-1.5 mb-1">Clădiri</div>
<div className="flex items-center gap-1.5">
<span
className="inline-block h-3 w-3 rounded-sm"
style={{ backgroundColor: "rgba(59,130,246,0.5)" }}
/>
Legală
</div>
<div className="flex items-center gap-1.5">
<span
className="inline-block h-3 w-3 rounded-sm"
style={{ backgroundColor: "rgba(239,68,68,0.5)" }}
/>
Fără acte
</div>
{mismatchSummary && (mismatchSummary.foreign > 0 || mismatchSummary.edge > 0) && (
<>
<div className="font-semibold text-[11px] mt-1.5 mb-1">Limită UAT</div>