From 742acb2d744e5f3f6c6685b71d095f7d3c7f37f6 Mon Sep 17 00:00:00 2001 From: AI Assistant Date: Fri, 6 Mar 2026 22:50:57 +0200 Subject: [PATCH] fix(search): proper address from all fields, parcel details endpoint, remove strikethrough - Address: use street.dictionaryItem.name (Strada/Alee/etc) + street.name, postalNo as house number, buildingEntryNo/FloorNo/UnitNo/SectionNo for apartment details, locality.name, county.name - Area+intravilan: fetch from /api/immovable/details/parcels/list (direct endpoint with area, intravilan, useCategory) before trying immApps - Owners: remove strikethrough, use smaller neutral font (text-[11px] text-muted-foreground/80), rename label to 'Proprietari anteriori' --- src/app/api/eterra/search/route.ts | 93 ++++++++++++++++--- .../components/parcel-sync-module.tsx | 4 +- 2 files changed, 84 insertions(+), 13 deletions(-) diff --git a/src/app/api/eterra/search/route.ts b/src/app/api/eterra/search/route.ts index 7cd2730..649d925 100644 --- a/src/app/api/eterra/search/route.ts +++ b/src/app/api/eterra/search/route.ts @@ -101,30 +101,55 @@ function persistWorkspace(siruta: string, workspacePk: number) { function formatAddress(item?: any) { const address = item?.immovableAddresses?.[0]?.address ?? null; if (!address) return ""; - const parts: string[] = []; - // addressDescription may contain the full text address already + + // If addressDescription is a clean string, use it if (address.addressDescription) { const desc = String(address.addressDescription).trim(); if (desc.length > 3 && !desc.includes("[object")) return desc; } - // street can be a string OR an object { name: "..." } - const streetName = - typeof address.street === "string" - ? address.street - : (address.street?.name ?? ""); - if (streetName) parts.push(`Str. ${streetName}`); - if (address.buildingNo) parts.push(`Nr. ${address.buildingNo}`); - // locality can also be a string or object + + const parts: string[] = []; + + // Street: dictionaryItem.name = type ("Strada"), name = actual name ("DIANEI") + const streetObj = address.street; + if (streetObj) { + const streetType = + typeof streetObj === "string" + ? "" + : (streetObj?.dictionaryItem?.name ?? ""); + const streetName = + typeof streetObj === "string" ? streetObj : (streetObj?.name ?? ""); + if (streetType && streetName) { + parts.push(`${streetType} ${streetName}`); + } else if (streetName) { + parts.push(`Str. ${streetName}`); + } + } + + // postalNo is often the house number in eTerra + const houseNo = address.postalNo ?? address.buildingNo ?? null; + if (houseNo) parts.push(`Nr. ${houseNo}`); + + // Building details (apartments, floors, etc.) + if (address.buildingEntryNo) parts.push(`Sc. ${address.buildingEntryNo}`); + if (address.buildingFloorNo) parts.push(`Et. ${address.buildingFloorNo}`); + if (address.buildingUnitNo) parts.push(`Ap. ${address.buildingUnitNo}`); + if (address.buildingSectionNo) parts.push(`Bl. ${address.buildingSectionNo}`); + + // Locality const localityName = typeof address.locality === "string" ? address.locality : (address.locality?.name ?? ""); if (localityName) parts.push(localityName); + + // County const countyName = typeof address.county === "string" ? address.county : (address.county?.name ?? ""); if (countyName) parts.push(`Jud. ${countyName}`); + return parts.length ? parts.join(", ") : ""; } @@ -417,7 +442,53 @@ export async function POST(req: Request) { } } - // 3. Fetch application data (solicitant, folosință, intravilan) + // 3. Fetch parcel details (area, intravilan, useCategory) — direct endpoint + if (immPk) { + try { + const parcels = await client.fetchImmovableParcelDetails( + workspaceId, + immPk, + 1, + 100, + ); + if (Array.isArray(parcels) && parcels.length > 0) { + // Sum area from all parcels + let totalArea = 0; + const intraVals: string[] = []; + const catMap = new Map(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + for (const p of parcels as any[]) { + const a = Number(p?.area ?? 0); + if (Number.isFinite(a) && a > 0) totalArea += a; + if (p?.intravilan) intraVals.push(String(p.intravilan)); + const cat = String(p?.useCategory ?? "").trim(); + if (cat) { + catMap.set( + cat, + (catMap.get(cat) ?? 0) + (Number.isFinite(a) ? a : 0), + ); + } + } + if (totalArea > 0 && (suprafata == null || suprafata <= 0)) { + suprafata = totalArea; + } + if (!intravilan && intraVals.length > 0) { + intravilan = normalizeIntravilan(intraVals); + } + if (!categorie && catMap.size > 0) { + categorie = Array.from(catMap.entries()) + .map( + ([k, a]) => `${k}:${a.toFixed(2).replace(/\.00$/, "")}`, + ) + .join("; "); + } + } + } catch { + // parcel details fetch failed + } + } + + // 4. Fetch application data (solicitant, fallback folosință) if (immPk) { try { const apps = await client.fetchImmAppsByImmovable( diff --git a/src/modules/parcel-sync/components/parcel-sync-module.tsx b/src/modules/parcel-sync/components/parcel-sync-module.tsx index 0138811..20d7225 100644 --- a/src/modules/parcel-sync/components/parcel-sync-module.tsx +++ b/src/modules/parcel-sync/components/parcel-sync-module.tsx @@ -1137,9 +1137,9 @@ export function ParcelSyncModule() { {p.proprietariVechi && (
- Proprietari vechi (radiați) + Proprietari anteriori - + {p.proprietariVechi}