diff --git a/src/app/api/eterra/search/route.ts b/src/app/api/eterra/search/route.ts index 5770c76..0fcebda 100644 --- a/src/app/api/eterra/search/route.ts +++ b/src/app/api/eterra/search/route.ts @@ -105,13 +105,26 @@ function formatAddress(item?: any) { // addressDescription may contain the full text address already if (address.addressDescription) { const desc = String(address.addressDescription).trim(); - // If it looks like a complete address (has comma or street), use it directly - if (desc.length > 3) return desc; + if (desc.length > 3 && !desc.includes("[object")) return desc; } - if (address.street) parts.push(`Str. ${address.street}`); + // 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}`); - if (address.locality?.name) parts.push(address.locality.name); - if (address.county?.name) parts.push(`Jud. ${address.county.name}`); + // locality can also be a string or object + const localityName = + typeof address.locality === "string" + ? address.locality + : address.locality?.name ?? ""; + if (localityName) parts.push(localityName); + const countyName = + typeof address.county === "string" + ? address.county + : address.county?.name ?? ""; + if (countyName) parts.push(`Jud. ${countyName}`); return parts.length ? parts.join(", ") : ""; } @@ -298,15 +311,23 @@ export async function POST(req: Request) { let suprafata: number | null = null; // Try multiple area fields - const areaStr = item?.area ?? item?.areaValue ?? item?.areaMP ?? item?.suprafata; + const areaStr = + item?.area ?? item?.areaValue ?? item?.areaMP ?? item?.suprafata; if (areaStr != null) { const parsed = Number(areaStr); if (Number.isFinite(parsed) && parsed > 0) suprafata = parsed; } // Log raw item keys once for debugging (first item only) if (results.length === 0) { - console.log("[search] immovable item keys:", Object.keys(item ?? {})); - console.log("[search] area fields:", { area: item?.area, areaValue: item?.areaValue, areaMP: item?.areaMP }); + console.log( + "[search] immovable item keys:", + Object.keys(item ?? {}), + ); + console.log("[search] area fields:", { + area: item?.area, + areaValue: item?.areaValue, + areaMP: item?.areaMP, + }); } // 2. Fetch documentation data (CF, proprietari) @@ -336,40 +357,74 @@ export async function POST(req: Request) { } // Extract owners from partTwoRegs — separate active vs cancelled + // using tree structure: "P" (person) nodes are children of + // inscription nodes. If a parent inscription has radiationDate, + // its person entries are former owners. const activeOwners: string[] = []; const cancelledOwners: string[] = []; // eslint-disable-next-line @typescript-eslint/no-explicit-any - const regs = docResponse?.partTwoRegs ?? []; - if (regs.length > 0) { - console.log("[search] partTwoRegs[0] keys:", Object.keys(regs[0])); - console.log("[search] partTwoRegs sample:", JSON.stringify(regs[0]).slice(0, 500)); + const regs: any[] = docResponse?.partTwoRegs ?? []; + if (regs.length > 0 && results.length === 0) { + console.log( + "[search] partTwoRegs count:", + regs.length, + "types:", + [...new Set(regs.map((r: any) => r?.nodeType))], + ); + // Log first 3 entries fully + regs.slice(0, 3).forEach((r: any, i: number) => + console.log(`[search] partTwoRegs[${i}]:`, JSON.stringify(r).slice(0, 600)), + ); + // Log last 3 entries + regs.slice(-3).forEach((r: any, i: number) => + console.log(`[search] partTwoRegs[${regs.length - 3 + i}]:`, JSON.stringify(r).slice(0, 600)), + ); } + + // Build nodeId → entry map for tree traversal // eslint-disable-next-line @typescript-eslint/no-explicit-any - regs.forEach((reg: any) => { - if ( - String(reg?.nodeType ?? "").toUpperCase() === "P" && - reg?.nodeName - ) { - const name = String(reg.nodeName).trim(); - if (!name) return; - // Check if this entry is cancelled/radiated - const isCancelled = - reg?.cancelled === true || - reg?.isActive === false || - reg?.radiat === true || - String(reg?.status ?? "").toUpperCase() === "RADIAT" || - String(reg?.status ?? "").toUpperCase() === "CANCELLED" || - reg?.radiationDate != null; - if (isCancelled) { - cancelledOwners.push(name); - } else { - activeOwners.push(name); - } + const nodeMap = new Map(); + for (const reg of regs) { + const nid = reg?.nodeId ?? reg?.id; + if (nid != null) nodeMap.set(nid, reg); + } + + // Check if an entry or any ancestor is radiated + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const isRadiated = (entry: any): boolean => { + // Direct checks on the entry itself + if (entry?.radiationDate != null) return true; + if (entry?.cancelled === true) return true; + if (entry?.isActive === false) return true; + if (entry?.closed === true) return true; + const st = String(entry?.status ?? "").toUpperCase(); + if (st === "RADIAT" || st === "CANCELLED" || st === "CLOSED") return true; + // Walk up to parent + const pid = entry?.parentNodeId ?? entry?.parentId; + if (pid != null) { + const parent = nodeMap.get(pid); + if (parent) return isRadiated(parent); } - }); + return false; + }; + + for (const reg of regs) { + if ( + String(reg?.nodeType ?? "").toUpperCase() !== "P" || + !reg?.nodeName + ) continue; + const name = String(reg.nodeName).trim(); + if (!name) continue; + if (isRadiated(reg)) { + cancelledOwners.push(name); + } else { + activeOwners.push(name); + } + } proprietariActuali = Array.from(new Set(activeOwners)); - proprietariVechi = Array.from(new Set(cancelledOwners)) - .filter((n) => !proprietariActuali.includes(n)); + proprietariVechi = Array.from(new Set(cancelledOwners)).filter( + (n) => !proprietariActuali.includes(n), + ); } catch { // Documentation fetch failed — continue with basic data } @@ -408,6 +463,16 @@ export async function POST(req: Request) { (fol ?? []).map((f: any) => f?.intravilan ?? ""), ); categorie = formatCategories(fol ?? []); + // Extract total area from folosinte as fallback + if (suprafata == null || suprafata <= 0) { + let totalArea = 0; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + for (const f of (fol ?? []) as any[]) { + const a = Number(f?.suprafata ?? 0); + if (Number.isFinite(a)) totalArea += a; + } + if (totalArea > 0) suprafata = totalArea; + } } catch { // folosinta fetch failed } diff --git a/src/modules/parcel-sync/components/parcel-sync-module.tsx b/src/modules/parcel-sync/components/parcel-sync-module.tsx index fe8a337..0138811 100644 --- a/src/modules/parcel-sync/components/parcel-sync-module.tsx +++ b/src/modules/parcel-sync/components/parcel-sync-module.tsx @@ -1034,7 +1034,9 @@ export function ParcelSyncModule() { p.proprietariVechi ? `Proprietari vechi: ${p.proprietariVechi}` : null, - !p.proprietariActuali && !p.proprietariVechi && p.proprietari + !p.proprietariActuali && + !p.proprietariVechi && + p.proprietari ? `Proprietari: ${p.proprietari}` : null, p.solicitant @@ -1142,14 +1144,16 @@ export function ParcelSyncModule() { )} - {!p.proprietariActuali && !p.proprietariVechi && p.proprietari && ( -
- - Proprietari - - {p.proprietari} -
- )} + {!p.proprietariActuali && + !p.proprietariVechi && + p.proprietari && ( +
+ + Proprietari + + {p.proprietari} +
+ )} )} {p.solicitant && (