fix(parcel-sync): quote all CSV fields + layer feature counts + drumul de azi

- CSV export: all fields properly quoted to prevent column misalignment
  when values contain commas (e.g. nrTopo with multiple topo numbers)
- Layer catalog: 'Numara toate' button fetches feature count per layer
  via /api/eterra/layers/summary (now supports session auth)
- Feature counts displayed as badges on each layer and category total
- 'Drumul de azi' section: persists today's layer counts in localStorage
  grouped by SIRUTA with timestamps
This commit is contained in:
AI Assistant
2026-03-06 23:19:58 +02:00
parent 0b049274b1
commit f73e639e4f
3 changed files with 233 additions and 26 deletions
+7 -8
View File
@@ -5,6 +5,7 @@ import {
} from "@/modules/parcel-sync/services/eterra-client";
import { LAYER_CATALOG } from "@/modules/parcel-sync/services/eterra-layers";
import { fetchUatGeometry } from "@/modules/parcel-sync/services/uat-geometry";
import { getSessionCredentials } from "@/modules/parcel-sync/services/session-store";
export const runtime = "nodejs";
export const dynamic = "force-dynamic";
@@ -18,19 +19,17 @@ type Body = {
/**
* POST — Count features per layer on the remote eTerra server.
* Supports session-based auth (falls back to env vars).
*/
export async function POST(req: Request) {
try {
const body = (await req.json()) as Body;
const username = (
body.username ??
process.env.ETERRA_USERNAME ??
""
const session = getSessionCredentials();
const username = String(
body.username || session?.username || process.env.ETERRA_USERNAME || "",
).trim();
const password = (
body.password ??
process.env.ETERRA_PASSWORD ??
""
const password = String(
body.password || session?.password || process.env.ETERRA_PASSWORD || "",
).trim();
const siruta = String(body.siruta ?? "").trim();
+5 -2
View File
@@ -131,7 +131,8 @@ function formatAddress(item?: any) {
if (houseNo) parts.push(`Nr. ${houseNo}`);
// Building details
if (address.buildingSectionNo) parts.push(`Bl. ${address.buildingSectionNo}`);
if (address.buildingSectionNo)
parts.push(`Bl. ${address.buildingSectionNo}`);
if (address.buildingEntryNo) parts.push(`Sc. ${address.buildingEntryNo}`);
if (address.buildingFloorNo) parts.push(`Et. ${address.buildingFloorNo}`);
if (address.buildingUnitNo) parts.push(`Ap. ${address.buildingUnitNo}`);
@@ -166,7 +167,9 @@ function formatAddress(item?: any) {
// If we still have nothing, try addressDescription from first entry
if (formatted.length === 0) {
const desc = addresses[0]?.address?.addressDescription ?? addresses[0]?.addressDescription;
const desc =
addresses[0]?.address?.addressDescription ??
addresses[0]?.addressDescription;
if (desc) {
const s = String(desc).trim();
if (s.length > 2 && !s.includes("[object")) return s;