68355efbba
UAT click previously console.logged only. gis-api search response doesn't include bbox/centroid, so ArchiTools can't fitBounds locally. Reuse the deep-link pattern (already used by Export GeoPackage) → open eterra.live/harta?siruta=X in a new tab. eterra.live has its own /api/geoportal/uat-bounds + flyTo wired. Future: add GET /api/v1/uat/:siruta/bounds to gis-api so ArchiTools can fitBounds inline without leaving the page. Also reverts the session.debug diagnostic (Marius confirmed hasRefreshToken=true + expiresIn=293 after attaching offline_access scope mapping to Authentik provider pk=6 — root cause fixed, diagnostic no longer needed). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
89 lines
2.8 KiB
TypeScript
89 lines
2.8 KiB
TypeScript
"use client";
|
|
|
|
import { useRef, useState, useCallback } from "react";
|
|
import dynamic from "next/dynamic";
|
|
import { BasemapSwitcher, type BasemapId } from "./basemap-switcher";
|
|
import { SearchBar, type FeatureHit, type UatHit } from "./search-bar";
|
|
import {
|
|
FeatureInfoPanel,
|
|
type ClickedFeatureLite,
|
|
} from "./feature-info-panel";
|
|
import type { MapViewerHandle } from "./map-viewer";
|
|
|
|
const MapViewer = dynamic(
|
|
() => import("./map-viewer").then((m) => ({ default: m.MapViewer })),
|
|
{
|
|
ssr: false,
|
|
loading: () => (
|
|
<div className="flex h-full items-center justify-center bg-muted/30">
|
|
<p className="text-sm text-muted-foreground">Se încarcă harta…</p>
|
|
</div>
|
|
),
|
|
},
|
|
);
|
|
|
|
export function GeoportalV2() {
|
|
const mapRef = useRef<MapViewerHandle>(null);
|
|
const [basemap, setBasemap] = useState<BasemapId>("liberty");
|
|
const [clicked, setClicked] = useState<ClickedFeatureLite | null>(null);
|
|
|
|
const handleFeatureClick = useCallback((f: ClickedFeatureLite | null) => {
|
|
setClicked(f);
|
|
}, []);
|
|
|
|
const handleUatSelect = useCallback((uat: UatHit) => {
|
|
// gis-api search doesn't return UAT bounds today, so we can't flyTo
|
|
// server-side. Workaround: deep-link to eterra.live/harta which has
|
|
// bbox lookup (their /api/geoportal/uat-bounds + flyTo). Future:
|
|
// add GET /api/v1/uat/:siruta/bounds to gis-api and fitBounds here.
|
|
const url = `https://eterra.live/harta?siruta=${encodeURIComponent(uat.siruta)}`;
|
|
window.open(url, "_blank", "noopener,noreferrer");
|
|
}, []);
|
|
|
|
const handleFeatureSelect = useCallback((f: FeatureHit) => {
|
|
// Show panel directly (feature ID is known)
|
|
setClicked({
|
|
id: f.id,
|
|
siruta: "",
|
|
cadastralRef: f.cadastralRef,
|
|
layerId: f.layerId,
|
|
areaValue: f.areaValue,
|
|
});
|
|
}, []);
|
|
|
|
return (
|
|
<div className="absolute inset-0">
|
|
<MapViewer
|
|
ref={mapRef}
|
|
basemap={basemap}
|
|
onFeatureClick={handleFeatureClick}
|
|
className="h-full w-full"
|
|
/>
|
|
|
|
{/* Top-left: search */}
|
|
<div className="absolute left-3 top-3 z-10 flex flex-col gap-2">
|
|
<SearchBar
|
|
onUatSelect={handleUatSelect}
|
|
onFeatureSelect={handleFeatureSelect}
|
|
/>
|
|
</div>
|
|
|
|
{/* Top-right: basemap + panel */}
|
|
<div className="absolute right-14 top-3 z-10 flex flex-col items-end gap-2">
|
|
<BasemapSwitcher value={basemap} onChange={setBasemap} />
|
|
{clicked && (
|
|
<FeatureInfoPanel
|
|
feature={clicked}
|
|
onClose={() => setClicked(null)}
|
|
/>
|
|
)}
|
|
</div>
|
|
|
|
{/* Bottom-right: cutover badge (visible until full rollout) */}
|
|
<div className="pointer-events-none absolute bottom-2 right-2 z-10 rounded bg-primary/90 px-2 py-0.5 text-[10px] font-medium text-primary-foreground shadow">
|
|
gis.ac · v2
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|