// // CreateViewModels.swift // Werkout_ios // // Created by Trey Tartt on 6/18/23. // import SwiftUI import SharedCore class CreateWorkoutExercise: ObservableObject, Identifiable { let id = UUID() var exercise: Exercise @Published var reps: Int = 0 @Published var duration: Int = 0 @Published var weight: Int = 0 init(exercise: Exercise, reps: Int = 0, duration: Int = 0, weight: Int = 0) { self.exercise = exercise self.reps = reps self.duration = duration self.weight = weight } func increaseReps() { self.reps += 1 } func decreaseReps() { self.reps -= 1 if self.reps < 0 { self.reps = 0 } } func increaseDuration() { self.duration += 15 self.reps = 0 } func decreaseDuration() { self.duration -= 15 if self.duration < 0 { self.duration = 0 } } func increaseWeight() { self.weight += 5 } func decreaseWeight() { self.weight -= 5 if self.weight < 0 { self.weight = 0 } } } class CreateWorkoutSuperSet: ObservableObject, Identifiable, Equatable { static func == (lhs: CreateWorkoutSuperSet, rhs: CreateWorkoutSuperSet) -> Bool { lhs.id == rhs.id } let id = UUID() @Published var title: String = "" @Published var exercises = [CreateWorkoutExercise]() @Published var numberOfRounds = 0 func increaseNumberOfRounds() { self.numberOfRounds += 1 } func decreaseNumberOfRounds() { self.numberOfRounds -= 1 if self.numberOfRounds < 0 { self.numberOfRounds = 0 } } func deleteExerciseForChosenSuperset(exercise: CreateWorkoutExercise) { if let idx = exercises.firstIndex(where: { $0.id == exercise.id }) { exercises.remove(at: idx) } } } class WorkoutViewModel: ObservableObject { @Published var superSets = [CreateWorkoutSuperSet]() @Published var title = String() @Published var description = String() @Published var validationError: String? @Published var isUploading = false @Published var randomValueForUpdatingValue = 0 func increaseRandomNumberForUpdating() { randomValueForUpdatingValue += 1 } func addNewSuperset() { increaseRandomNumberForUpdating() superSets.append(CreateWorkoutSuperSet()) } func delete(superset: CreateWorkoutSuperSet) { if let idx = superSets.firstIndex(where: { $0.id == superset.id }) { superSets.remove(at: idx) increaseRandomNumberForUpdating() } } func showRoundsError() { validationError = "Each superset must have at least one round." } func showNoDurationOrReps() { validationError = "Each exercise must have reps or duration." } func uploadWorkout() { guard isUploading == false else { return } validationError = nil let normalizedTitle = title.trimmingCharacters(in: .whitespacesAndNewlines) guard normalizedTitle.isEmpty == false else { validationError = "Workout title is required." return } var supersets = [[String: Any]]() for (supersetOffset, superset) in superSets.enumerated() { var supersetInfo = [String: Any]() supersetInfo["name"] = "" supersetInfo["rounds"] = superset.numberOfRounds supersetInfo["order"] = supersetOffset + 1 var exercises = [[String: Any]]() for (exerciseOffset, exercise) in superset.exercises.enumerated() { let item = ["id": exercise.exercise.id, "reps": exercise.reps, "weight": exercise.weight, "duration": exercise.duration, "order": exerciseOffset + 1] as [String : Any] exercises.append(item) } supersetInfo["exercises"] = exercises supersets.append(supersetInfo) } if supersets.isEmpty { validationError = "Add at least one superset before uploading." return } let issues = WorkoutValidation.validateSupersets(supersets) if let issue = issues.first { switch issue.code { case "invalid_rounds": showRoundsError() case "invalid_exercise_payload": showNoDurationOrReps() default: validationError = issue.message } return } let uploadBody = ["name": normalizedTitle, "description": description, "supersets": supersets] as [String : Any] isUploading = true CreateWorkoutFetchable(postData: uploadBody).fetch(completion: { result in self.isUploading = false switch result { case .success(_): self.superSets.removeAll() self.title = "" self.description = "" NotificationCenter.default.post( name: AppNotifications.createdNewWorkout, object: nil, userInfo: nil ) case .failure(let failure): self.validationError = "Failed to upload workout: \(failure.localizedDescription)" } }) } }