import SwiftUI import MapKit struct LeadLocationSection: View { let name: String let address: LeadAddress var locationService: any CustomerLocationService = AppleMapsCustomerLocationService() @State private var coordinate: CLLocationCoordinate2D? @State private var position: MapCameraPosition = .automatic @State private var errorMessage: LocalizedStringResource? @State private var retryID = 0 static let mapHeight: CGFloat = 328 private var addressText: String { [address.street, "\(address.postalCode) \(address.city)"] .compactMap { $0 } .joined(separator: ", ") } private var mapsURL: URL? { var components = URLComponents(string: "https://maps.apple.com/") components?.queryItems = [URLQueryItem(name: "q", value: addressText)] return components?.url } var body: some View { VStack(alignment: .leading, spacing: 8) { LeadSectionHeading(title: "STANDORT") ZStack { LeadDetailStyle.card if let coordinate { Map(position: $position) { Marker(name, coordinate: coordinate) .tint(LeadDetailStyle.blue) } .mapStyle(.standard(pointsOfInterest: .excludingAll)) .accessibilityLabel("Standort von \(name), \(addressText)") } else if let errorMessage { ContentUnavailableView { Label("Standort nicht verfügbar", systemImage: "mappin.slash") } description: { Text(errorMessage) } actions: { Button("Erneut versuchen") { retryID += 1 } } } else { ProgressView("Standort wird geladen") } } .safeAreaInset(edge: .bottom, spacing: 0) { if let mapsURL { Link(destination: mapsURL) { Label("In Apple Maps öffnen", systemImage: "map") .font(.subheadline.weight(.semibold)) .frame(maxWidth: .infinity, minHeight: 48) .foregroundStyle(.white) .background(LeadDetailStyle.blue) } .buttonStyle(.plain) } } .frame(maxWidth: .infinity) .frame(height: Self.mapHeight) .clipShape(.rect(cornerRadius: 12)) } .task(id: addressText + "#\(retryID)") { coordinate = nil errorMessage = nil do { let result = try await locationService.coordinate(for: addressText) try Task.checkCancellation() position = .region(MKCoordinateRegion( center: result, latitudinalMeters: 800, longitudinalMeters: 800 )) coordinate = result } catch is CancellationError { } catch { guard !Task.isCancelled else { return } if error is CustomerLocationError { errorMessage = "Für diese Anschrift wurde kein Standort gefunden." } else if let networkError = error as? URLError, [.notConnectedToInternet, .networkConnectionLost, .timedOut].contains(networkError.code) { errorMessage = "Keine Verbindung zu Apple Maps. Bitte prüfe deine Internetverbindung und versuche es erneut." } else { errorMessage = "Apple Maps konnte den Standort gerade nicht ermitteln. Bitte versuche es erneut." } } } } }