Fehler behebung

This commit is contained in:
Timo Knuth
2025-12-03 11:51:00 +01:00
parent d2953fd0d9
commit 30ecc292cd
20 changed files with 379 additions and 62 deletions

View File

@@ -26,7 +26,7 @@ import { SharedModule } from '../../../shared/shared/shared.module';
import { createMailInfo, map2User } from '../../../utils/utils';
// Import für Leaflet
// Benannte Importe für Leaflet
import { circle, Circle, Control, DomEvent, DomUtil, latLng, LatLngBounds, polygon, Polygon, tileLayer } from 'leaflet';
import { circle, Circle, Control, DomEvent, DomUtil, icon, Icon, latLng, LatLngBounds, Marker, polygon, Polygon, tileLayer } from 'leaflet';
import dayjs from 'dayjs';
import { AuthService } from '../../../services/auth.service';
import { BaseDetailsComponent } from '../base-details.component';
@@ -328,12 +328,18 @@ export class DetailsBusinessListingComponent extends BaseDetailsComponent {
const county = this.listing.location.county || '';
const state = this.listing.location.state;
if (latitude && longitude && cityName && state) {
this.mapCenter = latLng(latitude, longitude);
this.mapZoom = 11; // Zoom out to show city area
// Check if we have valid coordinates (null-safe check)
if (latitude !== null && latitude !== undefined &&
longitude !== null && longitude !== undefined) {
// Fetch city boundary from Nominatim API
this.geoService.getCityBoundary(cityName, state).subscribe({
this.mapCenter = latLng(latitude, longitude);
// Case 1: City name available - show city boundary (current behavior)
if (cityName && state) {
this.mapZoom = 11; // Zoom to city level
// Fetch city boundary from Nominatim API
this.geoService.getCityBoundary(cityName, state).subscribe({
next: (data) => {
if (data && data.length > 0 && data[0].geojson && data[0].geojson.type === 'Polygon') {
const coordinates = data[0].geojson.coordinates[0]; // Get outer boundary
@@ -426,6 +432,18 @@ export class DetailsBusinessListingComponent extends BaseDetailsComponent {
this.useFallbackCircle(latitude, longitude, cityName, county, state);
}
});
}
// Case 2: Only state available (NEW) - show state-level circle
else if (state) {
this.mapZoom = 6; // Zoom to state level
// Use state-level fallback with larger radius
this.useStateLevelFallback(latitude, longitude, county, state);
}
// Case 3: No location name at all - minimal marker
else {
this.mapZoom = 8;
this.useMinimalMarker(latitude, longitude);
}
}
}
@@ -463,6 +481,184 @@ export class DetailsBusinessListingComponent extends BaseDetailsComponent {
};
}
/**
* Show state-level boundary polygon
* Used when only state is available without city
*/
private useStateLevelFallback(latitude: number, longitude: number, county: string, state: string) {
this.mapCenter = latLng(latitude, longitude);
// Fetch state boundary from Nominatim API (similar to city boundary)
this.geoService.getStateBoundary(state).subscribe({
next: (data) => {
if (data && data.length > 0 && data[0].geojson) {
// Handle Polygon
if (data[0].geojson.type === 'Polygon') {
const coordinates = data[0].geojson.coordinates[0];
const latlngs = coordinates.map((coord: number[]) => latLng(coord[1], coord[0]));
const statePolygon = polygon(latlngs, {
color: '#ef4444',
fillColor: '#ef4444',
fillOpacity: 0.05, // Very transparent for large area
weight: 2
});
statePolygon.bindPopup(`
<div style="padding: 8px;">
<strong>General Area:</strong><br/>
${county ? county + ', ' : ''}${state}<br/>
<small style="color: #666;">State boundary shown for privacy.<br/>Exact location provided after contact.</small>
</div>
`);
this.mapLayers = [
tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap contributors',
}),
statePolygon
];
// Fit map to state bounds
const bounds = statePolygon.getBounds();
this.mapOptions = {
...this.mapOptions,
center: bounds.getCenter(),
zoom: this.mapZoom,
};
}
// Handle MultiPolygon (states with islands, etc.)
else if (data[0].geojson.type === 'MultiPolygon') {
const allPolygons: Polygon[] = [];
data[0].geojson.coordinates.forEach((polygonCoords: number[][][]) => {
const latlngs = polygonCoords[0].map((coord: number[]) => latLng(coord[1], coord[0]));
const statePolygon = polygon(latlngs, {
color: '#ef4444',
fillColor: '#ef4444',
fillOpacity: 0.05,
weight: 2
});
allPolygons.push(statePolygon);
});
if (allPolygons.length > 0) {
allPolygons[0].bindPopup(`
<div style="padding: 8px;">
<strong>General Area:</strong><br/>
${county ? county + ', ' : ''}${state}<br/>
<small style="color: #666;">State boundary shown for privacy.<br/>Exact location provided after contact.</small>
</div>
`);
}
this.mapLayers = [
tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap contributors',
}),
...allPolygons
];
// Calculate combined bounds
if (allPolygons.length > 0) {
const bounds = new LatLngBounds([]);
allPolygons.forEach(p => bounds.extend(p.getBounds()));
this.mapOptions = {
...this.mapOptions,
center: bounds.getCenter(),
zoom: this.mapZoom,
};
}
} else {
// Fallback if unexpected format
this.useCircleFallbackForState(latitude, longitude, county, state);
}
} else {
// Fallback if no data
this.useCircleFallbackForState(latitude, longitude, county, state);
}
},
error: (err) => {
console.error('Error fetching state boundary:', err);
// Fallback to circle on error
this.useCircleFallbackForState(latitude, longitude, county, state);
}
});
}
/**
* Fallback: Show circle when state boundary cannot be fetched
*/
private useCircleFallbackForState(latitude: number, longitude: number, county: string, state: string) {
this.mapCenter = latLng(latitude, longitude);
const stateCircle = circle([latitude, longitude], {
color: '#ef4444',
fillColor: '#ef4444',
fillOpacity: 0.05,
weight: 2,
radius: 50000 // 50km
});
stateCircle.bindPopup(`
<div style="padding: 8px;">
<strong>General Area:</strong><br/>
${county ? county + ', ' : ''}${state}<br/>
<small style="color: #666;">Approximate state-level location shown for privacy.<br/>Exact location provided after contact.</small>
</div>
`);
this.mapLayers = [
tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap contributors',
}),
stateCircle
];
this.mapOptions = {
...this.mapOptions,
center: this.mapCenter,
zoom: this.mapZoom,
};
}
/**
* Show minimal marker when no location name is available
*/
private useMinimalMarker(latitude: number, longitude: number) {
this.mapCenter = latLng(latitude, longitude);
const marker = new Marker([latitude, longitude], {
icon: icon({
...Icon.Default.prototype.options,
iconUrl: 'assets/leaflet/marker-icon.png',
iconRetinaUrl: 'assets/leaflet/marker-icon-2x.png',
shadowUrl: 'assets/leaflet/marker-shadow.png',
}),
});
marker.bindPopup(`
<div style="padding: 8px;">
<strong>Location</strong><br/>
<small style="color: #666;">Contact seller for exact address</small>
</div>
`);
this.mapLayers = [
tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; OpenStreetMap contributors',
}),
marker
];
this.mapOptions = {
...this.mapOptions,
center: this.mapCenter,
zoom: this.mapZoom,
};
}
/**
* Override onMapReady to show privacy-friendly address control
*/