diff --git a/Neuro App/HomeView.swift b/Neuro App/HomeView.swift index a9fffb4..8540768 100644 --- a/Neuro App/HomeView.swift +++ b/Neuro App/HomeView.swift @@ -81,7 +81,7 @@ struct HomeView: View { .cornerRadius(10) .shadow(radius: 2) - Text("Online Now:") + Text("Active Consultations:") .font(.headline) .padding(.top, 20) .foregroundColor(Color.black) @@ -225,6 +225,7 @@ struct OnlineUserCardView: View { .padding(.trailing, 15) } .frame(maxWidth: .infinity) + .frame(maxWidth: .infinity, minHeight: 60) .background( Color(UIColor { traitCollection in return traitCollection.userInterfaceStyle == .dark ? .black : .white diff --git a/Neuro App/NeuroDataModel.xcdatamodeld/NeuroDataModel.xcdatamodel/contents b/Neuro App/NeuroDataModel.xcdatamodeld/NeuroDataModel.xcdatamodel/contents index f426ce7..e937bd4 100644 --- a/Neuro App/NeuroDataModel.xcdatamodeld/NeuroDataModel.xcdatamodel/contents +++ b/Neuro App/NeuroDataModel.xcdatamodeld/NeuroDataModel.xcdatamodel/contents @@ -3,7 +3,9 @@ + + \ No newline at end of file diff --git a/Neuro App/Neuro_AppApp.swift b/Neuro App/Neuro_AppApp.swift index 03a9307..409213e 100755 --- a/Neuro App/Neuro_AppApp.swift +++ b/Neuro App/Neuro_AppApp.swift @@ -19,15 +19,15 @@ struct Neuro_App: App { var body: some Scene { WindowGroup { if authViewModel.isLoggedIn { - // ✅ User is logged in → go to HomeView + // User is logged in → go to HomeView HomeView() .environment(\.managedObjectContext, appDelegate.persistentContainer.viewContext) .environmentObject(appDelegate.signalingClient!) .environmentObject(authViewModel) .navigationBarBackButtonHidden(true) } else { - // ❌ Not logged in → show SignInView + // Not logged in → show SignInView SignInView() .environmentObject(authViewModel) } diff --git a/Neuro App/NewNIHFormView.swift b/Neuro App/NewNIHFormView.swift index 5c6ffaa..dd28e4f 100644 --- a/Neuro App/NewNIHFormView.swift +++ b/Neuro App/NewNIHFormView.swift @@ -1,16 +1,34 @@ import SwiftUI struct NewNIHFormView: View { + var remoteForm: RemoteStrokeForm? + var initialSelectedOptions: [Int] + + @Environment(\.presentationMode) var presentationMode @Environment(\.managedObjectContext) private var viewContext @StateObject private var viewModel = StrokeScaleFormViewModel() - @State private var patientName: String = "" - @Environment(\.presentationMode) var presentationMode - @State private var patientDOB: Date = Date() + @State private var patientName: String + @State private var patientDOB: Date + @State private var selectedOptions: [Int] @State private var showDOBPicker: Bool = false + + init(remoteForm: RemoteStrokeForm? = nil, initialSelectedOptions: [Int] = Array(repeating: -1, count: 15)) { + self.remoteForm = remoteForm + self.initialSelectedOptions = initialSelectedOptions + + _patientName = State(initialValue: remoteForm?.name ?? "") + _patientDOB = State(initialValue: StrokeScaleFormManager.convertDOB(from: remoteForm?.dob ?? "")) + _selectedOptions = State(initialValue: { + if let resultStr = remoteForm?.results { + return resultStr.map { Int(String($0)) ?? 9 } + } + return Array(repeating: -1, count: 15) + }()) + } var body: some View { VStack { - Text("New NIH Stroke Scale Form") + Text(remoteForm != nil ? "Update Form" : "New Form") .font(.title) .padding(.leading) .padding(.trailing) @@ -46,7 +64,11 @@ struct NewNIHFormView: View { }) { HStack { Text("DOB: \(formattedDate(patientDOB))") - .foregroundColor(.white) + .foregroundColor( + Color(UIColor { trait in + trait.userInterfaceStyle == .dark ? .white : .black + }) + ) .font(.headline) Spacer() Image(systemName: "calendar") @@ -92,7 +114,7 @@ struct NewNIHFormView: View { showDOBPicker = false } .font(.headline) - .foregroundColor(.white) + .foregroundColor(.black) .padding() .frame(maxWidth: .infinity) .background(Color.purple.opacity(0.2)) @@ -121,13 +143,13 @@ struct NewNIHFormView: View { HStack { Button(action: { saveForm() - presentationMode.wrappedValue.dismiss() // Dismiss after saving }) { Text("Save") .font(.headline) .foregroundColor(.white) .padding() .frame(maxWidth: .infinity) + .background(Color.green) .cornerRadius(10) } @@ -148,22 +170,37 @@ struct NewNIHFormView: View { .padding(.bottom) } .background(Color.purple.opacity(0.2)) + .onAppear { + for option in 0.. String { let formatter = DateFormatter() formatter.dateStyle = .medium return formatter.string(from: date) - } + } } diff --git a/Neuro App/SavedFormDetailView.swift b/Neuro App/SavedFormDetailView.swift index 3e55651..aa94bea 100644 --- a/Neuro App/SavedFormDetailView.swift +++ b/Neuro App/SavedFormDetailView.swift @@ -3,33 +3,24 @@ import UIKit import PDFKit struct SavedFormDetailView: View { - - var savedForm: NIHFormEntity + var remoteForm: RemoteStrokeForm + @ObservedObject var viewModel = StrokeScaleFormViewModel() @State var selectedOptions: [Int] - @Environment(\.dismiss) private var dismiss // Dismiss environment variable + @State private var isPresentingUpdateForm = false + @State private var showDeleteConfirmation = false + @Environment(\.dismiss) private var dismiss var totalScore: Int { - var score = 0 - for (index, selectedOption) in selectedOptions.enumerated() where selectedOption != -1 { - score += viewModel.questions[index].options[selectedOption].score + selectedOptions.enumerated().reduce(0) { acc, item in + let (index, selectedOption) = item + return selectedOption != -1 ? acc + viewModel.questions[index].options[selectedOption].score : acc } - return score } - - init(savedForm: NIHFormEntity) { - self.savedForm = savedForm - if let optionsData = savedForm.selectedOptions { - do { - let decodedOptions = try JSONDecoder().decode([Int].self, from: optionsData) - self._selectedOptions = State(initialValue: decodedOptions) - } catch { - self._selectedOptions = State(initialValue: Array(repeating: -1, count: 15)) - print("Failed to decode options") - } - } else { - self._selectedOptions = State(initialValue: Array(repeating: -1, count: 15)) - } + + init(remoteForm: RemoteStrokeForm, selectedOptions: [Int]) { + self.remoteForm = remoteForm + self._selectedOptions = State(initialValue: selectedOptions) } var body: some View { @@ -47,22 +38,18 @@ struct SavedFormDetailView: View { // Patient Info Section VStack { - Text("Patient Name: \(savedForm.patientName ?? "Unknown")") + Text("Patient Name: \(remoteForm.name)") .font(.headline) .padding(.bottom, 5) .multilineTextAlignment(.center) - - Text(savedForm.dob != nil - ? "Patient DOB: \(savedForm.dob!, style: .date)" - : "Patient DOB: Unknown") + + Text("Patient DOB: \(StrokeScaleFormManager.convertDOB(from: remoteForm.dob), style: .date)") .font(.subheadline) .padding(.bottom, 5) .foregroundColor(.gray) .multilineTextAlignment(.center) - Text(savedForm.date != nil - ? "Date: \(savedForm.date!, style: .date)" - : "Date: Unknown") + Text("Date: \(StrokeScaleFormManager.convertDOB(from: remoteForm.formDate), style: .date)") .font(.subheadline) .padding(.bottom, 5) .foregroundColor(.gray) @@ -75,7 +62,7 @@ struct SavedFormDetailView: View { Form { ForEach(viewModel.questions.indices, id: \.self) { index in let question = viewModel.questions[index] - let selectedOptionIndex = selectedOptions[index] + let selectedOptionIndex = viewModel.questions[index].selectedOption ?? -1 Section { VStack(alignment: .leading, spacing: 10) { @@ -127,9 +114,21 @@ struct SavedFormDetailView: View { .background(Color.white) .cornerRadius(10) }) + + Button(action: { + isPresentingUpdateForm = true + }) { + Text("Update") + .font(.headline) + .foregroundColor(.black) + .padding() + .frame(maxWidth: .infinity) + .background(Color.white) + .cornerRadius(10) + } Button(action: { - // Delete action + showDeleteConfirmation = true }, label: { Text("Delete") .font(.headline) @@ -144,140 +143,24 @@ struct SavedFormDetailView: View { .padding(.bottom) } .background(Color.purple.opacity(0.2)) - } - - private func deleteForm() { - guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else { - print("Failed to access AppDelegate") // Log if AppDelegate isn't accessible - return - } - - let managedContext = appDelegate.persistentContainer.viewContext - - // Proceed with deletion - managedContext.delete(savedForm) - - do { - try managedContext.save() - print("Form deleted successfully") - } catch { - print("Failed to delete the form: \(error.localizedDescription)") + .fullScreenCover(isPresented: $isPresentingUpdateForm) { + NewNIHFormView( + remoteForm: remoteForm, + initialSelectedOptions: selectedOptions + ) } - - // Optionally pop the view after deletion - if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, - let rootViewController = windowScene.windows.first?.rootViewController as? UINavigationController { - rootViewController.popViewController(animated: true) + .alert("Are you sure you want to delete this form?", isPresented: $showDeleteConfirmation) { + Button("Delete", role: .destructive) { + StrokeScaleFormManager.deleteForm(remoteForm: remoteForm) + dismiss() + } + Button("Cancel", role: .cancel) { } } - } - - private func exportFormAsPDF() { - let pdfRenderer = UIGraphicsPDFRenderer(bounds: CGRect(x: 0, y: 0, width: 595, height: 842)) // A4 size PDF - - let data = pdfRenderer.pdfData { context in - context.beginPage() - let font = UIFont.systemFont(ofSize: 16) - let headerFont = UIFont.boldSystemFont(ofSize: 18) - let purpleOutlineAttributes: [NSAttributedString.Key: Any] = [ - .font: font, - .foregroundColor: UIColor.black, - .paragraphStyle: NSMutableParagraphStyle() - ] - - var yPosition: CGFloat = 20 - let pageHeight: CGFloat = 842 - let margin: CGFloat = 20 - - // Title - let title = "NIH Stroke Scale Form" - title.draw(at: CGPoint(x: 20, y: yPosition), withAttributes: [NSAttributedString.Key.font: headerFont]) - yPosition += 40 - - // Patient Name - let patientNameText = "Patient Name: \(savedForm.patientName ?? "Unknown")" - patientNameText.draw(at: CGPoint(x: 20, y: yPosition), withAttributes: [NSAttributedString.Key.font: font]) - yPosition += 30 - - // Date - let dateFormatter = DateFormatter() - dateFormatter.dateStyle = .medium - let dateText = "Date: \(dateFormatter.string(from: savedForm.date ?? Date()))" - dateText.draw(at: CGPoint(x: 20, y: yPosition), withAttributes: [NSAttributedString.Key.font: font]) - yPosition += 30 - - // Total Score - let totalScoreText = "Total Score: \(totalScore)" - totalScoreText.draw(at: CGPoint(x: 20, y: yPosition), withAttributes: [NSAttributedString.Key.font: font]) - yPosition += 40 - - // Questions and Options - for (index, question) in viewModel.questions.enumerated() { - // Estimate the height of the question header and subheader (if present) - let questionHeaderHeight = (question.questionHeader as NSString).size(withAttributes: [.font: headerFont]).height - let subHeaderHeight = (question.subHeader?.size(withAttributes: [.font: font]) ?? CGSize.zero).height - let optionsHeight: CGFloat = question.options.reduce(0) { (result, option) in - let optionTitle = option.title as NSString - let boundingRect = optionTitle.boundingRect(with: CGSize(width: 450, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: [.font: font], context: nil) - return result + boundingRect.height + 20 - } - - // Check if the question will fit on the current page - let requiredHeight = questionHeaderHeight + subHeaderHeight + optionsHeight + 50 // Add some padding - if yPosition + requiredHeight > pageHeight - margin { - context.beginPage() - yPosition = 20 - } - - // Draw the Question Header - question.questionHeader.draw(at: CGPoint(x: 20, y: yPosition), withAttributes: [NSAttributedString.Key.font: headerFont]) - yPosition += 30 - - // Draw the Subheader - if let subHeader = question.subHeader { - subHeader.draw(at: CGPoint(x: 20, y: yPosition), withAttributes: [NSAttributedString.Key.font: font, NSAttributedString.Key.foregroundColor: UIColor.gray]) - yPosition += 25 - } - - // Draw the Options - for (optionIndex, option) in question.options.enumerated() { - let selectedOptionIndex = selectedOptions[index] - let optionTitle = option.title as NSString - let optionScoreText = option.score > 0 ? "+\(option.score)" : "\(option.score)" - - // Draw the text in multiline if necessary - let textRect = CGRect(x: 40, y: yPosition, width: 450, height: CGFloat.greatestFiniteMagnitude) - let textAttributes: [NSAttributedString.Key: Any] = [ - .font: font, - .foregroundColor: UIColor.black - ] - - let boundingRect = optionTitle.boundingRect(with: CGSize(width: 450, height: CGFloat.greatestFiniteMagnitude), options: .usesLineFragmentOrigin, attributes: textAttributes, context: nil) - optionTitle.draw(with: textRect, options: .usesLineFragmentOrigin, attributes: textAttributes, context: nil) - - // Draw the score aligned to the right - optionScoreText.draw(at: CGPoint(x: 500, y: yPosition), withAttributes: [NSAttributedString.Key.font: font]) - - // Add purple outline for selected options - if selectedOptionIndex == optionIndex { - let outlineRect = CGRect(x: 35, y: yPosition - 5, width: boundingRect.width + 10, height: boundingRect.height + 10) - let outlinePath = UIBezierPath(rect: outlineRect) - UIColor.purple.setStroke() - outlinePath.lineWidth = 2 - outlinePath.stroke() - } - - yPosition += boundingRect.height + 20 - } - yPosition += 20 + .onAppear { + for option in 0.. - @Binding var isNavigatingBack: Bool + @State private var selectedFormBundle: SelectedFormBundle? @State private var isShowingNewFormView = false - @State private var selectedForm: NIHFormEntity? @State private var isShowingDetailView = false - + @State private var selectedOptions: [Int] = [] + @State private var shouldReloadForms = false + @StateObject var formStore = RemoteFormStore() + + class RemoteFormStore: ObservableObject { + @Published var forms: [RemoteStrokeForm] = [] + } + + struct SelectedFormBundle: Identifiable { + let id = UUID() + let form: RemoteStrokeForm + let options: [Int] + } + var body: some View { ZStack { // Background gradient @@ -61,17 +68,17 @@ struct SavedFormsView: View { // List of Forms VStack(spacing: 15) { - ForEach(savedForms, id: \.self) { form in + ForEach(formStore.forms) { form in HStack { VStack(alignment: .leading, spacing: 5) { - Text(form.patientName ?? "Unnamed Patient") + Text(form.name) .font(.headline) .foregroundColor( Color(UIColor { traitCollection in return traitCollection.userInterfaceStyle == .dark ? .white : .black }) ) - Text(form.date ?? Date(), style: .date) + Text("Date: \(StrokeScaleFormManager.convertDOB(from: form.formDate), style: .date)") .font(.subheadline) .foregroundColor( Color(UIColor { traitCollection in @@ -83,9 +90,14 @@ struct SavedFormsView: View { Spacer() Button(action: { - selectedForm = form + let options = form.results.prefix(15).map { Int(String($0)) ?? 9 } + selectedFormBundle = SelectedFormBundle(form: form, options: Array(options)) isShowingDetailView = true - }) { + + print("🟣 Opening form with ID \(form.id), selectedOptions: \(selectedOptions)") + print("🧪 Setting selectedRemoteForm: \(String(describing: form))") + + }) { HStack { Text("View") } @@ -119,13 +131,18 @@ struct SavedFormsView: View { .fullScreenCover(isPresented: $isShowingNewFormView) { NewNIHFormView() } - .fullScreenCover(isPresented: $isShowingDetailView) { - if let form = selectedForm { - SavedFormDetailView(savedForm: form) - } + .fullScreenCover(item: $selectedFormBundle) { bundle in + SavedFormDetailView( + remoteForm: bundle.form, + selectedOptions: bundle.options + ) } .onAppear { - viewContext.refreshAllObjects() + StrokeScaleFormManager.fetchFormsFromServer { fetchedForms in + DispatchQueue.main.async { + formStore.forms = fetchedForms + } + } } } } diff --git a/Neuro App/StrokeScaleFormManager.swift b/Neuro App/StrokeScaleFormManager.swift index 24b9155..d40d8c3 100644 --- a/Neuro App/StrokeScaleFormManager.swift +++ b/Neuro App/StrokeScaleFormManager.swift @@ -10,33 +10,100 @@ import Foundation import CoreData import Security +extension Notification.Name { + static let formsDidUpdate = Notification.Name("formsDidUpdate") +} + +struct RemoteStrokeForm: Identifiable, Codable { + var id: Int + var name: String + var dob: String + var formDate: String + var results: String + var username: String + + enum CodingKeys: String, CodingKey { + case id, name, dob, results, username, formDate = "form_date" + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + id = try container.decode(Int.self, forKey: .id) + name = try container.decodeIfPresent(String.self, forKey: .name) ?? "" + dob = try container.decodeIfPresent(String.self, forKey: .dob) ?? "" + formDate = try container.decodeIfPresent(String.self, forKey: .formDate) ?? "" + results = try container.decodeIfPresent(String.self, forKey: .results) ?? "" + username = try container.decodeIfPresent(String.self, forKey: .username) ?? "" + } +} + struct StrokeScaleFormManager { + static var remoteForms: [RemoteStrokeForm] = [] + + static func fetchFormsFromServer(completion: @escaping ([RemoteStrokeForm]) -> Void) { + remoteForms.removeAll() + guard let username = UserDefaults.standard.string(forKey: "username") else { + print("No username found") + completion([]) + return + } + + guard let url = URL(string: "https://videochat-signaling-app.ue.r.appspot.com/key=peerjs/post") else { + print("Invalid URL") + completion([]) + return + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("getUsersForms", forHTTPHeaderField: "Action") + + let payload: [String: String] = ["username": username] + request.httpBody = try? JSONSerialization.data(withJSONObject: payload) + + if let cookies = HTTPCookieStorage.shared.cookies(for: url) { + let cookieHeader = HTTPCookie.requestHeaderFields(with: cookies) + request.allHTTPHeaderFields?.merge(cookieHeader, uniquingKeysWith: { _, new in new }) + } + + URLSession.shared.dataTask(with: request) { data, _, error in + guard let data = data, error == nil else { + print("Error fetching forms: \(error?.localizedDescription ?? "unknown")") + completion([]) + return + } + + do { + let decoded = try JSONDecoder().decode([RemoteStrokeForm].self, from: data) + DispatchQueue.main.async { + self.remoteForms = decoded + completion(decoded) + } + } catch { + print("Decoding error: \(error)") + completion([]) + } + }.resume() + } + + static func notifyFormsDidUpdate() { + NotificationCenter.default.post(name: .formsDidUpdate, object: nil) + } + + static func convertDOB(from string: String) -> Date { + let formatter = DateFormatter() + formatter.dateFormat = "MM/dd/yyyy" + return formatter.date(from: string) ?? Date() + } + static func saveForm( context: NSManagedObjectContext, patientName: String, - dob: Date = Date(timeIntervalSince1970: 0), + dob: Date, selectedOptions: [Int] ) { - let newForm = NIHFormEntity(context: context) - newForm.date = Date() - newForm.patientName = patientName - newForm.dob = dob - - do { - let encoded = try JSONEncoder().encode(selectedOptions) - newForm.selectedOptions = encoded - - DispatchQueue.main.async { - do { - try context.save() - print("Saved locally.") - } catch { - print("Failed to save locally: \(error)") - } - } - } catch { - print("Failed to encode options: \(error)") - } + let username = UserDefaults.standard.string(forKey: "username") ?? "" let formatter = DateFormatter() formatter.dateFormat = "MM/dd/yyyy" @@ -47,7 +114,7 @@ struct StrokeScaleFormManager { "patientName": patientName, "DOB": formatter.string(from: dob), "formDate": formatter.string(from: Date()), - "results": selectedOptions.map { String($0) }.joined(), + "results": selectedOptions.map { $0 == -1 ? "9" : String($0) }.joined(), "username": username ] @@ -57,15 +124,72 @@ struct StrokeScaleFormManager { request.httpMethod = "POST" request.setValue("application/json", forHTTPHeaderField: "Content-Type") request.setValue("submitStrokeScale", forHTTPHeaderField: "Action") + request.httpBody = try? JSONSerialization.data(withJSONObject: payload) - do { - request.httpBody = try JSONSerialization.data(withJSONObject: payload, options: []) - } catch { - print("JSON encode error: \(error)") + let session = URLSession(configuration: { + let config = URLSessionConfiguration.default + config.httpCookieStorage = HTTPCookieStorage.shared + config.httpShouldSetCookies = true + return config + }()) + + session.dataTask(with: request) { data, response, error in + if let error = error { + print("Server error: \(error.localizedDescription)") + return + } + + if let httpResponse = response as? HTTPURLResponse { + print("Server status: \(httpResponse.statusCode)") + } + + if let data = data, let str = String(data: data, encoding: .utf8) { + print("Response: \(str)") + } + }.resume() + } + + static func updateForm( + remoteForm: RemoteStrokeForm, + patientName: String, + dob: Date, + selectedOptions: [Int] + ) { + let username = remoteForm.username + let formID = remoteForm.id + + let formatter = DateFormatter() + formatter.dateFormat = "MM/dd/yyyy" + + let payload: [String: Any] = [ + "patientName": patientName, + "dob": formatter.string(from: dob), + "formDate": formatter.string(from: Date()), + "results": selectedOptions.map { $0 == -1 ? "9" : String($0) }.joined(), + "username": username, + "id": formID, + "action": "updateForm" + ] + + guard let url = URL(string: "https://videochat-signaling-app.ue.r.appspot.com/key=peerjs/post") else { + print("Invalid URL") return } - URLSession.shared.dataTask(with: request) { data, response, error in + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("updateForm", forHTTPHeaderField: "Action") + request.httpBody = try? JSONSerialization.data(withJSONObject: payload) + + let session = URLSession(configuration: { + let config = URLSessionConfiguration.default + config.httpCookieStorage = HTTPCookieStorage.shared + config.httpShouldSetCookies = true + return config + }()) + + session.dataTask(with: request) { data, response, error in if let error = error { print("Server error: \(error.localizedDescription)") return @@ -76,7 +200,46 @@ struct StrokeScaleFormManager { } if let data = data, let str = String(data: data, encoding: .utf8) { - print("Response: \(str)") + print("Update response: \(str)") + } + }.resume() + } + + static func deleteForm(remoteForm: RemoteStrokeForm) { + let payload: [String: Any] = [ + "id": remoteForm.id, + "username": remoteForm.username + ] + + guard let url = URL(string: "https://videochat-signaling-app.ue.r.appspot.com/key=peerjs/post") else { + print("Invalid URL") + return + } + + var request = URLRequest(url: url) + request.httpMethod = "POST" + request.setValue("application/json", forHTTPHeaderField: "Content-Type") + request.setValue("deleteForm", forHTTPHeaderField: "Action") + request.httpBody = try? JSONSerialization.data(withJSONObject: payload) + + if let cookies = HTTPCookieStorage.shared.cookies(for: url) { + let cookieHeader = HTTPCookie.requestHeaderFields(with: cookies) + request.allHTTPHeaderFields?.merge(cookieHeader) { _, new in new } + print("Cookie attached to delete request: \(cookieHeader)") + } + + URLSession.shared.dataTask(with: request) { data, response, error in + if let error = error { + print("Server error: \(error.localizedDescription)") + return + } + + if let httpResponse = response as? HTTPURLResponse { + print("Server status: \(httpResponse.statusCode)") + } + + if let data = data, let responseText = String(data: data, encoding: .utf8) { + print("Delete response: \(responseText)") } }.resume() }