add template for items, copy over exercise library

This commit is contained in:
Felix Förtsch
2024-08-13 00:52:55 +02:00
parent ec2a7c15c7
commit e33f9e80bc
8 changed files with 229 additions and 17 deletions

View File

@@ -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)
}

View File

@@ -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
}
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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)
}