This commit is contained in:
Trey t
2023-06-25 10:59:20 -05:00
parent 01915752b6
commit 24ee992f93
14 changed files with 448 additions and 727 deletions

View File

@@ -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 = "<group>"; };
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 = "<group>"; };
1CF65A272A3972840042FFBD /* Persistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = "<group>"; };
@@ -139,6 +143,8 @@
1CF65AB52A4532940042FFBD /* WatchMainViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WatchMainViewModel.swift; sourceTree = "<group>"; };
1CF65AB72A4534DC0042FFBD /* Werkout_watch Watch App.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Werkout_watch Watch App.entitlements"; sourceTree = "<group>"; };
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 = "<group>"; };
1CF65ABB2A4897E20042FFBD /* RegisteredUser.json */ = {isa = PBXFileReference; lastKnownFileType = text.json; path = RegisteredUser.json; sourceTree = "<group>"; };
/* 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 = "<group>";
@@ -255,6 +262,8 @@
1CF65A562A3BF3830042FFBD /* AllMuscles.json */,
1CF65A5E2A3BF5A60042FFBD /* Equipment.json */,
1CF65A662A3BFF840042FFBD /* Exercises.json */,
1CF65ABB2A4897E20042FFBD /* RegisteredUser.json */,
1C485C822A489B9C00A6F896 /* CompletedWorkouts.json */,
);
path = JSON;
sourceTree = "<group>";
@@ -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 */,

View File

@@ -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"
}
}

View File

@@ -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"
}
}

View File

@@ -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()
}
}
}

View File

@@ -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
}
]

View File

@@ -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"
}

View File

@@ -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
}

View File

@@ -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
}
}

View File

@@ -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<Response, FetchableError>) -> 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<Response, FetchableError>) -> 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<Response, FetchableError>) -> 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)

View File

@@ -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()
}
}
}

View File

@@ -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()
}
}

View File

@@ -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")
}
})

View File

@@ -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 })
}
}

View File

@@ -62,7 +62,7 @@ struct Werkout_iosApp: App {
.tag(3)
}
.onAppear{
DataStore.shared.fetchAllData()
}
.onReceive(pub) { (output) in
self.tabSelection = 1