diff --git a/LoopFollow/Remote/RemoteView.swift b/LoopFollow/Remote/RemoteView.swift index bc4f947c..abc1e58b 100644 --- a/LoopFollow/Remote/RemoteView.swift +++ b/LoopFollow/Remote/RemoteView.swift @@ -19,11 +19,12 @@ struct RemoteView: View { @State private var newHKTarget = HKQuantity(unit: .milligramsPerDeciliter, doubleValue: 0.0) @State private var duration = HKQuantity(unit: .minute(), doubleValue: 0.0) @State private var showConfirmation: Bool = false + @State private var showCancelConfirmation: Bool = false @State private var showCheckmark: Bool = false @State private var isLoading: Bool = false var onRefreshStatus: () -> Void - var onCancelExistingTarget: () -> Void + var onCancelExistingTarget: (@escaping (Bool) -> Void) -> Void var sendTempTarget: (HKQuantity, HKQuantity, @escaping (Bool) -> Void) -> Void var body: some View { @@ -46,16 +47,23 @@ struct RemoteView: View { if let tempTargetValue = tempTarget.value { Section(header: Text("Existing Temp Target")) { HStack { - Text("Current Target: \(Localizer.formatQuantity(tempTargetValue)) mg/dL") + Text("Current Target") Spacer() - Button(action: onCancelExistingTarget) { - Text("Cancel") - .foregroundColor(.red) - } + Text(Localizer.formatQuantity(tempTargetValue)) + Text(UserDefaultsRepository.getPreferredUnit().localizedShortUnitString).foregroundColor(.secondary) } + Button { showCancelConfirmation = true } + label: { + HStack { + Text("Cancel Temp Target") + Spacer() + Image(systemName: "xmark.app") + .font(.title) + } + } + .tint(.red) } } - Section(header: Text("Temporary Target")) { HStack { Text("Target") @@ -95,7 +103,6 @@ struct RemoteView: View { .navigationBarItems(trailing: Button(action: onRefreshStatus) { Image(systemName: "arrow.clockwise") }) - .padding() .disabled(isLoading) // Disable the form when loading if isLoading { @@ -104,7 +111,6 @@ struct RemoteView: View { } } } - .padding() .navigationTitle("Remote") .navigationBarTitleDisplayMode(.inline) .alert(isPresented: .constant(!statusMessage.value.isEmpty)) { @@ -116,6 +122,16 @@ struct RemoteView: View { }) ) } + .alert(isPresented: $showCancelConfirmation) { + Alert( + title: Text("Confirm Cancellation"), + message: Text("Are you sure you want to cancel the existing temp target?"), + primaryButton: .default(Text("Confirm"), action: { + cancelTempTarget() + }), + secondaryButton: .cancel() + ) + } } } @@ -135,6 +151,19 @@ struct RemoteView: View { } } } + + private func cancelTempTarget() { + isLoading = true + let zeroDuration = HKQuantity(unit: .minute(), doubleValue: 0.0) + onCancelExistingTarget() { success in + isLoading = false + if success { + statusMessage.value = "Temp target successfully cancelled." + } else { + statusMessage.value = "Failed to cancel temp target." + } + } + } } struct ErrorMessageView: View { diff --git a/LoopFollow/Remote/RemoteViewController.swift b/LoopFollow/Remote/RemoteViewController.swift index 422871eb..979fde2b 100644 --- a/LoopFollow/Remote/RemoteViewController.swift +++ b/LoopFollow/Remote/RemoteViewController.swift @@ -51,8 +51,31 @@ class RemoteViewController: UIViewController { // Refresh the status to check current temp targets and other relevant info } - private func cancelExistingTarget() { - // Cancel the existing temp target + private func cancelExistingTarget(completion: @escaping (Bool) -> Void) { + let tempTargetBody: [String: Any] = [ + "enteredBy": "LoopFollow", + "eventType": "Temporary Target", + "reason": "Manual", + "duration": 0, + "created_at": ISO8601DateFormatter().string(from: Date()) + ] + + NightscoutUtils.executePostRequest(eventType: .treatments, body: tempTargetBody) { (result: Result<[TreatmentCancelResponse], Error>) in + switch result { + case .success(let response): + print("Success: \(response)") + DispatchQueue.main.async { + self.statusMessage.set("Temp target successfully cancelled.") + completion(true) + } + case .failure(let error): + print("Error: \(error)") + DispatchQueue.main.async { + self.statusMessage.set("Failed to cancel temp target: \(error.localizedDescription)") + completion(false) + } + } + } } private func sendTempTarget(newTarget: HKQuantity, duration: HKQuantity, completion: @escaping (Bool) -> Void) { diff --git a/LoopFollow/Remote/TreatmentResponse.swift b/LoopFollow/Remote/TreatmentResponse.swift index dc4a737d..8e001ded 100644 --- a/LoopFollow/Remote/TreatmentResponse.swift +++ b/LoopFollow/Remote/TreatmentResponse.swift @@ -31,3 +31,23 @@ struct TreatmentResponse: Decodable { case id = "_id" } } + +struct TreatmentCancelResponse: Decodable { + let enteredBy: String + let eventType: String + let reason: String + let duration: Int + let createdAt: String + let utcOffset: Int + let id: String + + enum CodingKeys: String, CodingKey { + case enteredBy = "enteredBy" + case eventType = "eventType" + case reason = "reason" + case duration = "duration" + case createdAt = "created_at" + case utcOffset = "utcOffset" + case id = "_id" + } +} diff --git a/LoopFollow/helpers/NightscoutUtils.swift b/LoopFollow/helpers/NightscoutUtils.swift index 6d9d80e0..866dfb20 100644 --- a/LoopFollow/helpers/NightscoutUtils.swift +++ b/LoopFollow/helpers/NightscoutUtils.swift @@ -280,7 +280,14 @@ class NightscoutUtils { } return } - + // Print the JSON string for debugging + /* + if let jsonString = String(data: data, encoding: .utf8) { + print("JSON Response: \(jsonString)") + } else { + print("Failed to convert data to JSON string") + } + */ let decoder = JSONDecoder() do { let decodedObject = try decoder.decode(T.self, from: data)