diff --git a/Werkout_ios.xcodeproj/project.pbxproj b/Werkout_ios.xcodeproj/project.pbxproj index 42b8769..f293d92 100644 --- a/Werkout_ios.xcodeproj/project.pbxproj +++ b/Werkout_ios.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 1C485C832A489B9C00A6F896 /* CompletedWorkouts.json in Resources */ = {isa = PBXBuildFile; fileRef = 1C485C822A489B9C00A6F896 /* CompletedWorkouts.json */; }; 1CF65A262A3972840042FFBD /* Werkout_iosApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A252A3972840042FFBD /* Werkout_iosApp.swift */; }; 1CF65A282A3972840042FFBD /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A272A3972840042FFBD /* Persistence.swift */; }; 1CF65A2B2A3972840042FFBD /* Werkout_ios.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65A292A3972840042FFBD /* Werkout_ios.xcdatamodeld */; }; @@ -64,6 +65,8 @@ 1CF65AB32A452F360042FFBD /* WatchPackageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65AB22A452F360042FFBD /* WatchPackageModel.swift */; }; 1CF65AB42A4530200042FFBD /* WatchPackageModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65AB22A452F360042FFBD /* WatchPackageModel.swift */; }; 1CF65AB62A4532940042FFBD /* WatchMainViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65AB52A4532940042FFBD /* WatchMainViewModel.swift */; }; + 1CF65ABA2A4894430042FFBD /* UserStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CF65AB92A4894430042FFBD /* UserStore.swift */; }; + 1CF65ABC2A4897E20042FFBD /* RegisteredUser.json in Resources */ = {isa = PBXBuildFile; fileRef = 1CF65ABB2A4897E20042FFBD /* RegisteredUser.json */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -91,6 +94,7 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 1C485C822A489B9C00A6F896 /* CompletedWorkouts.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = CompletedWorkouts.json; sourceTree = ""; }; 1CF65A222A3972840042FFBD /* Werkout_ios.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Werkout_ios.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1CF65A252A3972840042FFBD /* Werkout_iosApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Werkout_iosApp.swift; sourceTree = ""; }; 1CF65A272A3972840042FFBD /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = ""; }; @@ -139,6 +143,8 @@ 1CF65AB52A4532940042FFBD /* WatchMainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchMainViewModel.swift; sourceTree = ""; }; 1CF65AB72A4534DC0042FFBD /* Werkout_watch Watch App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Werkout_watch Watch App.entitlements"; sourceTree = ""; }; 1CF65AB82A45387B0042FFBD /* Werkout-watch-Watch-App-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; path = "Werkout-watch-Watch-App-Info.plist"; sourceTree = SOURCE_ROOT; }; + 1CF65AB92A4894430042FFBD /* UserStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserStore.swift; sourceTree = ""; }; + 1CF65ABB2A4897E20042FFBD /* RegisteredUser.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = RegisteredUser.json; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -187,6 +193,8 @@ 1CF65A822A42347D0042FFBD /* Extensions.swift */, 1CF65A272A3972840042FFBD /* Persistence.swift */, 1CF65A4F2A3A1EA90042FFBD /* BridgeModule.swift */, + 1CF65A802A412AA30042FFBD /* DataStore.swift */, + 1CF65AB92A4894430042FFBD /* UserStore.swift */, 1CF65A3F2A3973840042FFBD /* Views */, 1CF65A8B2A44B7590042FFBD /* AccountView */, 1CF65A3E2A39737D0042FFBD /* APIModels */, @@ -195,7 +203,6 @@ 1CF65A302A3972850042FFBD /* Werkout_ios.entitlements */, 1CF65A292A3972840042FFBD /* Werkout_ios.xcdatamodeld */, 1CF65A312A3972850042FFBD /* Preview Content */, - 1CF65A802A412AA30042FFBD /* DataStore.swift */, 1CF65A862A4400E10042FFBD /* ToDo */, ); path = Werkout_ios; @@ -223,12 +230,12 @@ 1CF65A3E2A39737D0042FFBD /* APIModels */ = { isa = PBXGroup; children = ( - 1CF65A422A39FB410042FFBD /* Workout.swift */, - 1CF65A442A39FB550042FFBD /* Exercise.swift */, - 1CF65A462A39FB6C0042FFBD /* RegisteredUser.swift */, - 1CF65A582A3BF4B60042FFBD /* Muscle.swift */, - 1CF65A5A2A3BF4BE0042FFBD /* Equipment.swift */, 1CF65A842A43E8060042FFBD /* CompletedWorkout.swift */, + 1CF65A5A2A3BF4BE0042FFBD /* Equipment.swift */, + 1CF65A442A39FB550042FFBD /* Exercise.swift */, + 1CF65A582A3BF4B60042FFBD /* Muscle.swift */, + 1CF65A462A39FB6C0042FFBD /* RegisteredUser.swift */, + 1CF65A422A39FB410042FFBD /* Workout.swift */, ); path = APIModels; sourceTree = ""; @@ -255,6 +262,8 @@ 1CF65A562A3BF3830042FFBD /* AllMuscles.json */, 1CF65A5E2A3BF5A60042FFBD /* Equipment.json */, 1CF65A662A3BFF840042FFBD /* Exercises.json */, + 1CF65ABB2A4897E20042FFBD /* RegisteredUser.json */, + 1C485C822A489B9C00A6F896 /* CompletedWorkouts.json */, ); path = JSON; sourceTree = ""; @@ -415,9 +424,11 @@ buildActionMask = 2147483647; files = ( 1CF65A5F2A3BF5A60042FFBD /* Equipment.json in Resources */, + 1C485C832A489B9C00A6F896 /* CompletedWorkouts.json in Resources */, 1CF65A4A2A39FBB10042FFBD /* WorkoutOne.json in Resources */, 1CF65A652A3BF6BE0042FFBD /* AllWorkouts.json in Resources */, 1CF65A332A3972850042FFBD /* Preview Assets.xcassets in Resources */, + 1CF65ABC2A4897E20042FFBD /* RegisteredUser.json in Resources */, 1CF65A672A3BFF840042FFBD /* Exercises.json in Resources */, 1CF65A572A3BF3830042FFBD /* AllMuscles.json in Resources */, 1CF65A542A3A9AF30042FFBD /* Straight_Leg_Sit_Up.mp4 in Resources */, @@ -472,6 +483,7 @@ 1CF65A732A3F60D20042FFBD /* CreateExerciseActionsView.swift in Sources */, 1CF65A832A42347D0042FFBD /* Extensions.swift in Sources */, 1CF65A282A3972840042FFBD /* Persistence.swift in Sources */, + 1CF65ABA2A4894430042FFBD /* UserStore.swift in Sources */, 1CF65A5B2A3BF4BE0042FFBD /* Equipment.swift in Sources */, 1CF65A452A39FB550042FFBD /* Exercise.swift in Sources */, 1CF65A612A3BF6020042FFBD /* AddExerciseView.swift in Sources */, diff --git a/Werkout_ios/APIModels/CompletedWorkout.swift b/Werkout_ios/APIModels/CompletedWorkout.swift index a12c0c2..13a1223 100644 --- a/Werkout_ios/APIModels/CompletedWorkout.swift +++ b/Werkout_ios/APIModels/CompletedWorkout.swift @@ -9,18 +9,21 @@ import Foundation struct CompletedWorkout: Codable { let id: Int + let workout: Workout let createdAt, updatedAt: String - let difficulty, totalTime: Int + let difficulty, totalTime: Int? let workoutStartTime: String - let workout: Int + let notes: String? + let totalCalories: Int? enum CodingKeys: String, CodingKey { - case id + case id, workout case createdAt = "created_at" case updatedAt = "updated_at" case difficulty case totalTime = "total_time" case workoutStartTime = "workout_start_time" - case workout + case notes + case totalCalories = "total_calories" } } diff --git a/Werkout_ios/APIModels/RegisteredUser.swift b/Werkout_ios/APIModels/RegisteredUser.swift index 1d2bf11..5b93ae3 100644 --- a/Werkout_ios/APIModels/RegisteredUser.swift +++ b/Werkout_ios/APIModels/RegisteredUser.swift @@ -11,12 +11,15 @@ struct RegisteredUser: Codable { let id: Int let firstName, lastName, image: String? let nickName: String? + let token: String? + let email: String? enum CodingKeys: String, CodingKey { case id case firstName = "first_name" case lastName = "last_name" - case image + case image, token + case email = "email_address" case nickName = "nick_name" } } diff --git a/Werkout_ios/AccountView/AccountView.swift b/Werkout_ios/AccountView/AccountView.swift index b7431b9..8dd6861 100644 --- a/Werkout_ios/AccountView/AccountView.swift +++ b/Werkout_ios/AccountView/AccountView.swift @@ -9,7 +9,59 @@ import Foundation import SwiftUI struct AccountView: View { + @State var completedWorkouts: [CompletedWorkout]? + @ObservedObject var userStore = UserStore.shared + var body: some View { - Text("account view") + VStack { + if let registeredUser = userStore.registeredUser { + VStack(spacing: 10) { + if let nickName = registeredUser.nickName { + Text(nickName) + .font(.title) + } + + HStack { + Text(registeredUser.firstName ?? "-") + Text(registeredUser.lastName ?? "-") + } + + if let email = registeredUser.email { + Text(email) + } + } + } + + if let completedWorkouts = completedWorkouts { + Text("\(completedWorkouts.count)") + } + Spacer() + } + .onAppear{ +// fetchCompletedWorkouts() + } + } + + func fetchCompletedWorkouts() { + CompletedWorkoutFetchable().fetch(completion: { result in + switch result { + case .success(let model): + completedWorkouts = model + case .failure(let failure): + fatalError(failure.localizedDescription) + } + }) + } +} + +struct AccountView_Previews: PreviewProvider { + static let userStore = UserStore.shared + static let completedWorkouts = PreviewWorkout.parseCompletedWorkouts() + + static var previews: some View { + AccountView(completedWorkouts: completedWorkouts) + .onAppear{ + userStore.setFakeUser() + } } } diff --git a/Werkout_ios/JSON/CompletedWorkouts.json b/Werkout_ios/JSON/CompletedWorkouts.json new file mode 100644 index 0000000..b6830d3 --- /dev/null +++ b/Werkout_ios/JSON/CompletedWorkouts.json @@ -0,0 +1,26 @@ +[ + { + "id": 11, + "workout": { + "id": 21, + "registered_user": { + "id": 2, + "first_name": "test2_first", + "last_name": "test2_last", + "image": "", + "nick_name": null + }, + "created_at": "2023-06-20T21:03:00.124080Z", + "updated_at": "2023-06-20T21:03:00.125595Z", + "name": "Ipad", + "description": "description" + }, + "created_at": "2023-06-24T04:24:18.564094Z", + "updated_at": "2023-06-24T04:24:18.567762Z", + "difficulty": 1, + "total_time": 112, + "workout_start_time": "2015-10-22T19:50:08Z", + "notes": "free", + "total_calories": 123.0 + } +] diff --git a/Werkout_ios/JSON/RegisteredUser.json b/Werkout_ios/JSON/RegisteredUser.json new file mode 100644 index 0000000..a591b61 --- /dev/null +++ b/Werkout_ios/JSON/RegisteredUser.json @@ -0,0 +1,11 @@ +{ + "id": 1, + "email_address": "user1@user1.com", + "created_at": "2023-06-11T22:09:52.419314Z", + "updated_at": "2023-06-11T22:09:52.419342Z", + "first_name": "test1_fist", + "last_name": "test1_last", + "image": "", + "nick_name": "NickkkkName", + "token": "8f10a5b8c7532f7f8602193767b46a2625a85c52" +} diff --git a/Werkout_ios/JSON/WorkoutOne.json b/Werkout_ios/JSON/WorkoutOne.json index 973304d..90b34bf 100644 --- a/Werkout_ios/JSON/WorkoutOne.json +++ b/Werkout_ios/JSON/WorkoutOne.json @@ -1,735 +1,181 @@ { - "name": "Sample Workou 1", - "description": "thot workout", + "id": 20, + "name": "Adsfadfafa", + "description": "description", "exercises": [ { - "workout": 4, + "workout": 20, "exercise": { - "id": 790, + "id": 992, "muscles": [ { - "id": 9368, - "created_at": "2023-06-14T17:05:42.321949Z", - "updated_at": "2023-06-14T17:05:42.322466Z", - "exercise": 790, - "muscle": 3 - }, - { - "id": 9369, - "created_at": "2023-06-14T17:05:42.323207Z", - "updated_at": "2023-06-14T17:05:42.323633Z", - "exercise": 790, - "muscle": 2 - } - ], - "equipment": [ - { - "id": 1856, - "created_at": "2023-06-13T02:28:05.326753Z", - "updated_at": "2023-06-13T02:28:05.327125Z", - "exercise": 790, - "equipment": 1089 - } - ], - "audio_url": "/media/exercise_audio/Sprinter_Crunch.m4a", - "video_url": "/media/exercise_videos/Sprinter_Crunch.mp4", - "created_at": "2023-06-11T22:50:19.125036Z", - "updated_at": "2023-06-11T22:50:19.125042Z", - "name": "Sprinter Crunch", - "description": "With arms overhead and feet on the floor, crunch up off the floor and bring your elbow and opposite knee together. Unfold and switch sides", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": true, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": true, - "joints_used": "hip,shoulder,knee,lumbar spine,thoracic spine,elbow", - "movement_patterns": "core,core - rotational", - "equipment_required": "Yoga Mat", - "muscle_groups": "obliques,core", - "synonyms": "" - }, - "weight": null, - "reps": null, - "duration": 35, - "duration_audio": "/media/quantities_audio/for_35_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-12T02:11:42.925404Z" - }, - { - "workout": 4, - "exercise": { - "id": 798, - "muscles": [], - "equipment": [], - "audio_url": "/media/exercise_audio/Recover.m4a", - "video_url": "/media/exercise_videos/Recover.mp4", - "created_at": "2023-06-11T22:50:19.127914Z", - "updated_at": "2023-06-11T22:50:19.127921Z", - "name": "Recover", - "description": "Use this time to catch your breath. It will help you get more out of what's next", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": false, - "joints_used": "", - "movement_patterns": "", - "equipment_required": "", - "muscle_groups": "", - "synonyms": null - }, - "weight": null, - "reps": null, - "duration": 15, - "duration_audio": "/media/quantities_audio/for_15_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-12T02:11:42.929292Z" - }, - { - "workout": 4, - "exercise": { - "id": 603, - "muscles": [ - { - "id": 8193, - "created_at": "2023-06-14T17:05:40.908270Z", - "updated_at": "2023-06-14T17:05:40.908685Z", - "exercise": 603, - "muscle": 2 - } - ], - "equipment": [ - { - "id": 1362, - "created_at": "2023-06-13T02:28:04.775223Z", - "updated_at": "2023-06-13T02:28:04.775809Z", - "exercise": 603, - "equipment": 1089 - } - ], - "audio_url": "/media/exercise_audio/High_Plank.m4a", - "video_url": "/media/exercise_videos/High_Plank.mp4", - "created_at": "2023-06-11T22:50:19.053321Z", - "updated_at": "2023-06-11T22:50:19.053328Z", - "name": "High Plank", - "description": "Start with your hands directly under your shoulders while staying on the balls of your feet", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": true, - "is_distance": false, - "is_duration": true, - "is_reps": false, - "joints_used": "shoulder,wrist,elbow,ankle", - "movement_patterns": "core,core - anti-extension", - "equipment_required": "Yoga Mat", - "muscle_groups": "core", - "synonyms": "Front Lean Rest" - }, - "weight": null, - "reps": null, - "duration": 35, - "duration_audio": "/media/quantities_audio/for_35_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.946651Z" - }, - { - "workout": 4, - "exercise": { - "id": 798, - "muscles": [], - "equipment": [], - "audio_url": "/media/exercise_audio/Recover.m4a", - "video_url": "/media/exercise_videos/Recover.mp4", - "created_at": "2023-06-11T22:50:19.127914Z", - "updated_at": "2023-06-11T22:50:19.127921Z", - "name": "Recover", - "description": "Use this time to catch your breath. It will help you get more out of what's next", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": false, - "joints_used": "", - "movement_patterns": "", - "equipment_required": "", - "muscle_groups": "", - "synonyms": null - }, - "weight": null, - "reps": null, - "duration": 15, - "duration_audio": "/media/quantities_audio/for_15_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.946937Z" - }, - { - "workout": 4, - "exercise": { - "id": 142, - "muscles": [ - { - "id": 9137, - "created_at": "2023-06-14T17:05:42.053373Z", - "updated_at": "2023-06-14T17:05:42.053816Z", - "exercise": 142, - "muscle": 3 - }, - { - "id": 9138, - "created_at": "2023-06-14T17:05:42.054554Z", - "updated_at": "2023-06-14T17:05:42.055041Z", - "exercise": 142, - "muscle": 2 - }, - { - "id": 9139, - "created_at": "2023-06-14T17:05:42.055750Z", - "updated_at": "2023-06-14T17:05:42.056176Z", - "exercise": 142, - "muscle": 29 - } - ], - "equipment": [ - { - "id": 1760, - "created_at": "2023-06-13T02:28:05.211760Z", - "updated_at": "2023-06-13T02:28:05.212193Z", - "exercise": 142, - "equipment": 1091 - } - ], - "audio_url": "/media/exercise_audio/Single-Arm_Dumbbell_Suitcase_Carry.m4a", - "video_url": "/media/exercise_videos/Single-Arm_Dumbbell_Suitcase_Carry.mp4", - "created_at": "2023-06-11T22:50:18.866721Z", - "updated_at": "2023-06-11T22:50:18.866728Z", - "name": "Single-Arm Dumbbell Suitcase Carry", - "description": "Hold the dumbbell in your left hand.. Stay tall and keep your core tight,, as you walk forward.. Be careful not to lean to the side as you walk..", - "side": "left_arm", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": true, - "is_distance": true, - "is_duration": true, - "is_reps": false, - "joints_used": "ankle,lumbar spine,elbow,hip,knee,wrist", - "movement_patterns": "core,core - anti-lateral flexion,core - carry", - "equipment_required": "Dumbbell", - "muscle_groups": "obliques,core,forearms", - "synonyms": "Single Arm Dumbbell Suitcase Carry" - }, - "weight": 30, - "reps": null, - "duration": 35, - "duration_audio": "/media/quantities_audio/for_35_seconds.m4a", - "weight_audio": "/media/quantities_audio/for_30_pounds.m4a", - "created_at": "2023-06-14T13:28:52.947120Z" - }, - { - "workout": 4, - "exercise": { - "id": 370, - "muscles": [ - { - "id": 9146, - "created_at": "2023-06-14T17:05:42.064613Z", - "updated_at": "2023-06-14T17:05:42.064979Z", - "exercise": 370, - "muscle": 4 - }, - { - "id": 9147, - "created_at": "2023-06-14T17:05:42.065611Z", - "updated_at": "2023-06-14T17:05:42.066018Z", - "exercise": 370, + "id": 7270, + "created_at": "2023-06-14T17:05:39.769351Z", + "updated_at": "2023-06-14T17:05:39.769758Z", + "exercise": 992, "muscle": 6 }, { - "id": 9148, - "created_at": "2023-06-14T17:05:42.066724Z", - "updated_at": "2023-06-14T17:05:42.067255Z", - "exercise": 370, - "muscle": 3 + "id": 7271, + "created_at": "2023-06-14T17:05:39.770480Z", + "updated_at": "2023-06-14T17:05:39.771111Z", + "exercise": 992, + "muscle": 4 } ], "equipment": [ { - "id": 1763, - "created_at": "2023-06-13T02:28:05.215315Z", - "updated_at": "2023-06-13T02:28:05.215849Z", - "exercise": 370, + "id": 944, + "created_at": "2023-06-13T02:28:04.294180Z", + "updated_at": "2023-06-13T02:28:04.294658Z", + "exercise": 992, "equipment": 1091 } ], - "audio_url": "/media/exercise_audio/Single-Arm_Dumbbell_Suitcase_Deadlift.m4a", - "video_url": "/media/exercise_videos/Single-Arm_Dumbbell_Suitcase_Deadlift.mp4", - "created_at": "2023-06-11T22:50:18.961690Z", - "updated_at": "2023-06-11T22:50:18.961696Z", - "name": "Single-Arm Dumbbell Suitcase Deadlift", - "description": "Start with your feet just outside your hips,, and the dumbbell in your right hand.. Hinge your hips back,, and let your shoulders forward to lower the weight.. Push through the ground to stand up..", - "side": "right_arm", - "is_two_dumbbells": false, + "audio_url": "/media/exercise_audio/2_Dumbbell_Single-Leg_Deadlift.m4a", + "video_url": "/media/exercise_videos/2_Dumbbell_Single-Leg_Deadlift.mp4", + "created_at": "2023-06-11T22:50:19.197099Z", + "updated_at": "2023-06-11T22:50:19.197105Z", + "name": "2 Dumbbell Single-Leg Deadlift", + "description": "Holding a dumbbell in each hand, with your right leg on the ground, hinge at your hips and let your body see-saw down until you are parallel with the ground. Snap back to a standing position.", + "side": "right_leg", + "is_two_dumbbells": true, "is_trackable_distance": false, "is_alternating": false, "is_weight": true, "is_distance": false, "is_duration": true, "is_reps": true, - "joints_used": "ankle,lumbar spine,elbow,hip,knee", + "joints_used": "ankle,lumbar spine,hip,knee,wrist", "movement_patterns": "lower pull,lower pull - hip hinge", "equipment_required": "Dumbbell", - "muscle_groups": "glutes,hamstrings,obliques", - "synonyms": "Single Arm Dumbbell Suitcase Deadlift" + "muscle_groups": "hamstrings,glutes", + "synonyms": "2 Dumbbell Single Leg Deadlift" }, - "weight": 30, - "reps": null, - "duration": 35, - "duration_audio": "/media/quantities_audio/for_35_seconds.m4a", - "weight_audio": "/media/quantities_audio/for_30_pounds.m4a", - "created_at": "2023-06-14T13:28:52.947298Z" + "weight": 10, + "reps": 12, + "duration": null, + "duration_audio": null, + "weight_audio": "/media/quantities_audio/for_10_pounds.m4a", + "created_at": "2023-06-20T20:53:51.251968Z" }, { - "workout": 4, + "workout": 20, "exercise": { - "id": 1012, + "id": 992, "muscles": [ { - "id": 8968, - "created_at": "2023-06-14T17:05:41.850461Z", - "updated_at": "2023-06-14T17:05:41.850890Z", - "exercise": 1012, - "muscle": 2 + "id": 7270, + "created_at": "2023-06-14T17:05:39.769351Z", + "updated_at": "2023-06-14T17:05:39.769758Z", + "exercise": 992, + "muscle": 6 }, { - "id": 8969, - "created_at": "2023-06-14T17:05:41.851562Z", - "updated_at": "2023-06-14T17:05:41.851932Z", - "exercise": 1012, - "muscle": 27 - } - ], - "equipment": [ - { - "id": 1675, - "created_at": "2023-06-13T02:28:05.120220Z", - "updated_at": "2023-06-13T02:28:05.120555Z", - "exercise": 1012, - "equipment": 1089 - } - ], - "audio_url": "/media/exercise_audio/Scissors.m4a", - "video_url": "/media/exercise_videos/Scissors.mp4", - "created_at": "2023-06-11T22:50:19.204261Z", - "updated_at": "2023-06-11T22:50:19.204267Z", - "name": "Scissors", - "description": "", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": true, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": true, - "joints_used": "lumbar spine,hip", - "movement_patterns": "core", - "equipment_required": "Yoga Mat", - "muscle_groups": "core,hip adductors", - "synonyms": "" - }, - "weight": null, - "reps": null, - "duration": 35, - "duration_audio": "/media/quantities_audio/for_35_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.947467Z" - }, - { - "workout": 4, - "exercise": { - "id": 798, - "muscles": [], - "equipment": [], - "audio_url": "/media/exercise_audio/Recover.m4a", - "video_url": "/media/exercise_videos/Recover.mp4", - "created_at": "2023-06-11T22:50:19.127914Z", - "updated_at": "2023-06-11T22:50:19.127921Z", - "name": "Recover", - "description": "Use this time to catch your breath. It will help you get more out of what's next", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": false, - "joints_used": "", - "movement_patterns": "", - "equipment_required": "", - "muscle_groups": "", - "synonyms": null - }, - "weight": null, - "reps": null, - "duration": 20, - "duration_audio": "/media/quantities_audio/for_20_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.947631Z" - }, - { - "workout": 4, - "exercise": { - "id": 495, - "muscles": [ - { - "id": 7696, - "created_at": "2023-06-14T17:05:40.301365Z", - "updated_at": "2023-06-14T17:05:40.301765Z", - "exercise": 495, + "id": 7271, + "created_at": "2023-06-14T17:05:39.770480Z", + "updated_at": "2023-06-14T17:05:39.771111Z", + "exercise": 992, "muscle": 4 - }, - { - "id": 7697, - "created_at": "2023-06-14T17:05:40.302477Z", - "updated_at": "2023-06-14T17:05:40.302855Z", - "exercise": 495, - "muscle": 5 } ], "equipment": [ { - "id": 1139, - "created_at": "2023-06-13T02:28:04.524659Z", - "updated_at": "2023-06-13T02:28:04.525069Z", - "exercise": 495, - "equipment": 1089 + "id": 944, + "created_at": "2023-06-13T02:28:04.294180Z", + "updated_at": "2023-06-13T02:28:04.294658Z", + "exercise": 992, + "equipment": 1091 } ], - "audio_url": "/media/exercise_audio/Chair_Pose.m4a", - "video_url": "/media/exercise_videos/Chair_Pose.mp4", - "created_at": "2023-06-11T22:50:19.010855Z", - "updated_at": "2023-06-11T22:50:19.010862Z", - "name": "Chair Pose", - "description": "", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": false, - "joints_used": "ankle,hip,knee,shoulder", - "movement_patterns": "yoga", - "equipment_required": "Yoga Mat", - "muscle_groups": "glutes,quads", - "synonyms": "" - }, - "weight": null, - "reps": null, - "duration": 30, - "duration_audio": "/media/quantities_audio/for_30_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.947793Z" - }, - { - "workout": 4, - "exercise": { - "id": 798, - "muscles": [], - "equipment": [], - "audio_url": "/media/exercise_audio/Recover.m4a", - "video_url": "/media/exercise_videos/Recover.mp4", - "created_at": "2023-06-11T22:50:19.127914Z", - "updated_at": "2023-06-11T22:50:19.127921Z", - "name": "Recover", - "description": "Use this time to catch your breath. It will help you get more out of what's next", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": false, - "joints_used": "", - "movement_patterns": "", - "equipment_required": "", - "muscle_groups": "", - "synonyms": null - }, - "weight": null, - "reps": null, - "duration": 10, - "duration_audio": "/media/quantities_audio/for_10_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.947967Z" - }, - { - "workout": 4, - "exercise": { - "id": 448, - "muscles": [ - { - "id": 9651, - "created_at": "2023-06-14T17:05:42.656915Z", - "updated_at": "2023-06-14T17:05:42.657363Z", - "exercise": 448, - "muscle": 9 - }, - { - "id": 9652, - "created_at": "2023-06-14T17:05:42.658005Z", - "updated_at": "2023-06-14T17:05:42.658465Z", - "exercise": 448, - "muscle": 15 - } - ], - "equipment": [ - { - "id": 1971, - "created_at": "2023-06-13T02:28:05.459371Z", - "updated_at": "2023-06-13T02:28:05.459787Z", - "exercise": 448, - "equipment": 1106 - } - ], - "audio_url": "/media/exercise_audio/Wall_Slide_with_Lift_Off.m4a", - "video_url": "/media/exercise_videos/Wall_Slide_with_Lift_Off.mp4", - "created_at": "2023-06-11T22:50:18.992528Z", - "updated_at": "2023-06-11T22:50:18.992535Z", - "name": "Wall Slide with Lift Off", - "description": "Face a wall with the base of your hand touching the wall and palms facing each other. Slide your hands up the wall while maintaining the same back and forearm position. At the top of the movement, lift your hands off the wall. Replace your hands back on the wall before sliding back down.", - "side": "", - "is_two_dumbbells": false, + "audio_url": "/media/exercise_audio/2_Dumbbell_Single-Leg_Deadlift.m4a", + "video_url": "/media/exercise_videos/2_Dumbbell_Single-Leg_Deadlift.mp4", + "created_at": "2023-06-11T22:50:19.197099Z", + "updated_at": "2023-06-11T22:50:19.197105Z", + "name": "2 Dumbbell Single-Leg Deadlift", + "description": "Holding a dumbbell in each hand, with your right leg on the ground, hinge at your hips and let your body see-saw down until you are parallel with the ground. Snap back to a standing position.", + "side": "right_leg", + "is_two_dumbbells": true, "is_trackable_distance": false, "is_alternating": false, "is_weight": true, "is_distance": false, "is_duration": true, "is_reps": true, - "joints_used": "shoulder,elbow", - "movement_patterns": "mobility,mobility - dynamic", - "equipment_required": "Wall", - "muscle_groups": "upper back,rotator cuff", - "synonyms": "" + "joints_used": "ankle,lumbar spine,hip,knee,wrist", + "movement_patterns": "lower pull,lower pull - hip hinge", + "equipment_required": "Dumbbell", + "muscle_groups": "hamstrings,glutes", + "synonyms": "2 Dumbbell Single Leg Deadlift" }, - "weight": null, - "reps": null, - "duration": 30, - "duration_audio": "/media/quantities_audio/for_30_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.948128Z" + "weight": 10, + "reps": 12, + "duration": null, + "duration_audio": null, + "weight_audio": "/media/quantities_audio/for_10_pounds.m4a", + "created_at": "2023-06-20T20:53:51.254113Z" }, { - "workout": 4, + "workout": 20, "exercise": { - "id": 798, - "muscles": [], - "equipment": [], - "audio_url": "/media/exercise_audio/Recover.m4a", - "video_url": "/media/exercise_videos/Recover.mp4", - "created_at": "2023-06-11T22:50:19.127914Z", - "updated_at": "2023-06-11T22:50:19.127921Z", - "name": "Recover", - "description": "Use this time to catch your breath. It will help you get more out of what's next", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": false, - "joints_used": "", - "movement_patterns": "", - "equipment_required": "", - "muscle_groups": "", - "synonyms": null - }, - "weight": null, - "reps": null, - "duration": 10, - "duration_audio": "/media/quantities_audio/for_10_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.948291Z" - }, - { - "workout": 4, - "exercise": { - "id": 1045, + "id": 992, "muscles": [ { - "id": 7741, - "created_at": "2023-06-14T17:05:40.358740Z", - "updated_at": "2023-06-14T17:05:40.359220Z", - "exercise": 1045, + "id": 7270, + "created_at": "2023-06-14T17:05:39.769351Z", + "updated_at": "2023-06-14T17:05:39.769758Z", + "exercise": 992, + "muscle": 6 + }, + { + "id": 7271, + "created_at": "2023-06-14T17:05:39.770480Z", + "updated_at": "2023-06-14T17:05:39.771111Z", + "exercise": 992, "muscle": 4 - }, - { - "id": 7742, - "created_at": "2023-06-14T17:05:40.360107Z", - "updated_at": "2023-06-14T17:05:40.360946Z", - "exercise": 1045, - "muscle": 5 - }, - { - "id": 7743, - "created_at": "2023-06-14T17:05:40.362207Z", - "updated_at": "2023-06-14T17:05:40.363132Z", - "exercise": 1045, - "muscle": 16 } ], "equipment": [ { - "id": 1149, - "created_at": "2023-06-13T02:28:04.535504Z", - "updated_at": "2023-06-13T02:28:04.535969Z", - "exercise": 1045, - "equipment": 1089 + "id": 944, + "created_at": "2023-06-13T02:28:04.294180Z", + "updated_at": "2023-06-13T02:28:04.294658Z", + "exercise": 992, + "equipment": 1091 } ], - "audio_url": "/media/exercise_audio/Crescent_Lunge.m4a", - "video_url": "/media/exercise_videos/Crescent_Lunge.mp4", - "created_at": "2023-06-11T22:50:19.216136Z", - "updated_at": "2023-06-11T22:50:19.216142Z", - "name": "Crescent Lunge", - "description": "", - "side": "left_side", - "is_two_dumbbells": false, + "audio_url": "/media/exercise_audio/2_Dumbbell_Single-Leg_Deadlift.m4a", + "video_url": "/media/exercise_videos/2_Dumbbell_Single-Leg_Deadlift.mp4", + "created_at": "2023-06-11T22:50:19.197099Z", + "updated_at": "2023-06-11T22:50:19.197105Z", + "name": "2 Dumbbell Single-Leg Deadlift", + "description": "Holding a dumbbell in each hand, with your right leg on the ground, hinge at your hips and let your body see-saw down until you are parallel with the ground. Snap back to a standing position.", + "side": "right_leg", + "is_two_dumbbells": true, "is_trackable_distance": false, "is_alternating": false, - "is_weight": false, + "is_weight": true, "is_distance": false, "is_duration": true, - "is_reps": false, - "joints_used": "ankle,hip,knee,shoulder", - "movement_patterns": "yoga,mobility - static,lower push - lunge", - "equipment_required": "Yoga Mat", - "muscle_groups": "glutes,quads,hip flexor", - "synonyms": "" + "is_reps": true, + "joints_used": "ankle,lumbar spine,hip,knee,wrist", + "movement_patterns": "lower pull,lower pull - hip hinge", + "equipment_required": "Dumbbell", + "muscle_groups": "hamstrings,glutes", + "synonyms": "2 Dumbbell Single Leg Deadlift" }, - "weight": null, - "reps": null, - "duration": 30, - "duration_audio": "/media/quantities_audio/for_30_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.948449Z" - }, - { - "workout": 4, - "exercise": { - "id": 1047, - "muscles": [ - { - "id": 7744, - "created_at": "2023-06-14T17:05:40.364417Z", - "updated_at": "2023-06-14T17:05:40.364979Z", - "exercise": 1047, - "muscle": 4 - }, - { - "id": 7745, - "created_at": "2023-06-14T17:05:40.365773Z", - "updated_at": "2023-06-14T17:05:40.366233Z", - "exercise": 1047, - "muscle": 5 - }, - { - "id": 7746, - "created_at": "2023-06-14T17:05:40.366905Z", - "updated_at": "2023-06-14T17:05:40.367271Z", - "exercise": 1047, - "muscle": 16 - } - ], - "equipment": [ - { - "id": 1150, - "created_at": "2023-06-13T02:28:04.536605Z", - "updated_at": "2023-06-13T02:28:04.537010Z", - "exercise": 1047, - "equipment": 1089 - } - ], - "audio_url": "/media/exercise_audio/Crescent_Lunge.m4a", - "video_url": "/media/exercise_videos/Crescent_Lunge.mp4", - "created_at": "2023-06-11T22:50:19.216834Z", - "updated_at": "2023-06-11T22:50:19.216840Z", - "name": "Crescent Lunge", - "description": "", - "side": "right_side", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": false, - "joints_used": "ankle,hip,knee,shoulder", - "movement_patterns": "yoga,mobility - static,lower push - lunge", - "equipment_required": "Yoga Mat", - "muscle_groups": "glutes,quads,hip flexor", - "synonyms": "" - }, - "weight": null, - "reps": null, - "duration": 30, - "duration_audio": "/media/quantities_audio/for_30_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.948594Z" - }, - { - "workout": 4, - "exercise": { - "id": 798, - "muscles": [], - "equipment": [], - "audio_url": "/media/exercise_audio/Recover.m4a", - "video_url": "/media/exercise_videos/Recover.mp4", - "created_at": "2023-06-11T22:50:19.127914Z", - "updated_at": "2023-06-11T22:50:19.127921Z", - "name": "Recover", - "description": "Use this time to catch your breath. It will help you get more out of what's next", - "side": "", - "is_two_dumbbells": false, - "is_trackable_distance": false, - "is_alternating": false, - "is_weight": false, - "is_distance": false, - "is_duration": true, - "is_reps": false, - "joints_used": "", - "movement_patterns": "", - "equipment_required": "", - "muscle_groups": "", - "synonyms": null - }, - "weight": null, - "reps": null, - "duration": 10, - "duration_audio": "/media/quantities_audio/for_10_seconds.m4a", - "weight_audio": null, - "created_at": "2023-06-14T13:28:52.948713Z" + "weight": 10, + "reps": 12, + "duration": null, + "duration_audio": null, + "weight_audio": "/media/quantities_audio/for_10_pounds.m4a", + "created_at": "2023-06-20T20:53:51.255969Z" } ], "registered_user": { - "id": 1, - "first_name": "test1_fist", - "last_name": "test1_last", + "id": 2, + "first_name": "test2_first", + "last_name": "test2_last", "image": "", "nick_name": null } diff --git a/Werkout_ios/Network/Fetchables.swift b/Werkout_ios/Network/Fetchables.swift index b45c5ca..315738f 100644 --- a/Werkout_ios/Network/Fetchables.swift +++ b/Werkout_ios/Network/Fetchables.swift @@ -36,8 +36,14 @@ class AllExerciseFetchable: Fetchable { var endPoint: String = "exercise/all/" } +class CompletedWorkoutFetchable: Fetchable { + typealias Response = [CompletedWorkout] + var endPoint: String = "workout/completed/" +} + class CreateWorkoutFetchable: Postable { var postableData: [String : Any]? + var successStatus = 201 typealias Response = Workout var endPoint: String = "workout/create/" @@ -49,6 +55,7 @@ class CreateWorkoutFetchable: Postable { class CompleteWorkoutFetchable: Postable { var postableData: [String : Any]? + var successStatus = 201 typealias Response = CompletedWorkout var endPoint: String = "workout/complete/" @@ -57,3 +64,19 @@ class CompleteWorkoutFetchable: Postable { self.postableData = postData } } + +class LoginFetchable: Postable { + var postableData: [String : Any]? + var successStatus = 200 + + typealias Response = RegisteredUser + var endPoint: String = "registered_user/login/" + + var attachToken: Bool { + return false + } + + init(postData: [String: Any]) { + self.postableData = postData + } +} diff --git a/Werkout_ios/Network/Network.swift b/Werkout_ios/Network/Network.swift index 3c34284..0a85554 100644 --- a/Werkout_ios/Network/Network.swift +++ b/Werkout_ios/Network/Network.swift @@ -13,12 +13,13 @@ enum FetchableError: Error { case decodeError(Error) case endOfFileError case noPostData + case noToken case statusError(Int, String?) } protocol Fetchable { associatedtype Response: Codable - + var attachToken: Bool { get } var baseURL: String { get } var endPoint: String { get } func fetch(completion: @escaping (Result) -> Void) @@ -26,6 +27,7 @@ protocol Fetchable { protocol Postable: Fetchable { var postableData: [String: Any]? { get } + var successStatus: Int { get } } extension Fetchable { @@ -33,10 +35,24 @@ extension Fetchable { "http://127.0.0.1:8000/" } + var attachToken: Bool { + return true + } + func fetch(completion: @escaping (Result) -> Void) { let url = URL(string: baseURL+endPoint)! + + var request = URLRequest(url: url,timeoutInterval: Double.infinity) + if attachToken { + guard let token = UserStore.shared.token else { + completion(.failure(.noPostData)) + return + } + request.addValue(token, forHTTPHeaderField: "Authorization") + } + request.addValue("application/json", forHTTPHeaderField: "Content-Type") - let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, response, error) in + let task = URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in if let error = error { completion(.failure(.apiError(error))) return @@ -62,17 +78,23 @@ extension Fetchable { extension Postable { func fetch(completion: @escaping (Result) -> Void) { - guard let postableData = postableData else { - completion(.failure(.noPostData)) + guard let postableData = postableData else { + completion(.failure(.noPostData)) return } - - let url = URL(string: baseURL+endPoint)! - + + let url = URL(string: baseURL+endPoint)! + let postData = try! JSONSerialization.data(withJSONObject:postableData) var request = URLRequest(url: url,timeoutInterval: Double.infinity) - request.addValue("Token fd59cbf6f5db98726e896cdb6b095ecb9c43a592", forHTTPHeaderField: "Authorization") + if attachToken { + guard let token = UserStore.shared.token else { + completion(.failure(.noPostData)) + return + } + request.addValue(token, forHTTPHeaderField: "Authorization") + } request.addValue("application/json", forHTTPHeaderField: "Content-Type") request.httpMethod = "POST" @@ -85,7 +107,7 @@ extension Postable { } if let httpRespone = response as? HTTPURLResponse { - if httpRespone.statusCode != 201 { + if httpRespone.statusCode != successStatus { var returnStr: String? if let data = data { returnStr = String(data: data, encoding: .utf8) diff --git a/Werkout_ios/Preview Content/PreviewWorkout.swift b/Werkout_ios/Preview Content/PreviewWorkout.swift index c5d0813..dbcf5c4 100644 --- a/Werkout_ios/Preview Content/PreviewWorkout.swift +++ b/Werkout_ios/Preview Content/PreviewWorkout.swift @@ -74,4 +74,34 @@ class PreviewWorkout { fatalError() } } + + class func parseRegisterdUser() -> RegisteredUser { + if let filepath = Bundle.main.path(forResource: "RegisteredUser", ofType: "json") { + do { + let data = try Data(NSData(contentsOfFile: filepath)) + let muscles = try JSONDecoder().decode(RegisteredUser.self, from: data) + return muscles + } catch { + print(error) + fatalError() + } + } else { + fatalError() + } + } + + class func parseCompletedWorkouts() -> [CompletedWorkout] { + if let filepath = Bundle.main.path(forResource: "CompletedWorkouts", ofType: "json") { + do { + let data = try Data(NSData(contentsOfFile: filepath)) + let muscles = try JSONDecoder().decode([CompletedWorkout].self, from: data) + return muscles + } catch { + print(error) + fatalError() + } + } else { + fatalError() + } + } } diff --git a/Werkout_ios/UserStore.swift b/Werkout_ios/UserStore.swift new file mode 100644 index 0000000..7b8f0be --- /dev/null +++ b/Werkout_ios/UserStore.swift @@ -0,0 +1,38 @@ +// +// UserStore.swift +// Werkout_ios +// +// Created by Trey Tartt on 6/25/23. +// + +import Foundation + +class UserStore: ObservableObject { + static let shared = UserStore() + + @Published public private(set) var registeredUser: RegisteredUser? + + public var token: String? { + guard let token = registeredUser?.token else { + return nil + } + return "Token \(token)" + } + + func login(completion: @escaping (Bool)-> Void) { + let postData = ["email": "user1@user1.com", "password":"test12345"] + LoginFetchable(postData: postData).fetch(completion: { result in + switch result { + case .success(let model): + self.registeredUser = model + completion(true) + case .failure(let failure): + completion(false) + } + }) + } + + func setFakeUser() { + self.registeredUser = PreviewWorkout.parseRegisterdUser() + } +} diff --git a/Werkout_ios/Views/AllWorkouts/AllWorkoutsView.swift b/Werkout_ios/Views/AllWorkouts/AllWorkoutsView.swift index eb45f9a..104bcbe 100644 --- a/Werkout_ios/Views/AllWorkouts/AllWorkoutsView.swift +++ b/Werkout_ios/Views/AllWorkouts/AllWorkoutsView.swift @@ -46,14 +46,22 @@ struct AllWorkoutsView: View { } }.onAppear{ if needsUpdating { - AllWorkoutFetchable().fetch(completion: { result in - needsUpdating = false - switch result { - case .success(let model): - DispatchQueue.main.async { - self.workouts = model - } - case .failure(let failure): + UserStore.shared.login(completion: { success in + if success { + DataStore.shared.fetchAllData() + + AllWorkoutFetchable().fetch(completion: { result in + needsUpdating = false + switch result { + case .success(let model): + DispatchQueue.main.async { + self.workouts = model + } + case .failure(let failure): + fatalError("shit broke") + } + }) + } else { fatalError("shit broke") } }) diff --git a/Werkout_ios/Views/CompletedWorkout/CompletedWorkoutView.swift b/Werkout_ios/Views/CompletedWorkout/CompletedWorkoutView.swift index a2949b6..9d5efdd 100644 --- a/Werkout_ios/Views/CompletedWorkout/CompletedWorkoutView.swift +++ b/Werkout_ios/Views/CompletedWorkout/CompletedWorkoutView.swift @@ -21,18 +21,31 @@ struct CompletedWorkoutView: View { VStack { topViews() - calsBurned() - - heartRates() - - rateWorkout() - 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) }) @@ -66,9 +79,16 @@ struct CompletedWorkoutView: View { func calsBurned() -> some View { VStack { - Divider() - Text("calroies burned") - Text("\(postData["total_calories"] as! Float)") + if let cals = postData["total_calories"] as? Float { + HStack { + Image(systemName: "flame.fill") + .foregroundColor(.orange) + .font(.title) + VStack { + Text("\(cals, specifier: "%.0f")") + } + } + } } } @@ -76,24 +96,47 @@ struct CompletedWorkoutView: View { VStack { Divider() - Text("how hard was this shit") - HStack { - Text("easy") + Text("Easy") + .foregroundColor(.green) Spacer() Text("Death") + .foregroundColor(.red) } - Slider(value: $difficulty, in: 0...5, step: 1) + 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 { - Divider() if let heartRates = postData["heart_rates"] as? [Int] { let avg = heartRates.reduce(0, +)/heartRates.count - Text("Avg heart rate: \(avg)") + HStack { + Image(systemName: "heart") + .foregroundColor(.red) + .font(.title) + VStack { + HStack { + Text("\(heartRates.min() ?? 0)") + Text("-") + Text("\(heartRates.max() ?? 0)") + } + Text("\(avg)") + } + } } } } @@ -119,17 +162,21 @@ struct CompletedWorkoutView: View { } } -//struct CompletedWorkoutView_Previews: PreviewProvider { -// static let postBody = [ -// "difficulty": 1, -// "workout_start_time": Date().timeFormatForUpload, -// "workout": 1, -// "total_time": 140 -// ] as [String : Any] -// -// static let workout = PreviewWorkout.workout() -// -// static var previews: some View { -// CompletedWorkoutView(postData: CompletedWorkoutView_Previews.postBody, workout: workout) -// } -//} +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 = PreviewWorkout.workout() + + static var previews: some View { + CompletedWorkoutView(postData: CompletedWorkoutView_Previews.postBody, + workout: workout, + completedWorkoutDismissed: { _ in }) + } +} diff --git a/Werkout_ios/Werkout_iosApp.swift b/Werkout_ios/Werkout_iosApp.swift index 0e80e8e..46688d2 100644 --- a/Werkout_ios/Werkout_iosApp.swift +++ b/Werkout_ios/Werkout_iosApp.swift @@ -62,7 +62,7 @@ struct Werkout_iosApp: App { .tag(3) } .onAppear{ - DataStore.shared.fetchAllData() + } .onReceive(pub) { (output) in self.tabSelection = 1