From d82d0cd9fa7e9afa46dba55d402ee0361be160fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20F=C3=B6rtsch?= Date: Wed, 4 Sep 2024 18:44:28 +0200 Subject: [PATCH] fix repetitive save of WorkoutItem, add: Onboarding, Defaults, Settings, Trainer/Trainee skeletons, reorder files, remove all Bindable --- WorkoutsPlus/Components/AddItemButton.swift | 4 +- .../Components/ExerciseListItem.swift | 18 +--- WorkoutsPlus/Components/StepperListItem.swift | 43 ++++++++++ WorkoutsPlus/Configuration/Defaults.swift | 45 ++++++++++ .../{ => Configuration}/HardcodedData.swift | 0 WorkoutsPlus/ContentView.swift | 6 +- WorkoutsPlus/Debug/DebugList.swift | 64 +++++++++++++++ WorkoutsPlus/{ => Debug}/SampleData.swift | 0 WorkoutsPlus/DebugExerciseList.swift | 29 ------- WorkoutsPlus/Exercise/AddExercise.swift | 2 +- WorkoutsPlus/Exercise/ExerciseDetail.swift | 4 +- WorkoutsPlus/{ => Home}/WorkoutLog.swift | 0 .../{Exercise => Models}/Exercise.swift | 5 +- WorkoutsPlus/Models/Person.swift | 34 ++++++++ WorkoutsPlus/Models/Protocols.swift | 18 ++++ .../{Workout => Models}/Workout.swift | 15 ++-- .../{Workout => Models}/WorkoutItem.swift | 14 ++-- WorkoutsPlus/Onboarding/Onboarding.swift | 82 +++++++++++++++++++ WorkoutsPlus/README.md | 25 ++++++ WorkoutsPlus/Settings.swift | 18 ---- WorkoutsPlus/Settings/Settings.swift | 44 ++++++++++ WorkoutsPlus/Workout/AddWorkout.swift | 4 +- .../Workout/AddWorkoutItemToWorkout.swift | 48 ++++------- WorkoutsPlus/Workout/WorkoutDetail.swift | 36 +++++--- WorkoutsPlus/Workout/WorkoutLibrary.swift | 2 +- 25 files changed, 426 insertions(+), 134 deletions(-) create mode 100644 WorkoutsPlus/Components/StepperListItem.swift create mode 100644 WorkoutsPlus/Configuration/Defaults.swift rename WorkoutsPlus/{ => Configuration}/HardcodedData.swift (100%) create mode 100644 WorkoutsPlus/Debug/DebugList.swift rename WorkoutsPlus/{ => Debug}/SampleData.swift (100%) delete mode 100644 WorkoutsPlus/DebugExerciseList.swift rename WorkoutsPlus/{ => Home}/WorkoutLog.swift (100%) rename WorkoutsPlus/{Exercise => Models}/Exercise.swift (95%) create mode 100644 WorkoutsPlus/Models/Person.swift create mode 100644 WorkoutsPlus/Models/Protocols.swift rename WorkoutsPlus/{Workout => Models}/Workout.swift (84%) rename WorkoutsPlus/{Workout => Models}/WorkoutItem.swift (83%) create mode 100644 WorkoutsPlus/Onboarding/Onboarding.swift create mode 100644 WorkoutsPlus/README.md delete mode 100644 WorkoutsPlus/Settings.swift create mode 100644 WorkoutsPlus/Settings/Settings.swift diff --git a/WorkoutsPlus/Components/AddItemButton.swift b/WorkoutsPlus/Components/AddItemButton.swift index 4fead36..c37a872 100644 --- a/WorkoutsPlus/Components/AddItemButton.swift +++ b/WorkoutsPlus/Components/AddItemButton.swift @@ -12,9 +12,7 @@ struct AddItemButton: View { var action: () -> Void var body: some View { - Button(action: { - action() - }) { + Button(action: action) { HStack { Image(systemName: "plus.circle.fill") .foregroundStyle(.green) diff --git a/WorkoutsPlus/Components/ExerciseListItem.swift b/WorkoutsPlus/Components/ExerciseListItem.swift index 8156a70..a215ae0 100644 --- a/WorkoutsPlus/Components/ExerciseListItem.swift +++ b/WorkoutsPlus/Components/ExerciseListItem.swift @@ -20,23 +20,7 @@ struct ExerciseListItem: View { Button(action: { // workout.addExercise(from: exercise) }) { - HStack { - Text(String(exercise.reps)) - .font(.system(size: 14, weight: .bold)) - .foregroundStyle(.white) - .frame(width: 20, height: 10) - .padding(8) - .background(Color.blue) - .clipShape(RoundedRectangle(cornerRadius: 8)) - Text(exercise.name) - .foregroundStyle(.black) - Spacer() - Stepper( - value: $exercise.reps, - in: 0...100, - step: 1 - ) {} - } + StepperListItem(itemName: exercise.name, itemValue: $exercise.reps) } } } diff --git a/WorkoutsPlus/Components/StepperListItem.swift b/WorkoutsPlus/Components/StepperListItem.swift new file mode 100644 index 0000000..f8312fb --- /dev/null +++ b/WorkoutsPlus/Components/StepperListItem.swift @@ -0,0 +1,43 @@ +// +// StepperListItem.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 04.09.24. +// + +import SwiftUI + +struct StepperListItem: View { + @State var itemName: String + @Binding var itemValue: Int + + var body: some View { + Stepper( + value: $itemValue, + in: 0...100, + step: 1 + ) { + HStack { + Text(String(itemValue)) + .font(.system(size: 14, weight: .bold)) + .foregroundStyle(.white) + .frame(width: 20, height: 10) + .padding(8) + .background(Color.blue) + .clipShape(RoundedRectangle(cornerRadius: 8)) + Text(itemName) + .foregroundStyle(.black) + } + } + } +} + +#Preview { + @Previewable @State var value = 8 + + List { + StepperListItem(itemName: "Short Name", itemValue: $value) + StepperListItem(itemName: "Very very very very long name with whitespace", itemValue: $value) + StepperListItem(itemName: "Veryveryverylonglonglonglongnamewithoutwithwhitespace", itemValue: $value) + } +} diff --git a/WorkoutsPlus/Configuration/Defaults.swift b/WorkoutsPlus/Configuration/Defaults.swift new file mode 100644 index 0000000..a20b3b6 --- /dev/null +++ b/WorkoutsPlus/Configuration/Defaults.swift @@ -0,0 +1,45 @@ +// +// Defaults.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 04.09.24. +// + +import Foundation +import SwiftUI + +public class Defaults: ObservableObject { + @AppStorage("isFirstAppStart") public var isFirstAppStart = true + @AppStorage("isOnboarding") public var isOnboarding = true + @AppStorage("userId") public var userId = UUID().uuidString + + @AppStorage("sets") public var sets = 8 + @AppStorage("reps") public var reps = 8 + + public static let shared = Defaults() +} + +@propertyWrapper +public struct Default: DynamicProperty { + @ObservedObject private var defaults: Defaults + private let keyPath: ReferenceWritableKeyPath + + public init(_ keyPath: ReferenceWritableKeyPath, defaults: Defaults = .shared) { + self.keyPath = keyPath + self.defaults = defaults + } + + public var wrappedValue: T { + get { defaults[keyPath: keyPath] } + nonmutating set { defaults[keyPath: keyPath] = newValue } + } + + public var projectedValue: Binding { + Binding( + get: { defaults[keyPath: keyPath] }, + set: { value in + defaults[keyPath: keyPath] = value + } + ) + } +} diff --git a/WorkoutsPlus/HardcodedData.swift b/WorkoutsPlus/Configuration/HardcodedData.swift similarity index 100% rename from WorkoutsPlus/HardcodedData.swift rename to WorkoutsPlus/Configuration/HardcodedData.swift diff --git a/WorkoutsPlus/ContentView.swift b/WorkoutsPlus/ContentView.swift index c50f846..03831c3 100644 --- a/WorkoutsPlus/ContentView.swift +++ b/WorkoutsPlus/ContentView.swift @@ -10,10 +10,11 @@ import SwiftData struct ContentView: View { @Environment(\.modelContext) private var modelContext + @Default(\.isOnboarding) var isOnboarding var body: some View { TabView { - WorkoutLog() + // WorkoutLog() WorkoutLibrary() .tabItem { Image(systemName: "figure.run.square.stack") @@ -24,7 +25,7 @@ struct ContentView: View { Image(systemName: "figure.run") Text("Exercises") } - DebugExerciseList() + DebugList() .tabItem { Image(systemName: "hammer") Text("Debug") @@ -35,6 +36,7 @@ struct ContentView: View { Text("Settings") } } + .sheet(isPresented: $isOnboarding) { Onboarding() } } } diff --git a/WorkoutsPlus/Debug/DebugList.swift b/WorkoutsPlus/Debug/DebugList.swift new file mode 100644 index 0000000..9430f1e --- /dev/null +++ b/WorkoutsPlus/Debug/DebugList.swift @@ -0,0 +1,64 @@ +// +// DebugList.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 30.08.24. +// + +import SwiftUI +import SwiftData + +struct DebugList: View { + @Query(sort: \Exercise.name) private var exercises: [Exercise] + @Query(sort: \Workout.name) private var workouts: [Workout] + @Query(sort: \WorkoutItem.name) private var workoutItems: [WorkoutItem] + + var body: some View { + List { + Section(header: Text("Exercises")) { + ForEach(exercises) { exercise in + DebugListItem(item: exercise) + } + } + Section(header: Text("Workouts")) { + ForEach(workouts) { workout in + DebugListItem(item: workout) + } + } + Section(header: Text("WorkoutItems")) { + ForEach(workoutItems) { workoutItem in + VStack(alignment: .leading) { + Text("\(workoutItem.name), pos: \(workoutItem.position), reps: \(workoutItem.reps)") + Text(workoutItem.id.uuidString) + .font(.system(size: 12, weight: .bold)) + .fontDesign(.monospaced) + .foregroundStyle(.gray) + } + } + } + } + .tabItem { + Image(systemName: "wrench") + Text("Exercise Debug") + } + } +} + +struct DebugListItem: View { + var item: any Nameable + + var body: some View { + VStack(alignment: .leading) { + Text(item.name) + Text(item.id.uuidString) + .font(.system(size: 12, weight: .bold)) + .fontDesign(.monospaced) + .foregroundStyle(.gray) + } + } +} + +#Preview { + DebugList() + .modelContainer(SampleData.shared.modelContainer) +} diff --git a/WorkoutsPlus/SampleData.swift b/WorkoutsPlus/Debug/SampleData.swift similarity index 100% rename from WorkoutsPlus/SampleData.swift rename to WorkoutsPlus/Debug/SampleData.swift diff --git a/WorkoutsPlus/DebugExerciseList.swift b/WorkoutsPlus/DebugExerciseList.swift deleted file mode 100644 index c0f1674..0000000 --- a/WorkoutsPlus/DebugExerciseList.swift +++ /dev/null @@ -1,29 +0,0 @@ -// -// DebugExerciseList.swift -// WorkoutsPlus -// -// Created by Felix Förtsch on 30.08.24. -// - -import SwiftUI -import SwiftData - -struct DebugExerciseList: View { - @Query(sort: \WorkoutItem.name) private var exercises: [WorkoutItem] - - var body: some View { - List { - ForEach(exercises) { exercise in - Text("\(exercise.name), pos: \(exercise.position)") - } - } - .tabItem { - Image(systemName: "figure.run.square.stack") - Text("Exercise Debug") - } - } -} - -#Preview { - DebugExerciseList() -} diff --git a/WorkoutsPlus/Exercise/AddExercise.swift b/WorkoutsPlus/Exercise/AddExercise.swift index bc1e795..e3f0f4c 100644 --- a/WorkoutsPlus/Exercise/AddExercise.swift +++ b/WorkoutsPlus/Exercise/AddExercise.swift @@ -11,7 +11,7 @@ struct AddExercise: View { @Environment(\.modelContext) private var modelContext @Environment(\.dismiss) private var dismiss - @Bindable var exercise: Exercise + @State var exercise: Exercise var body : some View { Form { diff --git a/WorkoutsPlus/Exercise/ExerciseDetail.swift b/WorkoutsPlus/Exercise/ExerciseDetail.swift index 6e04abf..42f068e 100644 --- a/WorkoutsPlus/Exercise/ExerciseDetail.swift +++ b/WorkoutsPlus/Exercise/ExerciseDetail.swift @@ -1,5 +1,5 @@ // -// ExerciseDetailsView.swift +// ExerciseDetail.swift // WorkoutsPlus // // Created by Felix Förtsch on 10.08.24. @@ -11,7 +11,7 @@ struct ExerciseDetail: View { @Environment(\.dismiss) private var dismiss @Environment(\.modelContext) private var modelContext - @Bindable var exercise: Exercise + @State var exercise: Exercise var body: some View { diff --git a/WorkoutsPlus/WorkoutLog.swift b/WorkoutsPlus/Home/WorkoutLog.swift similarity index 100% rename from WorkoutsPlus/WorkoutLog.swift rename to WorkoutsPlus/Home/WorkoutLog.swift diff --git a/WorkoutsPlus/Exercise/Exercise.swift b/WorkoutsPlus/Models/Exercise.swift similarity index 95% rename from WorkoutsPlus/Exercise/Exercise.swift rename to WorkoutsPlus/Models/Exercise.swift index 64ea7f3..e1b252a 100644 --- a/WorkoutsPlus/Exercise/Exercise.swift +++ b/WorkoutsPlus/Models/Exercise.swift @@ -9,9 +9,10 @@ import Foundation import SwiftData @Model -final class Exercise: Identifiable { - var id = UUID() +final class Exercise: Nameable { static var systemImage = "figure.run" + + var id = UUID() @Attribute(.unique) var name: String // var metric: String = "reps" // var exerciseDescription: ExerciseDescription? diff --git a/WorkoutsPlus/Models/Person.swift b/WorkoutsPlus/Models/Person.swift new file mode 100644 index 0000000..5ab4d50 --- /dev/null +++ b/WorkoutsPlus/Models/Person.swift @@ -0,0 +1,34 @@ +// +// Person.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 03.09.24. +// + +import Foundation +import SwiftData + +@Model +class Trainer: Nameable { + var id = UUID() + var name: String = "" + + var trainees: [Trainee] = [] + + init(name: String) { + self.name = name + } +} + +@Model +class Trainee: Nameable { + var id = UUID() + var name: String = "" + + var trainer: Trainer? + + init(name: String, trainer: Trainer? = nil) { + self.name = name + self.trainer = trainer + } +} diff --git a/WorkoutsPlus/Models/Protocols.swift b/WorkoutsPlus/Models/Protocols.swift new file mode 100644 index 0000000..13ca887 --- /dev/null +++ b/WorkoutsPlus/Models/Protocols.swift @@ -0,0 +1,18 @@ +// +// Protocols.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 04.09.24. +// + +import Foundation + +protocol Nameable: Identifiable { + var id: UUID { get } + var name: String { get } +} + +protocol Positionable: Identifiable { + var id: UUID { get } + var position: Int { get } +} diff --git a/WorkoutsPlus/Workout/Workout.swift b/WorkoutsPlus/Models/Workout.swift similarity index 84% rename from WorkoutsPlus/Workout/Workout.swift rename to WorkoutsPlus/Models/Workout.swift index 67e82ea..d7176d7 100644 --- a/WorkoutsPlus/Workout/Workout.swift +++ b/WorkoutsPlus/Models/Workout.swift @@ -9,11 +9,12 @@ import Foundation import SwiftData @Model -final class Workout: Identifiable { - var id = UUID() - var name: String +final class Workout: Nameable { static var systemImage = "figure.run.square.stack" + var id = UUID() + @Attribute(.unique) var name: String + // Other properties and methods var timestamp: Date = Date.now @@ -25,22 +26,22 @@ final class Workout: Identifiable { func add(workoutItem: WorkoutItem) { self.workoutItems.append(workoutItem) - updateExercisePositions() + updateWorkoutItemsPositions() } func add(workoutItems: [WorkoutItem]) { for workoutItem in workoutItems { self.workoutItems.append(workoutItem) } - updateExercisePositions() + updateWorkoutItemsPositions() } func moveWorkoutItem(from source: IndexSet, to destination: Int) { workoutItems.move(fromOffsets: source, toOffset: destination) - updateExercisePositions() + updateWorkoutItemsPositions() } - private func updateExercisePositions() { + private func updateWorkoutItemsPositions() { for (index, exercise) in workoutItems.enumerated() { exercise.position = index } diff --git a/WorkoutsPlus/Workout/WorkoutItem.swift b/WorkoutsPlus/Models/WorkoutItem.swift similarity index 83% rename from WorkoutsPlus/Workout/WorkoutItem.swift rename to WorkoutsPlus/Models/WorkoutItem.swift index 1543a10..775e8c5 100644 --- a/WorkoutsPlus/Workout/WorkoutItem.swift +++ b/WorkoutsPlus/Models/WorkoutItem.swift @@ -1,5 +1,5 @@ // -// Exercise.swift +// WorkoutItem.swift // WorkoutsPlus // // Created by Felix Förtsch on 10.08.24. @@ -9,10 +9,10 @@ import Foundation import SwiftData @Model -final class WorkoutItem: Identifiable { +final class WorkoutItem: Nameable, Positionable { var id = UUID() var name: String - + var workout: Workout? var workoutItemType: WorkoutItemType var position: Int = 0 @@ -20,11 +20,9 @@ final class WorkoutItem: Identifiable { var reps: Int = 8 // EXERCISE - var exercise: Exercise? { - didSet { - self.name = exercise?.name ?? "self.name" - } - } + var exercise: Exercise? + // TODO: Think about what's happening when an exercise (template) is deleted or changed + // { didSet { self.name = exercise?.name ?? "self.name" } } init(_ reps: Int, _ exercise: String) { self.workoutItemType = .exercise diff --git a/WorkoutsPlus/Onboarding/Onboarding.swift b/WorkoutsPlus/Onboarding/Onboarding.swift new file mode 100644 index 0000000..7ee7259 --- /dev/null +++ b/WorkoutsPlus/Onboarding/Onboarding.swift @@ -0,0 +1,82 @@ +// +// Onboarding.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 04.09.24. +// + +import SwiftUI + +struct Onboarding: View { + @Default(\.isFirstAppStart) var isFirstAppStart + @Default(\.isOnboarding) var isOnboarding + @Default(\.userId) var userId + + @State private var currentPage = 0 + let totalPages = 3 + + var body: some View { + + VStack { + TabView(selection: $currentPage) { + ForEach(0.. 0 { + Button("Zurück") { + currentPage -= 1 + } + .padding(.horizontal, 40) + } + + Spacer() + + Button(currentPage == totalPages - 1 ? "Los geht's!" : "Weiter") { + if currentPage < totalPages - 1 { + currentPage += 1 + } else { + if (isFirstAppStart) { + userId = UUID().uuidString + } + isFirstAppStart = false + isOnboarding = false + } + } + .padding(.horizontal, 40) + } + .padding(.bottom, 40) + } + .tag(index) + } + } + .tabViewStyle(PageTabViewStyle(indexDisplayMode: .always)) + } + } +} + +#Preview { + Onboarding() +} diff --git a/WorkoutsPlus/README.md b/WorkoutsPlus/README.md new file mode 100644 index 0000000..12bf3cc --- /dev/null +++ b/WorkoutsPlus/README.md @@ -0,0 +1,25 @@ +# Workouts+ + +- JSON Import/Export +- Use Multipeer connect for sharing/tracking? +- Progression-Fotos: als eigene App? -> Generalisierung zu "Foto-Track" +- Karte mit öffentlichen Orten einbinden (AOK-Fitnesspark?) + +## Workouts +- time-based: 60 s +- rep-based: 3x +- Loops + +## Trainingspläne + +Idee: Platformdenken + +App ist für Sportler mit einem Trainer. Trainer können die App nutzen, um ihre Trainees mit Trainingsplänen zu versorgen. +Dazu muss der Trainer eine Möglichkeit bekommen bezahlt zu werden? + +## Ernährungspläne + +Visualisierung des Budgets (Balkendiagram, das man via DragNdrop auffüllen kann, um zu sehen, wie man hinkommt) +mglw mehrdimensional? eine Achse kcal eine Achse Protein? + +Energiebudget -> im ersten Schritt einfach immer denselben Ernährungsplan diff --git a/WorkoutsPlus/Settings.swift b/WorkoutsPlus/Settings.swift deleted file mode 100644 index 45a9390..0000000 --- a/WorkoutsPlus/Settings.swift +++ /dev/null @@ -1,18 +0,0 @@ -// -// Settings.swift -// WorkoutsPlus -// -// Created by Felix Förtsch on 30.08.24. -// - -import SwiftUI - -struct Settings: View { - var body: some View { - Text("Settings") - } -} - -#Preview { - Settings() -} diff --git a/WorkoutsPlus/Settings/Settings.swift b/WorkoutsPlus/Settings/Settings.swift new file mode 100644 index 0000000..ba486f9 --- /dev/null +++ b/WorkoutsPlus/Settings/Settings.swift @@ -0,0 +1,44 @@ +// +// Settings.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 30.08.24. +// + +import SwiftUI + +struct Settings: View { + @Default(\.isFirstAppStart) var isFirstAppStart + @Default(\.isOnboarding) var isOnboarding + @Default(\.userId) var userId + @Default(\.reps) var reps + + var body: some View { + List { + Section(header: Text("User")) { + Text(userId) + TextField("name", text: $userId) + } + Section(header: Text("Defaults")) { + StepperListItem(itemName: "Rep Count", itemValue: $reps) + } + Text(String(reps)) + Section(header: Text("Danger Zone")) { + + Toggle(isOn: $isOnboarding) { + Text("isOnboarding") + } + Button("Reset App", role: .destructive, action: resetApp) + } + } + } + + private func resetApp() { + isFirstAppStart = true + isOnboarding = true + } +} + +#Preview { + Settings() +} diff --git a/WorkoutsPlus/Workout/AddWorkout.swift b/WorkoutsPlus/Workout/AddWorkout.swift index 6b9c2db..50f2fd1 100644 --- a/WorkoutsPlus/Workout/AddWorkout.swift +++ b/WorkoutsPlus/Workout/AddWorkout.swift @@ -1,5 +1,5 @@ // -// AddWorkoutView.swift +// AddWorkout.swift // WorkoutsPlus // // Created by Felix Förtsch on 17.08.24. @@ -11,7 +11,7 @@ struct AddWorkout: View { @Environment(\.modelContext) private var modelContext @Environment(\.dismiss) private var dismiss - @Bindable var workout: Workout + @State var workout: Workout var body: some View { Form { diff --git a/WorkoutsPlus/Workout/AddWorkoutItemToWorkout.swift b/WorkoutsPlus/Workout/AddWorkoutItemToWorkout.swift index d046437..10d2e6e 100644 --- a/WorkoutsPlus/Workout/AddWorkoutItemToWorkout.swift +++ b/WorkoutsPlus/Workout/AddWorkoutItemToWorkout.swift @@ -12,54 +12,38 @@ struct AddWorkoutItemToWorkout: View { @Environment(\.modelContext) private var modelContext @Query(sort: \Exercise.name) private var exercises: [Exercise] - @Bindable var workout: Workout + @State var workout: Workout + // TODO: Add (i) Button that allows editing an exercise (maybe requires NavigationStack?) var body: some View { Group { List { Section(header: Text("Utilities")) { - AddExerciseToWorkoutListItem(WorkoutItem(workoutItems: []), workout) + // AddExerciseToWorkoutListItem(WorkoutItem(workoutItems: []), workout) } Section(header: Text("Excersises")) { if !exercises.isEmpty { ForEach(exercises) { exercise in - - AddExerciseToWorkoutListItem(WorkoutItem(from: exercise), workout) - }} else { - ContentUnavailableView { - // TODO: Add Button that allows adding an exercise - Label("No Exercises", systemImage: Exercise.systemImage) + AddItemButton(label: exercise.name) { + let workoutItem = WorkoutItem(from: exercise) + addWorkoutItemtoWorkout(workoutItem) } } + } else { + ContentUnavailableView { + // TODO: Add Button that allows adding an exercise + Label("No Exercises", systemImage: Exercise.systemImage) + } + } } } } } -} - -struct AddExerciseToWorkoutListItem: View { - @Environment(\.modelContext) private var modelContext - var workoutItem: WorkoutItem - var workout: Workout - - init(_ workoutItem: WorkoutItem, _ workout: Workout) { - self.workoutItem = workoutItem - self.workout = workout - } - - var body: some View { - Button(action: { - workout.add(workoutItem: workoutItem) - }) { - HStack { - Text(workoutItem.name) - .foregroundStyle(.black) - Spacer() - Image(systemName: "plus.circle.fill") - .foregroundStyle(.green) - } - } + private func addWorkoutItemtoWorkout(_ workoutItem: WorkoutItem) { + workout.add(workoutItem: workoutItem) + // TODO: Handle saving in a way the user knows when it's saved + // modelContext.save() } } diff --git a/WorkoutsPlus/Workout/WorkoutDetail.swift b/WorkoutsPlus/Workout/WorkoutDetail.swift index 8c4bb62..e4ba050 100644 --- a/WorkoutsPlus/Workout/WorkoutDetail.swift +++ b/WorkoutsPlus/Workout/WorkoutDetail.swift @@ -1,5 +1,5 @@ // -// WorkoutDetailsView.swift +// WorkoutDetail.swift // WorkoutsPlus // // Created by Felix Förtsch on 10.08.24. @@ -12,8 +12,8 @@ struct WorkoutDetail: View { @Environment(\.dismiss) private var dismiss @Environment(\.modelContext) private var modelContext - @Bindable var workout: Workout - @State private var isPresenting = false + @State var workout: Workout + @State private var isPresentingExerciseLibrary = false var body: some View { @@ -47,18 +47,17 @@ struct WorkoutDetail: View { EditButton() } } - .sheet(isPresented: $isPresenting) { - NavigationStack { - AddWorkoutItemToWorkout(workout: workout) - } - .presentationDetents([.medium, .large]) - .presentationDragIndicator(.visible) + .sheet(isPresented: $isPresentingExerciseLibrary) { + AddWorkoutItemToWorkout(workout: workout) + .presentationDetents([.medium, .large]) + .presentationDragIndicator(.visible) } + } private func addWorkoutItemToWorkout() { withAnimation { - isPresenting = true + isPresentingExerciseLibrary = true } } @@ -92,3 +91,20 @@ struct WorkoutDetail: View { .modelContainer(SampleData.shared.modelContainer) } } + +#Preview("Debug") { + TabView { + WorkoutDetail(workout: Workout.sampleData) + .tabItem { + Image(systemName: "figure.run.square.stack") + Text("Workouts") + } + + DebugList() + .tabItem { + Image(systemName: "hammer") + Text("Debug") + } + } + .modelContainer(SampleData.shared.modelContainer) +} diff --git a/WorkoutsPlus/Workout/WorkoutLibrary.swift b/WorkoutsPlus/Workout/WorkoutLibrary.swift index 88d2a18..4ba3b44 100644 --- a/WorkoutsPlus/Workout/WorkoutLibrary.swift +++ b/WorkoutsPlus/Workout/WorkoutLibrary.swift @@ -1,5 +1,5 @@ // -// WorkoutLibraryView.swift +// WorkoutLibrary.swift // WorkoutsPlus // // Created by Felix Förtsch on 10.08.24.