feat: add Geoportal module with MapLibre GL JS + Martin vector tiles
Phase 1 of the geoportal implementation: Infrastructure: - Martin vector tile server in docker-compose (port 3010) - PostGIS setup SQL for GisUat: native geom column, Esri→PostGIS trigger, GiST index, gis_uats view for Martin auto-discovery Geoportal module (src/modules/geoportal/): - map-viewer.tsx: MapLibre GL JS canvas with OSM base, Martin MVT sources (gis_uats, gis_terenuri, gis_cladiri), click-to-inspect, zoom-level-aware layer visibility, layer styling - layer-panel.tsx: collapsible sidebar with layer toggles - geoportal-module.tsx: standalone page wrapper - Module registered in config/modules.ts, flags.ts, i18n ParcelSync integration: - 6th tab "Harta" with lazy-loaded MapViewer (ssr: false) - Centered on selected UAT Dependencies: maplibre-gl v5.21.0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -61,12 +61,29 @@ import {
|
||||
} from "../services/eterra-layers";
|
||||
import type { ParcelDetail } from "@/app/api/eterra/search/route";
|
||||
import type { OwnerSearchResult } from "@/app/api/eterra/search-owner/route";
|
||||
import { User, FileText, Archive } from "lucide-react";
|
||||
import { User, FileText, Archive, Map as MapIcon } from "lucide-react";
|
||||
import dynamic from "next/dynamic";
|
||||
import { UatDashboard } from "./uat-dashboard";
|
||||
import { EpayConnect, type EpaySessionStatus } from "./epay-connect";
|
||||
import { EpayOrderButton } from "./epay-order-button";
|
||||
import { EpayTab } from "./epay-tab";
|
||||
|
||||
/* MapLibre uses WebGL — must disable SSR */
|
||||
const MapViewer = dynamic(
|
||||
() =>
|
||||
import("@/modules/geoportal/components/map-viewer").then((m) => ({
|
||||
default: m.MapViewer,
|
||||
})),
|
||||
{
|
||||
ssr: false,
|
||||
loading: () => (
|
||||
<div className="flex items-center justify-center h-64 bg-muted/30 rounded-lg">
|
||||
<p className="text-sm text-muted-foreground">Se incarca harta...</p>
|
||||
</div>
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Types */
|
||||
/* ------------------------------------------------------------------ */
|
||||
@@ -2070,6 +2087,10 @@ export function ParcelSyncModule() {
|
||||
<FileText className="h-4 w-4" />
|
||||
Extrase CF
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="map" className="gap-1.5">
|
||||
<MapIcon className="h-4 w-4" />
|
||||
Harta
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
</div>
|
||||
|
||||
@@ -4765,6 +4786,15 @@ export function ParcelSyncModule() {
|
||||
<TabsContent value="extracts" className="space-y-4">
|
||||
<EpayTab />
|
||||
</TabsContent>
|
||||
|
||||
{/* ═══════════════════════════════════════════════════════ */}
|
||||
{/* Tab 6: Harta (MapLibre GL) */}
|
||||
{/* ═══════════════════════════════════════════════════════ */}
|
||||
<TabsContent value="map" className="space-y-4">
|
||||
<div className="relative h-[600px] rounded-lg border overflow-hidden">
|
||||
<MapViewer className="h-full w-full" />
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user