feat(geoportal): add search, basemap switcher, feature info panel, selection + export
Major geoportal enhancements: - Basemap switcher (OSM/Satellite/Terrain) with ESRI + OpenTopoMap tiles - Search bar with debounced lookup (UATs by name, parcels by cadastral ref, owners by name) - Feature info panel showing enrichment data from ParcelSync (cadastru, proprietari, suprafata, folosinta) - Parcel selection mode with amber highlight + export (GeoJSON/DXF/GPKG via ogr2ogr) - Next.js /tiles rewrite proxying to Martin (fixes dev + avoids mixed content) - Fixed MapLibre web worker relative URL resolution (window.location.origin) API routes: /api/geoportal/search, /api/geoportal/feature, /api/geoportal/export Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
"use client";
|
||||
|
||||
import { Map, Mountain, Satellite } from "lucide-react";
|
||||
import { Button } from "@/shared/components/ui/button";
|
||||
import { cn } from "@/shared/lib/utils";
|
||||
import type { BasemapId } from "../types";
|
||||
|
||||
const BASEMAPS: { id: BasemapId; label: string; icon: typeof Map }[] = [
|
||||
{ id: "osm", label: "Harta", icon: Map },
|
||||
{ id: "satellite", label: "Satelit", icon: Satellite },
|
||||
{ id: "topo", label: "Teren", icon: Mountain },
|
||||
];
|
||||
|
||||
type BasemapSwitcherProps = {
|
||||
value: BasemapId;
|
||||
onChange: (id: BasemapId) => void;
|
||||
};
|
||||
|
||||
export function BasemapSwitcher({ value, onChange }: BasemapSwitcherProps) {
|
||||
return (
|
||||
<div className="bg-background/95 backdrop-blur-sm border rounded-lg shadow-lg flex p-0.5 gap-0.5">
|
||||
{BASEMAPS.map((b) => {
|
||||
const Icon = b.icon;
|
||||
const active = value === b.id;
|
||||
return (
|
||||
<Button
|
||||
key={b.id}
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
className={cn(
|
||||
"px-2 py-1 h-7 text-xs gap-1 rounded-md",
|
||||
active && "bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground"
|
||||
)}
|
||||
onClick={() => onChange(b.id)}
|
||||
title={b.label}
|
||||
>
|
||||
<Icon className="h-3.5 w-3.5" />
|
||||
<span className="hidden sm:inline">{b.label}</span>
|
||||
</Button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user