payfrit-beacon-ios/PayfritBeacon/Views/BeaconDetailScreen.swift
2026-02-01 23:39:29 -08:00

116 lines
4 KiB
Swift

import SwiftUI
struct BeaconDetailScreen: View {
let beacon: Beacon
var onSaved: () -> Void
@State private var name: String = ""
@State private var uuid: String = ""
@State private var isActive: Bool = true
@State private var isSaving = false
@State private var isDeleting = false
@State private var error: String?
@State private var showDeleteConfirm = false
@EnvironmentObject var appState: AppState
@Environment(\.dismiss) private var dismiss
var body: some View {
Form {
Section("Beacon Info") {
TextField("Name", text: $name)
TextField("UUID (32 hex characters)", text: $uuid)
.textInputAutocapitalization(.characters)
.autocorrectionDisabled()
.font(.system(.body, design: .monospaced))
Toggle("Active", isOn: $isActive)
}
Section("Details") {
LabeledContent("ID", value: "\(beacon.id)")
LabeledContent("Business ID", value: "\(beacon.businessId)")
if let date = beacon.createdAt {
LabeledContent("Created", value: date.formatted(date: .abbreviated, time: .shortened))
}
if let date = beacon.updatedAt {
LabeledContent("Updated", value: date.formatted(date: .abbreviated, time: .shortened))
}
}
if let error = error {
Section {
HStack {
Image(systemName: "exclamationmark.circle.fill")
.foregroundColor(.red)
Text(error)
.foregroundColor(.red)
}
}
}
Section {
Button("Save Changes") { save() }
.frame(maxWidth: .infinity)
.disabled(isSaving || isDeleting || name.isEmpty || uuid.isEmpty)
}
Section {
Button(isDeleting ? "Deleting..." : "Delete Beacon", role: .destructive) {
showDeleteConfirm = true
}
.frame(maxWidth: .infinity)
.disabled(isSaving || isDeleting)
}
}
.navigationTitle(beacon.name)
.onAppear {
name = beacon.name
uuid = beacon.uuid
isActive = beacon.isActive
}
.alert("Delete Beacon?", isPresented: $showDeleteConfirm) {
Button("Delete", role: .destructive) { deleteBeacon() }
Button("Cancel", role: .cancel) {}
} message: {
Text("This will permanently remove \"\(beacon.name)\". Service points using this beacon will be unassigned.")
}
}
private func save() {
isSaving = true
error = nil
Task {
do {
try await APIService.shared.updateBeacon(
beaconId: beacon.id,
name: name.trimmingCharacters(in: .whitespaces),
uuid: uuid.trimmingCharacters(in: .whitespaces),
isActive: isActive
)
onSaved()
dismiss()
} catch let apiError as APIError where apiError == .unauthorized {
await appState.handleUnauthorized()
} catch {
self.error = error.localizedDescription
}
isSaving = false
}
}
private func deleteBeacon() {
isDeleting = true
error = nil
Task {
do {
try await APIService.shared.deleteBeacon(beaconId: beacon.id)
onSaved()
dismiss()
} catch let apiError as APIError where apiError == .unauthorized {
await appState.handleUnauthorized()
} catch {
self.error = error.localizedDescription
}
isDeleting = false
}
}
}