WIP
This commit is contained in:
@@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct RegisteredUser: Codable {
|
struct RegisteredUser: Codable, Hashable {
|
||||||
let id: Int
|
let id: Int
|
||||||
let firstName, lastName, image: String?
|
let firstName, lastName, image: String?
|
||||||
let nickName: String?
|
let nickName: String?
|
||||||
|
|||||||
@@ -12,12 +12,14 @@ struct Superset: Codable, Identifiable, Hashable {
|
|||||||
let exercises: [SupersetExercise]
|
let exercises: [SupersetExercise]
|
||||||
let createdAt, updatedAt, name: String?
|
let createdAt, updatedAt, name: String?
|
||||||
let rounds, order, workout: Int
|
let rounds, order, workout: Int
|
||||||
|
let estimatedTime: Double?
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case id, exercises
|
case id, exercises
|
||||||
case createdAt = "created_at"
|
case createdAt = "created_at"
|
||||||
case updatedAt = "updated_at"
|
case updatedAt = "updated_at"
|
||||||
case name, rounds, order, workout
|
case name, rounds, order, workout
|
||||||
|
case estimatedTime = "estimated_time"
|
||||||
}
|
}
|
||||||
|
|
||||||
public func hash(into hasher: inout Hasher) {
|
public func hash(into hasher: inout Hasher) {
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ struct Workout: Codable, Identifiable, Equatable {
|
|||||||
let muscles: [String]?
|
let muscles: [String]?
|
||||||
let equipment: [String]?
|
let equipment: [String]?
|
||||||
let exercise_count: Int?
|
let exercise_count: Int?
|
||||||
|
let createdAt: Date?
|
||||||
|
let estimatedTime: Double?
|
||||||
|
let allSupersetExecercise: [SupersetExercise]?
|
||||||
|
|
||||||
enum CodingKeys: String, CodingKey {
|
enum CodingKeys: String, CodingKey {
|
||||||
case id, name, description, supersets, exercise_count, muscles, equipment
|
case id, name, description, supersets, exercise_count, muscles, equipment
|
||||||
@@ -28,6 +31,9 @@ struct Workout: Codable, Identifiable, Equatable {
|
|||||||
case maleVideos = "male_videos"
|
case maleVideos = "male_videos"
|
||||||
case femaleVideos = "female_videos"
|
case femaleVideos = "female_videos"
|
||||||
case bothVideos = "both_videos"
|
case bothVideos = "both_videos"
|
||||||
|
case createdAt = "created_at"
|
||||||
|
case estimatedTime = "estimated_time"
|
||||||
|
case allSupersetExecercise = "all_superset_exercise"
|
||||||
}
|
}
|
||||||
|
|
||||||
init(from decoder: Decoder) throws {
|
init(from decoder: Decoder) throws {
|
||||||
@@ -45,5 +51,20 @@ struct Workout: Codable, Identifiable, Equatable {
|
|||||||
self.equipment = try container.decodeIfPresent([String].self, forKey: .equipment)
|
self.equipment = try container.decodeIfPresent([String].self, forKey: .equipment)
|
||||||
self.muscles = try container.decodeIfPresent([String].self, forKey: .muscles)
|
self.muscles = try container.decodeIfPresent([String].self, forKey: .muscles)
|
||||||
self.exercise_count = try container.decodeIfPresent(Int.self, forKey: .exercise_count)
|
self.exercise_count = try container.decodeIfPresent(Int.self, forKey: .exercise_count)
|
||||||
|
|
||||||
|
let createdAtStr = try container.decodeIfPresent(String.self, forKey: .createdAt)
|
||||||
|
if let createdAtStr = createdAtStr {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.locale = Locale(identifier: "en_US_POSIX")
|
||||||
|
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
|
||||||
|
let date = formatter.date(from: createdAtStr)
|
||||||
|
self.createdAt = date
|
||||||
|
} else {
|
||||||
|
self.createdAt = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
self.estimatedTime = try container.decodeIfPresent(Double.self, forKey: .estimatedTime)
|
||||||
|
|
||||||
|
allSupersetExecercise = try container.decodeIfPresent([SupersetExercise].self, forKey: .allSupersetExecercise)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ enum BaseURLs: String {
|
|||||||
case dev = "https://dev.werkout.fitness"
|
case dev = "https://dev.werkout.fitness"
|
||||||
|
|
||||||
static var currentBaseURL: String {
|
static var currentBaseURL: String {
|
||||||
return BaseURLs.dev.rawValue
|
return BaseURLs.local.rawValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ class CurrentWorkoutInfo {
|
|||||||
var complete: (() -> Void)?
|
var complete: (() -> Void)?
|
||||||
|
|
||||||
var currentRound = 1
|
var currentRound = 1
|
||||||
|
var allSupersetExecerciseIndex = 0
|
||||||
|
|
||||||
var superset: [Superset] {
|
var superset: [Superset] {
|
||||||
return workout?.supersets?.sorted(by: { $0.order < $1.order }) ?? [Superset]()
|
return workout?.supersets?.sorted(by: { $0.order < $1.order }) ?? [Superset]()
|
||||||
@@ -57,6 +58,7 @@ class CurrentWorkoutInfo {
|
|||||||
|
|
||||||
let superset = supersets[supersetIndex]
|
let superset = supersets[supersetIndex]
|
||||||
let exercise = superset.exercises[exerciseIndex]
|
let exercise = superset.exercises[exerciseIndex]
|
||||||
|
allSupersetExecerciseIndex += 1
|
||||||
return exercise
|
return exercise
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,6 +86,12 @@ class CurrentWorkoutInfo {
|
|||||||
|
|
||||||
let superset = supersets[supersetIndex]
|
let superset = supersets[supersetIndex]
|
||||||
let exercise = superset.exercises[exerciseIndex]
|
let exercise = superset.exercises[exerciseIndex]
|
||||||
|
|
||||||
|
allSupersetExecerciseIndex -= 1
|
||||||
|
if allSupersetExecerciseIndex < 0 {
|
||||||
|
allSupersetExecerciseIndex = 0
|
||||||
|
}
|
||||||
|
|
||||||
return exercise
|
return exercise
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,12 +104,21 @@ class CurrentWorkoutInfo {
|
|||||||
supersetIndex = 0
|
supersetIndex = 0
|
||||||
exerciseIndex = 0
|
exerciseIndex = 0
|
||||||
currentRound = 1
|
currentRound = 1
|
||||||
|
allSupersetExecerciseIndex = 0
|
||||||
self.workout = nil
|
self.workout = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func goToWorkoutAt(supersetIndex: Int, exerciseIndex: Int) -> SupersetExercise? {
|
func goToWorkoutAt(supersetIndex: Int, exerciseIndex: Int) -> SupersetExercise? {
|
||||||
self.supersetIndex = supersetIndex
|
self.supersetIndex = supersetIndex
|
||||||
self.exerciseIndex = exerciseIndex
|
self.exerciseIndex = exerciseIndex
|
||||||
|
self.currentRound = 1
|
||||||
|
|
||||||
|
let currentExercise = currentExercise
|
||||||
|
if let firstIdx = workout?.allSupersetExecercise?.firstIndex(where: {
|
||||||
|
$0.exercise.id == currentExercise?.exercise.id
|
||||||
|
}) {
|
||||||
|
allSupersetExecerciseIndex = firstIdx
|
||||||
|
}
|
||||||
|
|
||||||
return currentExercise
|
return currentExercise
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,16 @@ class DataStore: ObservableObject {
|
|||||||
|
|
||||||
private let fetchAllDataQueue = DispatchGroup()
|
private let fetchAllDataQueue = DispatchGroup()
|
||||||
|
|
||||||
public func fetchAllData() {
|
public var workoutsUniqueUsers: [RegisteredUser]? {
|
||||||
|
guard let workouts = allWorkouts else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let users = workouts.compactMap({ $0.registeredUser })
|
||||||
|
return Array(Set(users))
|
||||||
|
}
|
||||||
|
|
||||||
|
public func fetchAllData(completion: @escaping (() -> Void)) {
|
||||||
status = .loading
|
status = .loading
|
||||||
|
|
||||||
fetchAllDataQueue.enter()
|
fetchAllDataQueue.enter()
|
||||||
@@ -35,6 +44,7 @@ class DataStore: ObservableObject {
|
|||||||
|
|
||||||
fetchAllDataQueue.notify(queue: .main) {
|
fetchAllDataQueue.notify(queue: .main) {
|
||||||
self.status = .idle
|
self.status = .idle
|
||||||
|
completion()
|
||||||
}
|
}
|
||||||
|
|
||||||
AllWorkoutFetchable().fetch(completion: { result in
|
AllWorkoutFetchable().fetch(completion: { result in
|
||||||
|
|||||||
@@ -8,36 +8,27 @@
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
struct AllWorkoutsListView: View {
|
struct AllWorkoutsListView: View {
|
||||||
@State var searchString: String = ""
|
enum SortType: String, CaseIterable {
|
||||||
let workouts: [Workout]
|
case name = "Name"
|
||||||
|
case date = "Date"
|
||||||
let selectedWorkout: ((Workout) -> Void)
|
|
||||||
|
|
||||||
var filteredWorkouts: [Workout] {
|
|
||||||
if !searchString.isEmpty, searchString.count > 0 {
|
|
||||||
return workouts.filter({
|
|
||||||
if $0.name.lowercased().contains(searchString.lowercased()) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if let equipment = $0.equipment?.joined(separator: "").lowercased(),
|
|
||||||
equipment.contains(searchString.lowercased()) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if let muscles = $0.muscles?.joined(separator: "").lowercased(),
|
|
||||||
muscles.contains(searchString.lowercased()) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return workouts
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@State var searchString: String = ""
|
||||||
|
@Binding var uniqueWorkoutUsers: [RegisteredUser]?
|
||||||
|
@State private var filteredRegisterdUser: RegisteredUser?
|
||||||
|
|
||||||
|
let workouts: [Workout]
|
||||||
|
let selectedWorkout: ((Workout) -> Void)
|
||||||
|
@State var filteredWorkouts = [Workout]()
|
||||||
var refresh: (() -> Void)
|
var refresh: (() -> Void)
|
||||||
|
@State var currentSort: SortType?
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
VStack {
|
VStack {
|
||||||
|
if let filteredRegisterdUser = filteredRegisterdUser {
|
||||||
|
Text((filteredRegisterdUser.firstName ?? "NA") + "'s Workouts")
|
||||||
|
}
|
||||||
|
|
||||||
ScrollView {
|
ScrollView {
|
||||||
LazyVStack(spacing: 20) {
|
LazyVStack(spacing: 20) {
|
||||||
ForEach(filteredWorkouts, id:\.id) { workout in
|
ForEach(filteredWorkouts, id:\.id) { workout in
|
||||||
@@ -51,24 +42,120 @@ struct AllWorkoutsListView: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.refreshable {
|
.refreshable {
|
||||||
refresh()
|
refresh()
|
||||||
}
|
}
|
||||||
|
|
||||||
TextField("Filter" ,text: $searchString)
|
HStack {
|
||||||
.padding()
|
TextField("Filter" ,text: $searchString)
|
||||||
.textFieldStyle(OvalTextFieldStyle())
|
.padding()
|
||||||
|
.textFieldStyle(OvalTextFieldStyle())
|
||||||
|
|
||||||
|
if let uniqueWorkoutUsers = uniqueWorkoutUsers {
|
||||||
|
Menu(content: {
|
||||||
|
ForEach(uniqueWorkoutUsers, id: \.self) { index in
|
||||||
|
Button(action: {
|
||||||
|
filteredRegisterdUser = index
|
||||||
|
filteredWorkouts = filterWorkouts()
|
||||||
|
}, label: {
|
||||||
|
Text((index.firstName ?? "") + " -" + (index.lastName ?? ""))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Button(action: {
|
||||||
|
filteredRegisterdUser = nil
|
||||||
|
filteredWorkouts = filterWorkouts()
|
||||||
|
}, label: {
|
||||||
|
Text("All")
|
||||||
|
})
|
||||||
|
|
||||||
|
}, label: {
|
||||||
|
Image(systemName: filteredRegisterdUser == nil ? "person.2" : "person.2.fill")
|
||||||
|
.padding(.trailing)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
Menu(content: {
|
||||||
|
ForEach(SortType.allCases, id: \.self) { index in
|
||||||
|
Button(action: {
|
||||||
|
sortWorkouts(sortType: index)
|
||||||
|
}, label: {
|
||||||
|
Text(index.rawValue)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, label: {
|
||||||
|
Image(systemName: "list.number")
|
||||||
|
.padding(.trailing)
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.onChange(of: searchString) { newValue in
|
||||||
|
filteredWorkouts = filterWorkouts()
|
||||||
|
}
|
||||||
|
.onAppear{
|
||||||
|
filteredWorkouts = filterWorkouts()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func sortWorkouts(sortType: SortType) {
|
||||||
|
if currentSort == sortType {
|
||||||
|
filteredWorkouts = filteredWorkouts.reversed()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch sortType {
|
||||||
|
case .name:
|
||||||
|
filteredWorkouts = filteredWorkouts.sorted(by: {
|
||||||
|
$0.name < $1.name
|
||||||
|
})
|
||||||
|
case .date:
|
||||||
|
filteredWorkouts = filteredWorkouts.sorted(by: {
|
||||||
|
$0.createdAt ?? Date() < $1.createdAt ?? Date()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
currentSort = sortType
|
||||||
|
}
|
||||||
|
|
||||||
|
func filterWorkouts() -> [Workout] {
|
||||||
|
var matchingWorkouts = [Workout]()
|
||||||
|
|
||||||
|
if (!searchString.isEmpty && searchString.count > 0) {
|
||||||
|
matchingWorkouts = workouts.filter({
|
||||||
|
if $0.name.lowercased().contains(searchString.lowercased()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if let equipment = $0.equipment?.joined(separator: "").lowercased(),
|
||||||
|
equipment.contains(searchString.lowercased()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if let muscles = $0.muscles?.joined(separator: "").lowercased(),
|
||||||
|
muscles.contains(searchString.lowercased()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if matchingWorkouts.isEmpty {
|
||||||
|
matchingWorkouts.append(contentsOf: workouts)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let filteredRegisterdUser = filteredRegisterdUser {
|
||||||
|
matchingWorkouts = matchingWorkouts.filter({
|
||||||
|
$0.registeredUser == filteredRegisterdUser
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return matchingWorkouts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AllWorkoutsListView_Previews: PreviewProvider {
|
struct AllWorkoutsListView_Previews: PreviewProvider {
|
||||||
static var previews: some View {
|
static var previews: some View {
|
||||||
AllWorkoutsListView(workouts: PreviewData.allWorkouts(),
|
AllWorkoutsListView(uniqueWorkoutUsers: .constant([]),
|
||||||
selectedWorkout: { workout in
|
workouts: PreviewData.allWorkouts(),
|
||||||
|
selectedWorkout: { workout in },
|
||||||
},
|
refresh: { })
|
||||||
refresh: {
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,9 +24,10 @@ enum MainViewTypes: Int, CaseIterable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct AllWorkoutsView: View {
|
struct AllWorkoutsView: View {
|
||||||
|
|
||||||
@State var isUpdating = false
|
@State var isUpdating = false
|
||||||
@State var workouts: [Workout]?
|
@State var workouts: [Workout]?
|
||||||
|
@State var uniqueWorkoutUsers: [RegisteredUser]?
|
||||||
|
|
||||||
var bridgeModule = BridgeModule.shared
|
var bridgeModule = BridgeModule.shared
|
||||||
@State public var needsUpdating: Bool = true
|
@State public var needsUpdating: Bool = true
|
||||||
|
|
||||||
@@ -61,6 +62,7 @@ struct AllWorkoutsView: View {
|
|||||||
selectedWorkout = bridgeModule.currentExerciseInfo.workout
|
selectedWorkout = bridgeModule.currentExerciseInfo.workout
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
switch selectedSegment {
|
switch selectedSegment {
|
||||||
case .AllWorkout:
|
case .AllWorkout:
|
||||||
if isUpdating {
|
if isUpdating {
|
||||||
@@ -68,7 +70,9 @@ struct AllWorkoutsView: View {
|
|||||||
.progressViewStyle(.circular)
|
.progressViewStyle(.circular)
|
||||||
}
|
}
|
||||||
|
|
||||||
AllWorkoutsListView(workouts: workouts, selectedWorkout: { workout in
|
AllWorkoutsListView(uniqueWorkoutUsers: $uniqueWorkoutUsers,
|
||||||
|
workouts: workouts,
|
||||||
|
selectedWorkout: { workout in
|
||||||
selectedWorkout = workout
|
selectedWorkout = workout
|
||||||
}, refresh: {
|
}, refresh: {
|
||||||
self.needsUpdating = true
|
self.needsUpdating = true
|
||||||
@@ -155,21 +159,19 @@ struct AllWorkoutsView: View {
|
|||||||
|
|
||||||
if needsUpdating {
|
if needsUpdating {
|
||||||
self.isUpdating = true
|
self.isUpdating = true
|
||||||
dataStore.fetchAllData()
|
dataStore.fetchAllData(completion: {
|
||||||
|
DispatchQueue.main.async {
|
||||||
AllWorkoutFetchable().fetch(completion: { result in
|
guard let allWorkouts = dataStore.allWorkouts else {
|
||||||
needsUpdating = false
|
return
|
||||||
switch result {
|
|
||||||
case .success(let model):
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.workouts = model
|
|
||||||
self.isUpdating = false
|
|
||||||
}
|
|
||||||
case .failure(_):
|
|
||||||
DispatchQueue.main.async {
|
|
||||||
self.isUpdating = false
|
|
||||||
}
|
}
|
||||||
|
self.workouts = allWorkouts.sorted(by: {
|
||||||
|
$0.createdAt ?? Date() < $1.createdAt ?? Date()
|
||||||
|
})
|
||||||
|
self.isUpdating = false
|
||||||
|
self.uniqueWorkoutUsers = dataStore.workoutsUniqueUsers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.isUpdating = false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -19,6 +19,17 @@ struct WorkoutOverviewView: View {
|
|||||||
|
|
||||||
Text(workout.description ?? "")
|
Text(workout.description ?? "")
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
|
||||||
|
if let estimatedTime = workout.estimatedTime {
|
||||||
|
Text("Time: " + estimatedTime.asString(style: .abbreviated))
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let createdAt = workout.createdAt {
|
||||||
|
Text(createdAt, style: .date)
|
||||||
|
.font(.footnote)
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let exerciseCount = workout.exercise_count {
|
if let exerciseCount = workout.exercise_count {
|
||||||
VStack {
|
VStack {
|
||||||
|
|||||||
@@ -17,8 +17,7 @@ struct ExternalWorkoutDetailView: View {
|
|||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
ZStack {
|
ZStack {
|
||||||
if let workout = bridgeModule.currentExerciseInfo.workout,
|
if let workout = bridgeModule.currentExerciseInfo.workout {
|
||||||
let exercise = bridgeModule.currentExerciseInfo.currentExercise {
|
|
||||||
GeometryReader { metrics in
|
GeometryReader { metrics in
|
||||||
VStack {
|
VStack {
|
||||||
HStack {
|
HStack {
|
||||||
@@ -32,7 +31,7 @@ struct ExternalWorkoutDetailView: View {
|
|||||||
|
|
||||||
VStack {
|
VStack {
|
||||||
ExtExerciseList(workout: workout,
|
ExtExerciseList(workout: workout,
|
||||||
currentExercise: exercise)
|
allSupersetExecerciseIndex: bridgeModule.currentExerciseInfo.allSupersetExecerciseIndex)
|
||||||
|
|
||||||
if let currentExercisePositionString = bridgeModule.currentExercisePositionString {
|
if let currentExercisePositionString = bridgeModule.currentExercisePositionString {
|
||||||
Text(currentExercisePositionString)
|
Text(currentExercisePositionString)
|
||||||
@@ -153,63 +152,64 @@ struct TitleView: View {
|
|||||||
|
|
||||||
struct ExtExerciseList: View {
|
struct ExtExerciseList: View {
|
||||||
var workout: Workout
|
var workout: Workout
|
||||||
var currentExercise: SupersetExercise
|
var allSupersetExecerciseIndex: Int
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if let supersets = workout.supersets {
|
if let allSupersetExecercise = workout.allSupersetExecercise {
|
||||||
ScrollViewReader { proxy in
|
ZStack {
|
||||||
List() {
|
ScrollViewReader { proxy in
|
||||||
ForEach(supersets.indices, id: \.self) { supersetIndex in
|
List() {
|
||||||
let superset = supersets[supersetIndex]
|
ForEach(allSupersetExecercise.indices, id: \.self) { supersetExecerciseIdx in
|
||||||
|
let supersetExecercise = allSupersetExecercise[supersetExecerciseIdx]
|
||||||
Section(content: {
|
HStack {
|
||||||
ForEach(superset.exercises.indices, id: \.self) { exerciseIndex in
|
if supersetExecerciseIdx == allSupersetExecerciseIndex {
|
||||||
let supersetExecercise = superset.exercises[exerciseIndex]
|
Image(systemName: "checkmark")
|
||||||
|
.foregroundColor(.green)
|
||||||
HStack {
|
|
||||||
if supersetExecercise.id == currentExercise.id {
|
|
||||||
Image(systemName: "checkmark")
|
|
||||||
.foregroundColor(.green)
|
|
||||||
.font(Font.system(size: 55))
|
|
||||||
.minimumScaleFactor(0.01)
|
|
||||||
.lineLimit(1)
|
|
||||||
.foregroundColor(.green)
|
|
||||||
}
|
|
||||||
|
|
||||||
Text(supersetExecercise.exercise.name)
|
|
||||||
.font(Font.system(size: 55))
|
.font(Font.system(size: 55))
|
||||||
.minimumScaleFactor(0.01)
|
.minimumScaleFactor(0.01)
|
||||||
.lineLimit(3)
|
.lineLimit(1)
|
||||||
.padding()
|
.foregroundColor(.green)
|
||||||
|
|
||||||
Spacer()
|
|
||||||
}
|
}
|
||||||
.id(supersetExecercise.id)
|
|
||||||
}
|
Text(supersetExecercise.exercise.name)
|
||||||
}, header: {
|
|
||||||
HStack {
|
|
||||||
Text(superset.name ?? "--")
|
|
||||||
.font(Font.system(size: 55))
|
.font(Font.system(size: 55))
|
||||||
.minimumScaleFactor(0.01)
|
.minimumScaleFactor(0.01)
|
||||||
.lineLimit(3)
|
.lineLimit(3)
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
Text("\(superset.rounds) rounds")
|
|
||||||
.font(Font.system(size: 55))
|
|
||||||
.minimumScaleFactor(0.01)
|
|
||||||
.lineLimit(3)
|
|
||||||
.padding()
|
|
||||||
}
|
}
|
||||||
})
|
.id(supersetExecerciseIdx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
.onChange(of: allSupersetExecerciseIndex, perform: { newValue in
|
||||||
|
withAnimation {
|
||||||
|
proxy.scrollTo(allSupersetExecerciseIndex, anchor: .top)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
VStack {
|
||||||
|
Text("\(allSupersetExecerciseIndex+1)/\(workout.allSupersetExecercise?.count ?? 0)")
|
||||||
|
.font(Font.system(size: 55))
|
||||||
|
.minimumScaleFactor(0.01)
|
||||||
|
.lineLimit(1)
|
||||||
|
.padding()
|
||||||
|
.bold()
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.background(
|
||||||
|
Capsule()
|
||||||
|
.strokeBorder(Color.black, lineWidth: 0.8)
|
||||||
|
.background(Color(uiColor: UIColor(red: 148/255,
|
||||||
|
green: 0,
|
||||||
|
blue: 211/255,
|
||||||
|
alpha: 0.5)))
|
||||||
|
.clipped()
|
||||||
|
)
|
||||||
|
.clipShape(Capsule())
|
||||||
|
|
||||||
|
Spacer()
|
||||||
}
|
}
|
||||||
.onChange(of: currentExercise, perform: { newValue in
|
|
||||||
withAnimation {
|
|
||||||
print(newValue.id)
|
|
||||||
proxy.scrollTo(newValue.id, anchor: .top)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -113,6 +113,12 @@ struct ExerciseListView: View {
|
|||||||
Text("\(superset.rounds) rounds")
|
Text("\(superset.rounds) rounds")
|
||||||
.foregroundColor(Color("appColor"))
|
.foregroundColor(Color("appColor"))
|
||||||
.bold()
|
.bold()
|
||||||
|
|
||||||
|
if let estimatedTime = superset.estimatedTime {
|
||||||
|
Text("@ " + estimatedTime.asString(style: .abbreviated))
|
||||||
|
.foregroundColor(Color("appColor"))
|
||||||
|
.bold()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,20 @@ struct InfoView: View {
|
|||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.font(.title3)
|
.font(.title3)
|
||||||
.padding()
|
.padding()
|
||||||
|
|
||||||
if let desc = workout.description {
|
if let desc = workout.description {
|
||||||
Text(desc)
|
Text(desc)
|
||||||
.frame(maxWidth: .infinity, alignment: .leading)
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
.font(.body)
|
.font(.body)
|
||||||
.padding([.leading, .trailing])
|
.padding([.leading, .trailing])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let estimatedTime = workout.estimatedTime {
|
||||||
|
Text(estimatedTime.asString(style: .abbreviated))
|
||||||
|
.frame(maxWidth: .infinity, alignment: .leading)
|
||||||
|
.font(.body)
|
||||||
|
.padding([.leading, .trailing])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,6 @@ struct WorkoutDetailView: View {
|
|||||||
if phoneThotStyle != .off {
|
if phoneThotStyle != .off {
|
||||||
GeometryReader { metrics in
|
GeometryReader { metrics in
|
||||||
ZStack {
|
ZStack {
|
||||||
|
|
||||||
PlayerView(player: $avPlayer)
|
PlayerView(player: $avPlayer)
|
||||||
.frame(width: metrics.size.width * 1, height: metrics.size.height * 1)
|
.frame(width: metrics.size.width * 1, height: metrics.size.height * 1)
|
||||||
.onAppear{
|
.onAppear{
|
||||||
|
|||||||
Reference in New Issue
Block a user