diff --git a/Werkout_ios.xcodeproj/project.pbxproj b/Werkout_ios.xcodeproj/project.pbxproj index 7831781..5adab08 100644 --- a/Werkout_ios.xcodeproj/project.pbxproj +++ b/Werkout_ios.xcodeproj/project.pbxproj @@ -36,6 +36,9 @@ 1CF65A6E2A3F60480042FFBD /* CreateViewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A6D2A3F60480042FFBD /* CreateViewModels.swift */; }; 1CF65A732A3F60D20042FFBD /* CreateExerciseActionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A722A3F60D20042FFBD /* CreateExerciseActionsView.swift */; }; 1CF65A7B2A3F83440042FFBD /* CreateWorkoutSupersetActionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A7A2A3F83440042FFBD /* CreateWorkoutSupersetActionsView.swift */; }; + 1CF65A7D2A41275D0042FFBD /* Network.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A7C2A41275D0042FFBD /* Network.swift */; }; + 1CF65A7F2A4129320042FFBD /* Fetchables.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A7E2A4129320042FFBD /* Fetchables.swift */; }; + 1CF65A812A412AA30042FFBD /* DataStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A802A412AA30042FFBD /* DataStore.swift */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -71,6 +74,9 @@ 1CF65A6D2A3F60480042FFBD /* CreateViewModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateViewModels.swift; sourceTree = ""; }; 1CF65A722A3F60D20042FFBD /* CreateExerciseActionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateExerciseActionsView.swift; sourceTree = ""; }; 1CF65A7A2A3F83440042FFBD /* CreateWorkoutSupersetActionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateWorkoutSupersetActionsView.swift; sourceTree = ""; }; + 1CF65A7C2A41275D0042FFBD /* Network.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Network.swift; sourceTree = ""; }; + 1CF65A7E2A4129320042FFBD /* Fetchables.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fetchables.swift; sourceTree = ""; }; + 1CF65A802A412AA30042FFBD /* DataStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DataStore.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -115,6 +121,7 @@ 1CF65A302A3972850042FFBD /* Werkout_ios.entitlements */, 1CF65A292A3972840042FFBD /* Werkout_ios.xcdatamodeld */, 1CF65A312A3972850042FFBD /* Preview Content */, + 1CF65A802A412AA30042FFBD /* DataStore.swift */, ); path = Werkout_ios; sourceTree = ""; @@ -132,6 +139,8 @@ 1CF65A3D2A3973760042FFBD /* Network */ = { isa = PBXGroup; children = ( + 1CF65A7C2A41275D0042FFBD /* Network.swift */, + 1CF65A7E2A4129320042FFBD /* Fetchables.swift */, ); path = Network; sourceTree = ""; @@ -262,6 +271,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 1CF65A7F2A4129320042FFBD /* Fetchables.swift in Sources */, + 1CF65A812A412AA30042FFBD /* DataStore.swift in Sources */, 1CF65A6B2A3C1EAC0042FFBD /* CreateWorkoutMainView.swift in Sources */, 1CF65A7B2A3F83440042FFBD /* CreateWorkoutSupersetActionsView.swift in Sources */, 1CF65A262A3972840042FFBD /* Werkout_iosApp.swift in Sources */, @@ -278,6 +289,7 @@ 1CF65A592A3BF4B60042FFBD /* Muscle.swift in Sources */, 1CF65A2B2A3972840042FFBD /* Werkout_ios.xcdatamodeld in Sources */, 1CF65A2D2A3972840042FFBD /* MainView.swift in Sources */, + 1CF65A7D2A41275D0042FFBD /* Network.swift in Sources */, 1CF65A732A3F60D20042FFBD /* CreateExerciseActionsView.swift in Sources */, 1CF65A282A3972840042FFBD /* Persistence.swift in Sources */, 1CF65A5B2A3BF4BE0042FFBD /* Equipment.swift in Sources */, diff --git a/Werkout_ios/DataStore.swift b/Werkout_ios/DataStore.swift new file mode 100644 index 0000000..bc44040 --- /dev/null +++ b/Werkout_ios/DataStore.swift @@ -0,0 +1,79 @@ +// +// DataStore.swift +// Werkout_ios +// +// Created by Trey Tartt on 6/19/23. +// + +import Foundation + +class DataStore { + enum DataStoreStatus { + case loading + case idle + } + + static let shared = DataStore() + + public private(set) var allWorkouts: [Workout]? + public private(set) var allMuscles: [Muscle]? + public private(set) var allEquipment: [Equipment]? + public private(set) var allExercise: [ExerciseExercise]? + + public private(set) var status = DataStoreStatus.idle + + private let fetchAllDataQueue = DispatchGroup() + + public func fetchAllData() { + status = .loading + + fetchAllDataQueue.enter() + fetchAllDataQueue.enter() + fetchAllDataQueue.enter() + fetchAllDataQueue.enter() + + fetchAllDataQueue.notify(queue: .main) { + self.status = .idle + } + + AllWorkoutFetchable().fetch(completion: { result in + switch result { + case .success(let model): + self.allWorkouts = model + case .failure(let error): + print(error) + } + self.fetchAllDataQueue.leave() + }) + + AllMusclesFetchable().fetch(completion: { result in + switch result { + case .success(let model): + self.allMuscles = model + case .failure(let error): + print(error) + } + self.fetchAllDataQueue.leave() + }) + + AllEquipmentFetchable().fetch(completion: { result in + switch result { + case .success(let model): + self.allEquipment = model + case .failure(let error): + print(error) + } + self.fetchAllDataQueue.leave() + }) + + AllExerciseFetchable().fetch(completion: { result in + switch result { + case .success(let model): + self.allExercise = model + case .failure(let error): + print(error) + } + self.fetchAllDataQueue.leave() + }) + } +} diff --git a/Werkout_ios/Network/Fetchables.swift b/Werkout_ios/Network/Fetchables.swift new file mode 100644 index 0000000..0eb55de --- /dev/null +++ b/Werkout_ios/Network/Fetchables.swift @@ -0,0 +1,37 @@ +// +// AllWorkoutFetchable.swift +// Werkout_ios +// +// Created by Trey Tartt on 6/19/23. +// + +import Foundation + +class AllWorkoutFetchable: Fetchable { + typealias Response = [Workout] + var endPoint: String = "workout/all/" +} + +class WorkoutDetailFetchable: Fetchable { + typealias Response = Workout + var endPoint: String + + init(workoutID: String) { + self.endPoint = "/workout/"+workoutID+"/details/" + } +} + +class AllMusclesFetchable: Fetchable { + typealias Response = [Muscle] + var endPoint: String = "muscle/all/" +} + +class AllEquipmentFetchable: Fetchable { + typealias Response = [Equipment] + var endPoint: String = "equipment/all/" +} + +class AllExerciseFetchable: Fetchable { + typealias Response = [ExerciseExercise] + var endPoint: String = "exercise/all/" +} diff --git a/Werkout_ios/Network/Network.swift b/Werkout_ios/Network/Network.swift new file mode 100644 index 0000000..35c30db --- /dev/null +++ b/Werkout_ios/Network/Network.swift @@ -0,0 +1,57 @@ +// +// Network.swift +// Werkout_ios +// +// Created by Trey Tartt on 6/19/23. +// + +import Foundation + +enum FetchableError: Error { + case apiError(Error) + case noData + case decodeError(Error) + case endOfFileError +} + +protocol Fetchable { + associatedtype Response: Codable + + var baseURL: String { get } + var endPoint: String { get } + + func fetch(completion: @escaping (Result) -> Void) +} + +extension Fetchable { + var baseURL: String { + "http://127.0.0.1:8000/" + } + + func fetch(completion: @escaping (Result) -> Void) { + let url = URL(string: baseURL+endPoint)! + + let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in + if let error = error { + completion(.failure(.apiError(error))) + return + } + guard let data = data else { + completion(.failure(.noData)) + return + } + + do { + let model = try JSONDecoder().decode(Response.self, from: data) + completion(.success(model)) + return + } catch { + completion(.failure(.decodeError(error))) + return + } + completion(.failure(.endOfFileError)) + }) + + task.resume() + } +} diff --git a/Werkout_ios/Views/AddExerciseView.swift b/Werkout_ios/Views/AddExerciseView.swift index a905a19..d5c697d 100644 --- a/Werkout_ios/Views/AddExerciseView.swift +++ b/Werkout_ios/Views/AddExerciseView.swift @@ -10,10 +10,6 @@ import SwiftUI import Combine struct AddExerciseView: View { - @State var exercises: [ExerciseExercise]? - @State var equipment: [Equipment]? - @State var muscles: [Muscle]? - @State var selectedMuscles = [Muscle]() @State var selectedEquipment = [Equipment]() @State var filteredExercises = [ExerciseExercise]() @@ -27,7 +23,7 @@ struct AddExerciseView: View { var body: some View { VStack { - if let muscles = muscles { + if let muscles = DataStore.shared.allMuscles { Button("toggle all", action: { if self.selectedMuscles.count > 0 { self.selectedMuscles.removeAll() @@ -66,7 +62,7 @@ struct AddExerciseView: View { }.frame(height: 100) } - if let equipment = equipment { + if let equipment = DataStore.shared.allEquipment { Button("toggle all", action: { if self.selectedEquipment.count > 0 { self.selectedEquipment.removeAll() @@ -137,9 +133,14 @@ struct AddExerciseView: View { } } .onAppear{ - parseMuscle() - parseEquipment() - parseExercises() + guard let exercises = DataStore.shared.allExercise, + let muscles = DataStore.shared.allMuscles, + let equipment = DataStore.shared.allEquipment else { + return + } + selectedMuscles = muscles + selectedEquipment = equipment + filteredExercises = exercises } } @@ -154,9 +155,9 @@ struct AddExerciseView: View { return } - guard let exercises = exercises, - let muscles = muscles, - let equipment = equipment else { + guard let exercises = DataStore.shared.allExercise, + let muscles = DataStore.shared.allMuscles, + let equipment = DataStore.shared.allEquipment else { filteredExercises = [ExerciseExercise]() return } @@ -192,52 +193,52 @@ struct AddExerciseView: View { }) } - func parseExercises() { - if let filepath = Bundle.main.path(forResource: "Exercises", ofType: "json") { - do { - let data = try Data(NSData(contentsOfFile: filepath)) - let workout = try JSONDecoder().decode([ExerciseExercise].self, from: data) - self.filteredExercises.append(contentsOf: workout) - self.exercises = workout - } catch { - print(error) - fatalError() - } - } else { - fatalError() - } - } - - func parseEquipment() { - if let filepath = Bundle.main.path(forResource: "Equipment", ofType: "json") { - do { - let data = try Data(NSData(contentsOfFile: filepath)) - let workout = try JSONDecoder().decode([Equipment].self, from: data) - self.equipment = workout - self.selectedEquipment.append(contentsOf: workout) - } catch { - print(error) - fatalError() - } - } else { - fatalError() - } - } - - func parseMuscle() { - if let filepath = Bundle.main.path(forResource: "AllMuscles", ofType: "json") { - do { - let data = try Data(NSData(contentsOfFile: filepath)) - let workout = try JSONDecoder().decode([Muscle].self, from: data) - self.muscles = workout - self.selectedMuscles.append(contentsOf: workout) - } catch { - print(error) - fatalError() - } - } else { - fatalError() - } - } +// func parseExercises() { +// if let filepath = Bundle.main.path(forResource: "Exercises", ofType: "json") { +// do { +// let data = try Data(NSData(contentsOfFile: filepath)) +// let workout = try JSONDecoder().decode([ExerciseExercise].self, from: data) +// self.filteredExercises.append(contentsOf: workout) +// self.exercises = workout +// } catch { +// print(error) +// fatalError() +// } +// } else { +// fatalError() +// } +// } +// +// func parseEquipment() { +// if let filepath = Bundle.main.path(forResource: "Equipment", ofType: "json") { +// do { +// let data = try Data(NSData(contentsOfFile: filepath)) +// let workout = try JSONDecoder().decode([Equipment].self, from: data) +// self.equipment = workout +// self.selectedEquipment.append(contentsOf: workout) +// } catch { +// print(error) +// fatalError() +// } +// } else { +// fatalError() +// } +// } +// +// func parseMuscle() { +// if let filepath = Bundle.main.path(forResource: "AllMuscles", ofType: "json") { +// do { +// let data = try Data(NSData(contentsOfFile: filepath)) +// let workout = try JSONDecoder().decode([Muscle].self, from: data) +// self.muscles = workout +// self.selectedMuscles.append(contentsOf: workout) +// } catch { +// print(error) +// fatalError() +// } +// } else { +// fatalError() +// } +// } } diff --git a/Werkout_ios/Werkout_iosApp.swift b/Werkout_ios/Werkout_iosApp.swift index 6f01ac4..afe076b 100644 --- a/Werkout_ios/Werkout_iosApp.swift +++ b/Werkout_ios/Werkout_iosApp.swift @@ -56,6 +56,9 @@ struct Werkout_iosApp: App { Label("Accounts", systemImage: "person.fill.turn.down") } } + .onAppear{ + DataStore.shared.fetchAllData() + } } }