diff --git a/src/hooks/usePek.ts b/src/hooks/usePek.ts index 6dc4297..8067e46 100644 --- a/src/hooks/usePek.ts +++ b/src/hooks/usePek.ts @@ -54,6 +54,27 @@ export interface ParcelSearchResponse { id: string; egrid?: string; number?: string; + perimeter?: { + closed: boolean; + punkte: Array<{ + koordinatensystem: string; + x: number; + y: number; + z: number | null; + }>; + }; + geometry_geojson?: { + type: string; + geometry: { + type: string; + coordinates: number[][][]; + }; + properties: { + id: string; + egrid?: string; + number?: string; + }; + }; }>; } @@ -285,92 +306,85 @@ export function usePek() { } // Adjacent parcels (if available) - // Fetch geometries for adjacent parcels + // Use geometries from the response (no need to fetch separately) if (data.adjacent_parcels && includeAdjacent && data.adjacent_parcels.length > 0) { - // Fetch geometries for each adjacent parcel - const adjacentPromises = data.adjacent_parcels.map(async (adjacent) => { - try { - // Search for the adjacent parcel by its ID or EGRID - const searchLocation = adjacent.egrid || adjacent.id || adjacent.number; - if (!searchLocation) { - if (import.meta.env.DEV) { - console.warn(`⚠️ Adjacent parcel ${adjacent.id} has no search location`); - } - return null; - } + const adjacentGeometries: ParcelGeometry[] = []; - if (import.meta.env.DEV) { - console.log(`🔍 Fetching geometry for adjacent parcel: ${searchLocation}`); - } - - const adjResponse = await api.get('/api/realestate/parcel/search', { - params: { - location: searchLocation, - include_adjacent: false // Don't fetch adjacent of adjacent - } + data.adjacent_parcels.forEach((adjacent) => { + if (import.meta.env.DEV) { + console.log(`🔍 Processing adjacent parcel ${adjacent.id}:`, { + hasGeometryGeoJson: !!adjacent.geometry_geojson, + hasPerimeter: !!adjacent.perimeter, + geometryGeoJson: adjacent.geometry_geojson, + perimeter: adjacent.perimeter }); + } - const adjData: ParcelSearchResponse = adjResponse.data; - let adjCoordinates: MapPoint[] = []; + let adjCoordinates: MapPoint[] = []; - // Extract coordinates from adjacent parcel - if (adjData.map_view?.geometry_geojson?.geometry?.coordinates) { - const coords = adjData.map_view.geometry_geojson.geometry.coordinates[0]; - if (Array.isArray(coords)) { - adjCoordinates = coords.map((coord: number[]) => ({ - x: coord[0], - y: coord[1] - })); - } - } else if (adjData.parcel.perimeter?.punkte) { - adjCoordinates = adjData.parcel.perimeter.punkte.map((p) => ({ - x: p.x, - y: p.y + // Extract coordinates from geometry_geojson if available + if (adjacent.geometry_geojson?.geometry?.coordinates) { + const coords = adjacent.geometry_geojson.geometry.coordinates[0]; + if (Array.isArray(coords) && coords.length > 0) { + adjCoordinates = coords.map((coord: number[]) => ({ + x: coord[0], + y: coord[1] })); + if (import.meta.env.DEV) { + console.log(`✅ Extracted ${adjCoordinates.length} coordinates from geometry_geojson for ${adjacent.id}`); + } } - + } + // Fallback to perimeter.punkte if available + else if (adjacent.perimeter?.punkte) { + adjCoordinates = adjacent.perimeter.punkte.map((p) => ({ + x: p.x, + y: p.y + })); if (import.meta.env.DEV) { - console.log(`✅ Fetched ${adjCoordinates.length} coordinates for adjacent parcel ${adjacent.id}`); + console.log(`✅ Extracted ${adjCoordinates.length} coordinates from perimeter for ${adjacent.id}`); } + } - return { + // Only add if we have valid coordinates + if (adjCoordinates.length >= 3) { + adjacentGeometries.push({ id: adjacent.id, egrid: adjacent.egrid, number: adjacent.number, coordinates: adjCoordinates, isSelected: false, isAdjacent: true - }; - } catch (err) { - // If fetching fails, log error but don't add parcel - if (import.meta.env.DEV) { - console.error(`❌ Failed to fetch geometry for adjacent parcel ${adjacent.id}:`, err); - } - return null; + }); + } else if (import.meta.env.DEV) { + console.warn(`⚠️ Adjacent parcel ${adjacent.id} has insufficient geometry data:`, { + coordCount: adjCoordinates.length, + hasGeometryGeoJson: !!adjacent.geometry_geojson, + hasPerimeter: !!adjacent.perimeter, + geometryGeoJsonStructure: adjacent.geometry_geojson ? { + hasGeometry: !!adjacent.geometry_geojson.geometry, + hasCoordinates: !!adjacent.geometry_geojson.geometry?.coordinates, + coordinatesLength: adjacent.geometry_geojson.geometry?.coordinates?.length, + firstCoordLength: adjacent.geometry_geojson.geometry?.coordinates?.[0]?.length + } : null + }); } }); - // Wait for all adjacent parcel geometries - const adjacentGeometries = await Promise.all(adjacentPromises); - const validAdjacentGeometries = adjacentGeometries.filter( - (g): g is ParcelGeometry => g !== null && g.coordinates.length >= 3 - ); - if (import.meta.env.DEV) { console.log(`📦 Adjacent parcels summary:`, { requested: data.adjacent_parcels.length, - fetched: adjacentGeometries.filter(g => g !== null).length, - valid: validAdjacentGeometries.length, - geometries: validAdjacentGeometries.map(g => ({ + valid: adjacentGeometries.length, + geometries: adjacentGeometries.map(g => ({ id: g.id, number: g.number, coordCount: g.coordinates.length })) }); } - + // Add adjacent parcels to geometries array - geometries.push(...validAdjacentGeometries); + geometries.push(...adjacentGeometries); } // Update parcel geometries with all parcels (main + adjacent) @@ -430,17 +444,43 @@ export function usePek() { ); /** - * Handle parcel click on map + * Handle parcel click on map - select the clicked parcel */ const handleParcelClick = useCallback(async (parcelId: string) => { - // Re-search for this specific parcel with adjacent parcels - if (selectedParcel) { - const locationString = selectedParcel.parcel.centroid - ? `${selectedParcel.parcel.centroid.x},${selectedParcel.parcel.centroid.y}` - : locationInput; - await searchParcel(locationString, true); + // Find the clicked parcel in the geometries + const clickedParcel = parcelGeometries.find(p => p.id === parcelId); + + if (clickedParcel && clickedParcel.coordinates.length > 0) { + // Use a point inside the parcel (first coordinate is always on the boundary, which is inside) + // For better accuracy, use a point slightly inside the boundary + const firstCoord = clickedParcel.coordinates[0]; + + // Calculate centroid as fallback, but prefer a point we know is inside + const sumX = clickedParcel.coordinates.reduce((sum, coord) => sum + coord.x, 0); + const sumY = clickedParcel.coordinates.reduce((sum, coord) => sum + coord.y, 0); + const centroidX = sumX / clickedParcel.coordinates.length; + const centroidY = sumY / clickedParcel.coordinates.length; + + // Use first coordinate (guaranteed to be on/in the parcel) for search + const locationString = `${firstCoord.x},${firstCoord.y}`; + await searchParcel(locationString, true); // Always include adjacent parcels + } else { + // Fallback: try to search by parcel ID/EGRID if available + if (selectedParcel?.adjacent_parcels) { + const adjacentParcel = selectedParcel.adjacent_parcels.find(p => p.id === parcelId); + if (adjacentParcel?.egrid) { + // Search by EGRID + await searchParcel(adjacentParcel.egrid, true); + } else if (adjacentParcel?.number) { + // Try searching by number (might need address context) + await searchParcel(adjacentParcel.number, true); + } else if (adjacentParcel?.id) { + // Last resort: try searching by ID + await searchParcel(adjacentParcel.id, true); + } + } } - }, [selectedParcel, locationInput, searchParcel]); + }, [parcelGeometries, selectedParcel, searchParcel]); /** * Process natural language command