diff --git a/WorkoutsPlus/ContentView.swift b/WorkoutsPlus/ContentView.swift new file mode 100644 index 0000000..6ee68f7 --- /dev/null +++ b/WorkoutsPlus/ContentView.swift @@ -0,0 +1,33 @@ +// +// ContentView.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 13.08.24. +// + +import SwiftUI +import SwiftData + +struct ContentView: View { + @Environment(\.modelContext) private var modelContext + + var body: some View { + TabView { + ExerciseLibraryView() + .tabItem { + Image(systemName: "figure.run.square.stack") + Text("Library") + } + Text("Settings") + .tabItem { + Image(systemName: "gear") + Text("Settings") + } + } + } +} + +#Preview { + ContentView() + .modelContainer(for: Exercise.self, inMemory: true) +} diff --git a/WorkoutsPlus/Exercise.swift b/WorkoutsPlus/Exercise.swift new file mode 100644 index 0000000..5e7eb4d --- /dev/null +++ b/WorkoutsPlus/Exercise.swift @@ -0,0 +1,20 @@ +// +// Item.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 10.08.24. +// + +import Foundation +import SwiftData + +@Model +final class Exercise { + var name: String + var timestamp: Date + + init(name: String = "", timestamp: Date = Date.now) { + self.name = name + self.timestamp = timestamp + } +} diff --git a/WorkoutsPlus/ExerciseDetailsView.swift b/WorkoutsPlus/ExerciseDetailsView.swift new file mode 100644 index 0000000..e4a5dce --- /dev/null +++ b/WorkoutsPlus/ExerciseDetailsView.swift @@ -0,0 +1,60 @@ +// +// ExerciseDetailsView.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 10.08.24. +// + +import SwiftUI + +struct ExerciseDetailsView: View { + @Environment(\.dismiss) private var dismiss + @Environment(\.modelContext) private var modelContext + + var item: Exercise? + var isPresentedAsSheet: Bool = false + + var body: some View { + + Form { + TextField("Exercise Name", text: Binding( + get: { item?.name ?? "" }, + set: { newName in + if item != nil { + item?.name = newName + } + } + )) + .toolbar { + if (isPresentedAsSheet) { + ToolbarItem(placement: .topBarLeading) { + Button("Cancel") { + dismiss() + } + } + } + ToolbarItem(placement: .topBarTrailing) { + Button("Save") { + saveItem() + dismiss() + } + } + } + } + } + + private func saveItem() { + if modelContext.hasChanges { + do { + try modelContext.save() + } catch { + print("Failed to save item: \(error.localizedDescription)") + } + } + } +} + +#Preview { + let sampleItem = Exercise(name: "Sample Item") + ExerciseDetailsView(item: sampleItem) +} diff --git a/WorkoutsPlus/ExerciseLibraryView.swift b/WorkoutsPlus/ExerciseLibraryView.swift new file mode 100644 index 0000000..9be6a3d --- /dev/null +++ b/WorkoutsPlus/ExerciseLibraryView.swift @@ -0,0 +1,100 @@ +// +// ExerciseLibraryView.swift +// WorkoutsPlus +// +// Created by Felix Förtsch on 10.08.24. +// + +import SwiftUI +import SwiftData + +struct ExerciseLibraryView: View { + @Environment(\.modelContext) private var modelContext + @Query private var items: [Exercise] + + @State private var isPresentingNewItemSheet = false + + let initialDataSet = [ + "Pull-up", + "Push-up", + "Dips", + "Rows", + "Split Squat" + ] + + var body: some View { + NavigationView { + List { + ForEach(items.sorted(by: { $0.name < $1.name })) { item in + NavigationLink(destination: ExerciseDetailsView(item: item)) { + Text(item.name) + } + } + .onDelete(perform: deleteExercise) + } + .onAppear { + if items.isEmpty { + loadInitialData(exercises: initialDataSet) + } + } + .toolbar { + ToolbarItem(placement: .navigationBarTrailing) { + Button { + createNewExercise() + } label: { + Label("Add Exercise", systemImage: "plus") + } + } + } + .sheet(isPresented: $isPresentingNewItemSheet) { + let newItem = Exercise(name: "") + NavigationView { + ExerciseDetailsView(item: newItem, isPresentedAsSheet: true) + .onDisappear { + if !newItem.name.isEmpty { + saveExercise(item: newItem) + } + } + } + } + } + } + + private func createNewExercise() { + isPresentingNewItemSheet = true + } + + private func saveExercise(item: Exercise) { + modelContext.insert(item) + try? modelContext.save() + } + + private func deleteExercise(offsets: IndexSet) { + withAnimation { + for index in offsets { + modelContext.delete(items[index]) + } + try? modelContext.save() + } + } + + private func loadInitialData(exercises: [String]) { + var items: [Exercise] = [] + + for exercise in exercises { + let item = Exercise(name: exercise) + items.append(item) + } + + for item in items { + modelContext.insert(item) + } + + try? modelContext.save() + } +} + +#Preview { + ExerciseLibraryView() + .modelContainer(for: Exercise.self, inMemory: true) +} diff --git a/WorkoutsPlus/Item.swift b/WorkoutsPlus/Templates/Item.swift similarity index 100% rename from WorkoutsPlus/Item.swift rename to WorkoutsPlus/Templates/Item.swift diff --git a/WorkoutsPlus/ItemDetailsView.swift b/WorkoutsPlus/Templates/ItemDetailsView.swift similarity index 69% rename from WorkoutsPlus/ItemDetailsView.swift rename to WorkoutsPlus/Templates/ItemDetailsView.swift index 2783370..25a1d1e 100644 --- a/WorkoutsPlus/ItemDetailsView.swift +++ b/WorkoutsPlus/Templates/ItemDetailsView.swift @@ -15,16 +15,16 @@ struct ItemDetailsView: View { var isPresentedAsSheet: Bool = false var body: some View { - - Form { - TextField("Exercise Name", text: Binding( - get: { item?.name ?? "" }, - set: { newName in - if item != nil { - item?.name = newName - } + + Form { + TextField("Exercise Name", text: Binding( + get: { item?.name ?? "" }, + set: { newName in + if item != nil { + item?.name = newName } - )) + } + )) .toolbar { if (isPresentedAsSheet) { ToolbarItem(placement: .topBarLeading) { @@ -54,9 +54,8 @@ struct ItemDetailsView: View { } } -struct ExerciseDetailsView_Previews: PreviewProvider { - static var previews: some View { - let sampleItem = Item(name: "Sample Item") - ItemDetailsView(item: sampleItem) - } +#Preview { + let sampleItem = Item(name: "Sample Item") + ItemDetailsView(item: sampleItem) } + diff --git a/WorkoutsPlus/ItemLibrary.swift b/WorkoutsPlus/Templates/ItemLibrary.swift similarity index 96% rename from WorkoutsPlus/ItemLibrary.swift rename to WorkoutsPlus/Templates/ItemLibrary.swift index 01b09c2..327b509 100644 --- a/WorkoutsPlus/ItemLibrary.swift +++ b/WorkoutsPlus/Templates/ItemLibrary.swift @@ -25,7 +25,7 @@ struct ItemLibrary: View { var body: some View { NavigationView { List { - ForEach(items) { item in + ForEach(items.sorted(by: { $0.name < $1.name })) { item in NavigationLink(destination: ItemDetailsView(item: item)) { Text(item.name) } diff --git a/WorkoutsPlus/WorkoutsPlusApp.swift b/WorkoutsPlus/WorkoutsPlusApp.swift index 698d73d..160d464 100644 --- a/WorkoutsPlus/WorkoutsPlusApp.swift +++ b/WorkoutsPlus/WorkoutsPlusApp.swift @@ -12,7 +12,7 @@ import SwiftData struct WorkoutsPlusApp: App { var sharedModelContainer: ModelContainer = { let schema = Schema([ - Item.self, + Exercise.self, ]) let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: false) @@ -25,7 +25,7 @@ struct WorkoutsPlusApp: App { var body: some Scene { WindowGroup { - ItemLibrary() + ContentView() } .modelContainer(sharedModelContainer) }