d48a2bbf5d
Split parcel-sync-module.tsx (4800 lines) into modular files: - Orchestrator (452 lines): shared state (session, UAT, sync) + tab routing - Types + helpers, ConnectionPill, 6 tab components (search, layers, export, database, cf, map) New ParcelSync Harta tab: - UAT-scoped map: zoom to extent, filter parcels/buildings by siruta - Data-driven styling via gis_terenuri_status enrichment overlay (green=no enrichment, dark green=enriched, blue outline=building, red=no legal docs) - Reuses Geoportal components (MapViewer, SelectionToolbar, FeatureInfoPanel, BasemapSwitcher) - Export DXF/GPKG for selection, legend New PostGIS views (gis_terenuri_status, gis_cladiri_status): - has_enrichment, has_building, build_legal columns from enrichment JSON - Auto-created via /api/geoportal/setup-enrichment-views - Does not modify existing Geoportal views New API: /api/geoportal/uat-bounds (WGS84 bbox from PostGIS geometry) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
53 lines
1.5 KiB
TypeScript
53 lines
1.5 KiB
TypeScript
/**
|
|
* GET /api/geoportal/uat-bounds?siruta=57582
|
|
*
|
|
* Returns WGS84 bounding box for a UAT from PostGIS geometry.
|
|
* Used by ParcelSync Harta tab to zoom to selected UAT.
|
|
*/
|
|
import { NextRequest, NextResponse } from "next/server";
|
|
import { prisma } from "@/core/storage/prisma";
|
|
|
|
export const runtime = "nodejs";
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export async function GET(req: NextRequest) {
|
|
const siruta = req.nextUrl.searchParams.get("siruta");
|
|
if (!siruta) {
|
|
return NextResponse.json({ error: "siruta required" }, { status: 400 });
|
|
}
|
|
|
|
try {
|
|
const rows = await prisma.$queryRaw`
|
|
SELECT
|
|
ST_XMin(ST_Transform(geom, 4326)) AS min_lng,
|
|
ST_YMin(ST_Transform(geom, 4326)) AS min_lat,
|
|
ST_XMax(ST_Transform(geom, 4326)) AS max_lng,
|
|
ST_YMax(ST_Transform(geom, 4326)) AS max_lat
|
|
FROM "GisUat"
|
|
WHERE siruta = ${siruta} AND geom IS NOT NULL
|
|
LIMIT 1
|
|
` as Array<{
|
|
min_lng: number;
|
|
min_lat: number;
|
|
max_lng: number;
|
|
max_lat: number;
|
|
}>;
|
|
|
|
const first = rows[0];
|
|
if (!first) {
|
|
return NextResponse.json({ error: "UAT not found or no geometry" }, { status: 404 });
|
|
}
|
|
|
|
return NextResponse.json({
|
|
siruta,
|
|
bounds: [
|
|
[first.min_lng, first.min_lat],
|
|
[first.max_lng, first.max_lat],
|
|
],
|
|
});
|
|
} catch (error) {
|
|
const msg = error instanceof Error ? error.message : "Eroare";
|
|
return NextResponse.json({ error: msg }, { status: 500 });
|
|
}
|
|
}
|