287 lines
9.6 KiB
Swift
287 lines
9.6 KiB
Swift
//
|
|
// AllWorkoutsView.swift
|
|
// Werkout_ios
|
|
//
|
|
// Created by Trey Tartt on 6/15/23.
|
|
//
|
|
|
|
import Foundation
|
|
import SwiftUI
|
|
|
|
enum MainViewTypes: Int, CaseIterable {
|
|
case AllWorkout = 0
|
|
case MyWorkouts
|
|
|
|
var title: String {
|
|
switch self {
|
|
|
|
case .AllWorkout:
|
|
return "All Workouts"
|
|
case .MyWorkouts:
|
|
return "Planned Workouts"
|
|
}
|
|
}
|
|
}
|
|
|
|
struct AllWorkoutsView: View {
|
|
|
|
@State var isUpdating = false
|
|
@State var workouts: [Workout]?
|
|
var bridgeModule = BridgeModule.shared
|
|
@State public var needsUpdating: Bool = true
|
|
|
|
@ObservedObject var dataStore = DataStore.shared
|
|
|
|
@State private var showWorkoutDetail = false
|
|
@State private var selectedWorkout: Workout? {
|
|
didSet {
|
|
bridgeModule.currentWorkout = selectedWorkout
|
|
}
|
|
}
|
|
|
|
@State private var selectedPlannedWorkout: Workout? {
|
|
didSet {
|
|
bridgeModule.currentWorkout = selectedPlannedWorkout
|
|
}
|
|
}
|
|
|
|
@State private var showLoginView = false
|
|
@State private var selectedSegment: MainViewTypes = .AllWorkout
|
|
@State var selectedDate: Date = Date()
|
|
|
|
let pub = NotificationCenter.default.publisher(for: NSNotification.Name("CreatedNewWorkout"))
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
if let workouts = workouts {
|
|
VStack {
|
|
AllWorkoutPickerView(mainViews: MainViewTypes.allCases,
|
|
selectedSegment: $selectedSegment,
|
|
showCurrentWorkout: {
|
|
selectedWorkout = bridgeModule.currentWorkout
|
|
})
|
|
|
|
switch selectedSegment {
|
|
case .AllWorkout:
|
|
if isUpdating {
|
|
ProgressView()
|
|
.progressViewStyle(.circular)
|
|
}
|
|
|
|
AllWorkoutsListView(workouts: workouts, selectedWorkout: { workout in
|
|
selectedWorkout = workout
|
|
}, refresh: {
|
|
self.needsUpdating = true
|
|
maybeUpdateShit()
|
|
})
|
|
Divider()
|
|
case .MyWorkouts:
|
|
plannedWorkout(workouts: UserStore.shared.plannedWorkouts)
|
|
}
|
|
}
|
|
} else {
|
|
ProgressView()
|
|
.progressViewStyle(.circular)
|
|
}
|
|
}.onAppear{
|
|
// UserStore.shared.logout()
|
|
maybeUpdateShit()
|
|
}
|
|
.sheet(item: $selectedWorkout) { item in
|
|
let viewModel = WorkoutDetailViewModel(workout: item)
|
|
WorkoutDetailView(viewModel: viewModel)
|
|
}
|
|
.sheet(item: $selectedPlannedWorkout) { item in
|
|
let viewModel = WorkoutDetailViewModel(workout: item)
|
|
WorkoutDetailView(viewModel: viewModel, showAddToCalendar: false)
|
|
}
|
|
.sheet(isPresented: $showLoginView) {
|
|
LoginView(completion: {
|
|
self.needsUpdating = true
|
|
maybeUpdateShit()
|
|
})
|
|
}
|
|
.onReceive(pub) { (output) in
|
|
self.needsUpdating = true
|
|
maybeUpdateShit()
|
|
}
|
|
}
|
|
|
|
func plannedWorkout(workouts: [PlannedWorkout]) -> some View {
|
|
List {
|
|
ForEach(workouts, id:\.workout.name) { plannedWorkout in
|
|
HStack {
|
|
VStack(alignment: .leading) {
|
|
Text(plannedWorkout.onDate.plannedDate?.weekDay ?? "-")
|
|
.font(.title)
|
|
|
|
Text(plannedWorkout.onDate.plannedDate?.monthString ?? "-")
|
|
.font(.title)
|
|
|
|
Text(plannedWorkout.onDate.plannedDate?.dateString ?? "-")
|
|
.font(.title)
|
|
}
|
|
|
|
Divider()
|
|
|
|
VStack {
|
|
Text(plannedWorkout.workout.name)
|
|
.font(.title)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
|
|
Text(plannedWorkout.workout.description ?? "")
|
|
.font(.body)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
|
|
Text(plannedWorkout.onDate)
|
|
.font(.footnote)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
.contentShape(Rectangle())
|
|
.onTapGesture {
|
|
selectedPlannedWorkout = plannedWorkout.workout
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func maybeUpdateShit() {
|
|
if UserStore.shared.token != nil{
|
|
if UserStore.shared.plannedWorkouts.isEmpty {
|
|
UserStore.shared.fetchPlannedWorkouts()
|
|
}
|
|
|
|
if needsUpdating {
|
|
self.isUpdating = true
|
|
dataStore.fetchAllData()
|
|
|
|
AllWorkoutFetchable().fetch(completion: { result in
|
|
needsUpdating = false
|
|
switch result {
|
|
case .success(let model):
|
|
DispatchQueue.main.async {
|
|
self.workouts = model
|
|
self.isUpdating = false
|
|
}
|
|
case .failure(_):
|
|
DispatchQueue.main.async {
|
|
self.isUpdating = false
|
|
}
|
|
}
|
|
})
|
|
}
|
|
} else {
|
|
showLoginView = true
|
|
}
|
|
}
|
|
}
|
|
|
|
struct AllWorkoutPickerView: View {
|
|
var mainViews: [MainViewTypes]
|
|
@Binding var selectedSegment: MainViewTypes
|
|
@StateObject var bridgeModule = BridgeModule.shared
|
|
var showCurrentWorkout: (() -> Void)
|
|
|
|
var body: some View {
|
|
HStack {
|
|
Picker("", selection: $selectedSegment) {
|
|
ForEach(mainViews, id: \.self) { viewType in
|
|
Text(viewType.title)
|
|
}
|
|
}
|
|
.pickerStyle(.segmented)
|
|
.padding()
|
|
|
|
if bridgeModule.isInWorkout {
|
|
Button(action: {
|
|
showCurrentWorkout()
|
|
}, label: {
|
|
Image(systemName: "figure.strengthtraining.traditional")
|
|
.padding(.trailing)
|
|
})
|
|
.tint(.blue)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
struct AllWorkoutsListView: View {
|
|
@State var searchString: String = ""
|
|
let workouts: [Workout]
|
|
|
|
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
|
|
}
|
|
}
|
|
var refresh: (() -> Void)
|
|
|
|
var body: some View {
|
|
VStack {
|
|
List {
|
|
ForEach(filteredWorkouts, id:\.name) { workout in
|
|
Section {
|
|
VStack {
|
|
Text(workout.name)
|
|
.font(.title2)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
Text(workout.description ?? "")
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
|
|
if let muscles = workout.muscles,
|
|
muscles.joined(separator: ", ").count > 0{
|
|
Divider()
|
|
Text(muscles.joined(separator: ", "))
|
|
.font(.footnote)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
|
|
if let equipment = workout.equipment,
|
|
equipment.joined(separator: ", ").count > 0 {
|
|
Divider()
|
|
Text(equipment.joined(separator: ", "))
|
|
.font(.footnote)
|
|
.frame(maxWidth: .infinity, alignment: .leading)
|
|
}
|
|
}
|
|
.contentShape(Rectangle())
|
|
.onTapGesture {
|
|
selectedWorkout(workout)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
.refreshable {
|
|
refresh()
|
|
}
|
|
TextField("Filter", text: $searchString)
|
|
.padding(.leading)
|
|
}
|
|
}
|
|
}
|
|
|
|
struct AllWorkoutsView_Previews: PreviewProvider {
|
|
static var previews: some View {
|
|
AllWorkoutsView(workouts: PreviewData.allWorkouts())
|
|
}
|
|
}
|