import SwiftUI import CoreLocation struct AddWalkSheet: View { let coord: CLLocationCoordinate2D? let onSaved: () async -> Void @Environment(\.dismiss) private var dismiss @State private var titel = "" @State private var date = Calendar.current.date(byAdding: .day, value: 1, to: .now) ?? .now @State private var time = Calendar.current.date(bySettingHour: 17, minute: 0, second: 0, of: .now) ?? .now @State private var ortName = "" @State private var maxTeilnehmer = 10 @State private var beschreibung = "" @State private var isSaving = false @State private var errorMessage: String? var body: some View { NavigationStack { Form { Section("Titel") { TextField("z. B. Gassi-Runde am Schlosspark", text: $titel) } Section("Datum & Uhrzeit") { DatePicker("Datum", selection: $date, in: Date.now..., displayedComponents: .date) .environment(\.locale, Locale(identifier: "de_DE")) DatePicker("Uhrzeit", selection: $time, displayedComponents: .hourAndMinute) .environment(\.locale, Locale(identifier: "de_DE")) } Section("Treffpunkt") { TextField("Name (z. B. Hauptplatz)", text: $ortName) if let coord { Text(String(format: "%.5f, %.5f", coord.latitude, coord.longitude)) .font(.caption.monospacedDigit()) .foregroundStyle(.secondary) } else { Text("Standort wird noch geholt — bitte einen Moment warten.") .font(.caption) .foregroundStyle(.secondary) } } Section("Max. Teilnehmer") { Stepper("\(maxTeilnehmer)", value: $maxTeilnehmer, in: 2...100) } Section("Beschreibung (optional)") { TextField("Was ist geplant? Wie lange?", text: $beschreibung, axis: .vertical) .lineLimit(2...6) } if let errorMessage { Section { Text(errorMessage).font(.footnote).foregroundStyle(.red) } } } .navigationTitle("Neues Treffen") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Abbrechen") { dismiss() } .disabled(isSaving) } ToolbarItem(placement: .confirmationAction) { if isSaving { ProgressView() } else { Button("Sichern") { Task { await save() } } .disabled(!canSave) } } } } } private var canSave: Bool { coord != nil && !titel.trimmingCharacters(in: .whitespaces).isEmpty } private func save() async { guard let coord else { return } isSaving = true errorMessage = nil defer { isSaving = false } let dateFmt = DateFormatter(); dateFmt.dateFormat = "yyyy-MM-dd" let timeFmt = DateFormatter(); timeFmt.dateFormat = "HH:mm" let body = WalkCreateBody( titel: titel.trimmingCharacters(in: .whitespaces), datum: dateFmt.string(from: date), uhrzeit: timeFmt.string(from: time), lat: coord.latitude, lon: coord.longitude, ortName: ortName.trimmingCharacters(in: .whitespaces).isEmpty ? nil : ortName, maxTeilnehmer: maxTeilnehmer, beschreibung: beschreibung.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty ? nil : beschreibung ) do { let _: WalkMeeting = try await APIClient.shared.post("/api/walks", body: body) await onSaved() dismiss() } catch { errorMessage = error.localizedDescription } } }