// // CompletedWorkoutView.swift // Werkout_ios // // Created by Trey Tartt on 6/22/23. // import SwiftUI struct CompletedWorkoutView: View { @ObservedObject var bridgeModule = BridgeModule.shared var postData: [String: Any] let workout: Workout @Environment(\.dismiss) var dismiss @State var difficulty: Float = 0 @State var notes: String = "" let completedWorkoutDismissed: ((Bool) -> Void)? var body: some View { VStack { topViews() Divider() HStack { calsBurned() .frame(maxWidth: .infinity) heartRates() .frame(maxWidth: .infinity) } rateWorkout() .frame(maxHeight: 88) Divider() TextField("Notes", text: $notes) .frame(height: 55) .textFieldStyle(PlainTextFieldStyle()) .padding([.horizontal], 4) .overlay(RoundedRectangle(cornerRadius: 16).stroke(Color(uiColor: .clear))).background(Color(uiColor: .init(red: 200/255, green: 200/255, blue: 200/255, alpha: 0.2))) .cornerRadius(8) Spacer() Button("Upload", action: { upload(postBody: postData) }) .frame(maxWidth: .infinity, alignment: .center) .frame(height: 44) .foregroundColor(.blue) .background(.yellow) .cornerRadius(8) .padding() .frame(maxWidth: .infinity) } .padding([.leading, .trailing]) } func topViews() -> some View { VStack { Text(workout.name) .frame(maxWidth: .infinity, alignment: .leading) .font(.title3) .padding(.top ) if let desc = workout.description { Text(desc) .frame(maxWidth: .infinity, alignment: .leading) .font(.body) .padding(.top) } } } func calsBurned() -> some View { VStack { if let cals = postData["total_calories"] as? Float { HStack { Image(systemName: "flame.fill") .foregroundColor(.orange) .font(.title) VStack { Text("\(cals, specifier: "%.0f")") } } } } } func rateWorkout() -> some View { VStack { Divider() HStack { Text("Easy") .foregroundColor(.green) Spacer() Text("Death") .foregroundColor(.red) } ZStack { LinearGradient( gradient: Gradient(colors: [.green, .red]), startPoint: .leading, endPoint: .trailing ) .mask(Slider(value: $difficulty, in: 0...5, step: 1)) // Dummy replicated slider, to allow sliding Slider(value: $difficulty, in: 0...5, step: 1) .opacity(0.05) // Opacity is the trick here. .accentColor(.clear) } } } func heartRates() -> some View { VStack { if let heartRates = postData["heart_rates"] as? [Int], heartRates.count > 0 { let avg = heartRates.reduce(0, +)/heartRates.count HStack { Image(systemName: "heart") .foregroundColor(.red) .font(.title) VStack { HStack { Text("\(heartRates.min() ?? 0)") Text("-") Text("\(heartRates.max() ?? 0)") } Text("\(avg)") } } } } } func upload(postBody: [String: Any]) { var _postBody = postBody _postBody["difficulty"] = difficulty _postBody["notes"] = notes CompleteWorkoutFetchable(postData: _postBody).fetch(completion: { result in switch result { case .success(_): DispatchQueue.main.async { bridgeModule.resetCurrentWorkout() dismiss() completedWorkoutDismissed?(true) } case .failure(let failure): print(failure) } }) } } struct CompletedWorkoutView_Previews: PreviewProvider { static let postBody = [ "difficulty": 1, "workout_start_time": Date().timeFormatForUpload, "workout": 1, "total_time": 140, "total_calories": Float(120.0), "heart_rates": [65,65,4,54,232,12] ] as [String : Any] static let workout = PreviewData.workout() static var previews: some View { CompletedWorkoutView(postData: CompletedWorkoutView_Previews.postBody, workout: workout, completedWorkoutDismissed: { _ in }) } }