import SwiftUI struct BeaconEditSheet: View { var onSaved: () -> Void @State private var name = "" @State private var uuid = "" @State private var isSaving = false @State private var error: String? @EnvironmentObject var appState: AppState @Environment(\.dismiss) private var dismiss var body: some View { NavigationStack { Form { Section("New Beacon") { TextField("Name (e.g. Table 1 Beacon)", text: $name) TextField("UUID (32 hex characters)", text: $uuid) .textInputAutocapitalization(.characters) .autocorrectionDisabled() .font(.system(.body, design: .monospaced)) } Section { Text("The UUID should be a 32-character hexadecimal string that uniquely identifies this beacon. Example: 626C7565636861726D31000000000001") .font(.caption) .foregroundColor(.secondary) } if let error = error { Section { HStack { Image(systemName: "exclamationmark.circle.fill") .foregroundColor(.red) Text(error) .foregroundColor(.red) } } } } .navigationTitle("Add Beacon") .navigationBarTitleDisplayMode(.inline) .toolbar { ToolbarItem(placement: .cancellationAction) { Button("Cancel") { dismiss() } } ToolbarItem(placement: .confirmationAction) { Button("Save") { save() } .disabled(isSaving || name.isEmpty || uuid.isEmpty) } } } } private func save() { let trimmedName = name.trimmingCharacters(in: .whitespaces) let trimmedUUID = uuid.trimmingCharacters(in: .whitespaces) guard !trimmedName.isEmpty else { error = "Name is required" return } guard !trimmedUUID.isEmpty else { error = "UUID is required" return } isSaving = true error = nil Task { do { _ = try await APIService.shared.createBeacon(name: trimmedName, uuid: trimmedUUID) onSaved() dismiss() } catch let apiError as APIError where apiError == .unauthorized { await appState.handleUnauthorized() } catch { self.error = error.localizedDescription } isSaving = false } } }