Files
WerkoutIOS/Werkout_ios/Views/AddExerciseView.swift
Trey t e6cc60b064 WIP
2023-06-18 21:12:17 -05:00

244 lines
9.2 KiB
Swift

//
// CreateWorkout.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/15/23.
//
import Foundation
import SwiftUI
import Combine
struct AddExerciseView: View {
@State var exercises: [ExerciseExercise]?
@State var equipment: [Equipment]?
@State var muscles: [Muscle]?
@State var selectedMuscles = [Muscle]()
@State var selectedEquipment = [Equipment]()
@State var filteredExercises = [ExerciseExercise]()
@State var searchString: String = ""
@EnvironmentObject var bridgeModule: BridgeModule
@Environment(\.dismiss) var dismiss
var selectedWorkout: ((ExerciseExercise) -> Void)
var body: some View {
VStack {
if let muscles = muscles {
Button("toggle all", action: {
if self.selectedMuscles.count > 0 {
self.selectedMuscles.removeAll()
} else {
self.selectedMuscles.append(contentsOf: muscles)
}
filterExercises()
})
ScrollView(.horizontal) {
HStack(spacing: 10) {
ForEach(muscles, id:\.id) { muscle in
ZStack {
RoundedRectangle(cornerRadius: 8)
.stroke(selectedMuscles.contains(where: { $0.id == muscle.id }) ? .green : .gray, lineWidth: 3)
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text(muscle.name)
.lineLimit(2)
.multilineTextAlignment(.center)
.frame(maxWidth: .infinity, maxHeight: .infinity)
}
.contentShape(Rectangle())
.onTapGesture {
if selectedMuscles.contains(where: { $0.id == muscle.id }) {
self.selectedMuscles.removeAll(where: {
$0.id == muscle.id
})
} else {
self.selectedMuscles.append(muscle)
}
filterExercises()
}
.frame(width: 150, height: 70)
}
}.padding()
}.frame(height: 100)
}
if let equipment = equipment {
Button("toggle all", action: {
if self.selectedEquipment.count > 0 {
self.selectedEquipment.removeAll()
} else {
self.selectedEquipment.append(contentsOf: equipment)
}
filterExercises()
})
ScrollView(.horizontal) {
HStack(spacing: 10) {
ForEach(equipment, id:\.id) { aequipment in
ZStack {
RoundedRectangle(cornerRadius: 8)
.stroke(selectedEquipment.contains(where: { $0.id == aequipment.id }) ? .green : .gray, lineWidth: 3)
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text(aequipment.name ?? "--")
.frame(maxWidth: .infinity, maxHeight: .infinity)
.lineLimit(2)
.multilineTextAlignment(.center)
}
.contentShape(Rectangle())
.onTapGesture {
if selectedEquipment.contains(where: { $0.id == aequipment.id }) {
self.selectedEquipment.removeAll(where: {
$0.id == aequipment.id
})
} else {
self.selectedEquipment.append(aequipment)
}
filterExercises()
}
.frame(width: 150, height: 70)
}
}.padding()
}.frame(height: 100)
}
TextField("Filter", text: $searchString)
.onReceive(Just(searchString)) { location in
filterExercises()
}
.padding()
List() {
ForEach(filteredExercises.indices, id: \.self) { i in
let obj = filteredExercises[i]
VStack {
Text(obj.name)
.frame(maxWidth: .infinity, alignment: .leading)
if obj.side.count > 0 {
Text(obj.side)
.font(.footnote)
.frame(maxWidth: .infinity, alignment: .leading)
}
Text(obj.equipmentRequired)
.font(.footnote)
.frame(maxWidth: .infinity, alignment: .leading)
Text(obj.muscleGroups)
.font(.footnote)
.frame(maxWidth: .infinity, alignment: .leading)
}
.contentShape(Rectangle())
.onTapGesture {
selectedWorkout(obj)
dismiss()
}
}
}
}
.onAppear{
parseMuscle()
parseEquipment()
parseExercises()
}
}
func filterExercises() {
if selectedMuscles.count == 0 {
filteredExercises = [ExerciseExercise]()
return
}
if selectedEquipment.count == 0 {
filteredExercises = [ExerciseExercise]()
return
}
guard let exercises = exercises,
let muscles = muscles,
let equipment = equipment else {
filteredExercises = [ExerciseExercise]()
return
}
filteredExercises = exercises.filter({ exercise in
var hasCorrectMuscles = false
if selectedMuscles.count == muscles.count {
hasCorrectMuscles = true
} else {
let exerciseMuscleIds = exercise.muscles.map({ $0.muscle })
let selctedMuscleIds = selectedMuscles.map({ $0.id })
if exerciseMuscleIds.contains(selctedMuscleIds) {
hasCorrectMuscles = true
}
}
var hasCorrectEquipment = false
if selectedEquipment.count == equipment.count {
hasCorrectEquipment = true
} else {
let exerciseEquipmentIds = exercise.equipment.map({ $0.equipment })
let selctedEquipmentIds = selectedEquipment.map({ $0.id })
if exerciseEquipmentIds.contains(selctedEquipmentIds) {
hasCorrectEquipment = true
}
}
if !searchString.isEmpty {
return exercise.name.contains(searchString) && hasCorrectMuscles && hasCorrectEquipment
} else {
return hasCorrectMuscles && hasCorrectEquipment
}
})
}
func parseExercises() {
if let filepath = Bundle.main.path(forResource: "Exercises", ofType: "json") {
do {
let data = try Data(NSData(contentsOfFile: filepath))
let workout = try JSONDecoder().decode([ExerciseExercise].self, from: data)
self.filteredExercises.append(contentsOf: workout)
self.exercises = workout
} catch {
print(error)
fatalError()
}
} else {
fatalError()
}
}
func parseEquipment() {
if let filepath = Bundle.main.path(forResource: "Equipment", ofType: "json") {
do {
let data = try Data(NSData(contentsOfFile: filepath))
let workout = try JSONDecoder().decode([Equipment].self, from: data)
self.equipment = workout
self.selectedEquipment.append(contentsOf: workout)
} catch {
print(error)
fatalError()
}
} else {
fatalError()
}
}
func parseMuscle() {
if let filepath = Bundle.main.path(forResource: "AllMuscles", ofType: "json") {
do {
let data = try Data(NSData(contentsOfFile: filepath))
let workout = try JSONDecoder().decode([Muscle].self, from: data)
self.muscles = workout
self.selectedMuscles.append(contentsOf: workout)
} catch {
print(error)
fatalError()
}
} else {
fatalError()
}
}
}