This commit is contained in:
Trey t
2023-06-25 21:11:35 -05:00
parent 508491510c
commit d055ed182d
3 changed files with 205 additions and 92 deletions

View File

@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
1C485C832A489B9C00A6F896 /* CompletedWorkouts.json in Resources */ = {isa = PBXBuildFile; fileRef = 1C485C822A489B9C00A6F896 /* CompletedWorkouts.json */; };
1C485C872A4915C400A6F896 /* CreateWorkoutItemPickerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1C485C862A4915C400A6F896 /* CreateWorkoutItemPickerView.swift */; };
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 */; };
@@ -95,6 +96,7 @@
/* Begin PBXFileReference section */
1C485C822A489B9C00A6F896 /* CompletedWorkouts.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = CompletedWorkouts.json; sourceTree = "<group>"; };
1C485C862A4915C400A6F896 /* CreateWorkoutItemPickerView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CreateWorkoutItemPickerView.swift; 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>"; };
@@ -275,6 +277,7 @@
1CF65A6A2A3C1EAC0042FFBD /* CreateWorkoutMainView.swift */,
1CF65A722A3F60D20042FFBD /* CreateExerciseActionsView.swift */,
1CF65A7A2A3F83440042FFBD /* CreateWorkoutSupersetActionsView.swift */,
1C485C862A4915C400A6F896 /* CreateWorkoutItemPickerView.swift */,
);
path = CreateWorkout;
sourceTree = "<group>";
@@ -487,6 +490,7 @@
1CF65A5B2A3BF4BE0042FFBD /* Equipment.swift in Sources */,
1CF65A452A39FB550042FFBD /* Exercise.swift in Sources */,
1CF65A612A3BF6020042FFBD /* AddExerciseView.swift in Sources */,
1C485C872A4915C400A6F896 /* CreateWorkoutItemPickerView.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -10,35 +10,37 @@ import SwiftUI
import Combine
struct AddExerciseView: View {
enum CreateWorkoutItemPickerViewType {
case muscles
case equipment
}
@State var selectedMuscles = [Muscle]()
@State var selectedEquipment = [Equipment]()
@State var filteredExercises = [ExerciseExercise]()
@State var searchString: String = ""
@StateObject var bridgeModule = BridgeModule.shared
@Environment(\.dismiss) var dismiss
var selectedWorkout: ((ExerciseExercise) -> Void)
@State var createWorkoutItemPickerViewModel: CreateWorkoutItemPickerViewModel?
@State var createWorkoutItemPickerViewType: CreateWorkoutItemPickerViewType?
var body: some View {
VStack {
muscleView()
Divider()
equipmentView()
Divider()
TextField("Filter", text: $searchString)
.onReceive(Just(searchString)) { location in
filterExercises()
}
.padding()
Divider()
HStack {
muscleView()
.frame(maxWidth: .infinity)
Divider()
equipmentView()
.frame(maxWidth: .infinity)
}
.padding(.top)
.frame(height: 44)
exerciseView()
.padding(.top)
}
.onAppear{
if #function.hasPrefix("__preview") {
@@ -53,6 +55,38 @@ struct AddExerciseView: View {
selectedEquipment = equipment
filteredExercises = exercises
}
.sheet(item: $createWorkoutItemPickerViewModel) { item in
CreateWorkoutItemPickerView(viewModel: item, completed: { selectedids in
if let viewType = createWorkoutItemPickerViewType {
switch viewType {
case .muscles:
if let muscles = DataStore.shared.allMuscles {
selectedMuscles.removeAll()
for id in selectedids {
if let muscle = muscles.first(where: {
$0.id == id
}) {
selectedMuscles.append(muscle)
}
}
}
case .equipment:
if let equipment = DataStore.shared.allEquipment {
selectedEquipment.removeAll()
for id in selectedids {
if let equipment = equipment.first(where: {
$0.id == id
}) {
selectedEquipment.append(equipment)
}
}
}
}
}
filterExercises()
})
}
.background(Color(uiColor: .tertiarySystemBackground))
}
@@ -97,94 +131,57 @@ struct AddExerciseView: View {
}
}
if !searchString.isEmpty {
return exercise.name.contains(searchString) && hasCorrectMuscles && hasCorrectEquipment
} else {
return hasCorrectMuscles && hasCorrectEquipment
}
return hasCorrectMuscles && hasCorrectEquipment
})
}
func muscleView() -> some View {
VStack {
if let _ = DataStore.shared.allMuscles {
Text("Select Muscles")
.foregroundColor(.cyan)
Text("\(selectedMuscles.count) Selected")
}
}
.onTapGesture {
if let muscles = DataStore.shared.allMuscles {
Button("toggle all", action: {
if self.selectedMuscles.count > 0 {
self.selectedMuscles.removeAll()
} else {
self.selectedMuscles.append(contentsOf: muscles)
}
filterExercises()
var createWorkoutItemPickerModels = [CreateWorkoutItemPickerModel]()
muscles.forEach({
let model = CreateWorkoutItemPickerModel(id: $0.id, name: $0.name)
createWorkoutItemPickerModels.append(model)
})
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)
createWorkoutItemPickerModels = createWorkoutItemPickerModels.sorted(by: {
$0.name < $1.name
})
let selectedIds = selectedMuscles.map { $0.id }
createWorkoutItemPickerViewModel = CreateWorkoutItemPickerViewModel(allValues: createWorkoutItemPickerModels, selectedIds: selectedIds)
createWorkoutItemPickerViewType = .muscles
}
}
}
func equipmentView() -> some View {
VStack {
if let _ = DataStore.shared.allEquipment {
Text("Select Equipment")
.foregroundColor(.cyan)
Text("\(selectedEquipment.count) Selected")
}
}
.onTapGesture {
if let equipment = DataStore.shared.allEquipment {
Button("toggle all", action: {
if self.selectedEquipment.count > 0 {
self.selectedEquipment.removeAll()
} else {
self.selectedEquipment.append(contentsOf: equipment)
}
filterExercises()
var createWorkoutItemPickerModels = [CreateWorkoutItemPickerModel]()
equipment.forEach({
let model = CreateWorkoutItemPickerModel(id: $0.id,
name: $0.name ?? "-")
createWorkoutItemPickerModels.append(model)
})
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)
createWorkoutItemPickerModels = createWorkoutItemPickerModels.sorted(by: {
$0.name < $1.name
})
let selectedIds = selectedEquipment.map { $0.id }
createWorkoutItemPickerViewModel = CreateWorkoutItemPickerViewModel(allValues: createWorkoutItemPickerModels, selectedIds: selectedIds)
createWorkoutItemPickerViewType = .equipment
}
}
}

View File

@@ -0,0 +1,112 @@
//
// CreateWorkoutItemPicker.swift
// Werkout_ios
//
// Created by Trey Tartt on 6/25/23.
//
import SwiftUI
import Combine
struct CreateWorkoutItemPickerModel {
let id: Int
let name: String
}
class CreateWorkoutItemPickerViewModel: Identifiable, ObservableObject {
let allValues: [CreateWorkoutItemPickerModel]
@Published var selectedIds: [Int]
init(allValues: [CreateWorkoutItemPickerModel], selectedIds: [Int]) {
self.allValues = allValues
self.selectedIds = selectedIds
}
func toggleAll() {
if selectedIds.isEmpty {
selectedIds.append(contentsOf: allValues.map({ $0.id }))
} else {
selectedIds.removeAll()
}
}
}
struct CreateWorkoutItemPickerView: View {
@ObservedObject var viewModel: CreateWorkoutItemPickerViewModel
var completed: (([Int]) -> Void)
@Environment(\.dismiss) var dismiss
@State var searchString: String = ""
var body: some View {
VStack {
List() {
ForEach(viewModel.allValues, id:\.self.id) { value in
if searchString.isEmpty || value.name.lowercased().contains(searchString.lowercased()) {
HStack {
Circle()
.stroke(.blue, lineWidth: 1)
.background(Circle().fill(viewModel.selectedIds.contains(value.id) ? .blue :.clear))
.frame(width: 33, height: 33)
Text(value.name)
}
.contentShape(Rectangle())
.onTapGesture {
if viewModel.selectedIds.contains(value.id) {
if let idx = viewModel.selectedIds.firstIndex(of: value.id){
viewModel.selectedIds.remove(at: idx)
}
} else {
viewModel.selectedIds.append(value.id)
}
}
}
}
}
TextField("Filter", text: $searchString)
.padding()
HStack {
Button(action: {
viewModel.toggleAll()
}, label: {
Image(systemName: "checklist")
.font(.title)
})
.frame(maxWidth: 44, alignment: .center)
.frame(height: 44)
.foregroundColor(.green)
.background(.white)
.cornerRadius(8)
.padding()
Button(action: {
completed(viewModel.selectedIds)
dismiss()
}, label: {
Text("done")
})
.frame(maxWidth: .infinity, alignment: .center)
.frame(height: 44)
.foregroundColor(.blue)
.background(.yellow)
.cornerRadius(8)
.padding()
.frame(maxWidth: .infinity)
}
}
}
}
struct CreateWorkoutItemPickerView_Previews: PreviewProvider {
static let fakeValues = [CreateWorkoutItemPickerModel(id: 1, name: "one"),
CreateWorkoutItemPickerModel(id: 2, name: "two"),
CreateWorkoutItemPickerModel(id: 3, name: "three")]
static var previews: some View {
CreateWorkoutItemPickerView(viewModel: CreateWorkoutItemPickerViewModel(allValues: fakeValues, selectedIds: [1]), completed: { selectedIds in
})
}
}