wip
This commit is contained in:
@ -22,44 +22,38 @@ struct SplitPickerView: View {
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
VStack {
|
||||
Form {
|
||||
Section (header: Text("This Split")) {
|
||||
List {
|
||||
ForEach(splits) { split in
|
||||
Button(action: {
|
||||
onSplitSelected(split)
|
||||
dismiss()
|
||||
}) {
|
||||
HStack {
|
||||
Text(split.name)
|
||||
.font(.headline)
|
||||
Spacer()
|
||||
Text("\(split.exercises?.count ?? 0)")
|
||||
.font(.caption)
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
ScrollView {
|
||||
LazyVGrid(columns: [GridItem(.flexible()), GridItem(.flexible())], spacing: 16) {
|
||||
ForEach(splits) { split in
|
||||
Button(action: {
|
||||
onSplitSelected(split)
|
||||
dismiss()
|
||||
}) {
|
||||
VStack {
|
||||
ZStack {
|
||||
RoundedRectangle(cornerRadius: 12)
|
||||
.fill(split.getColor())
|
||||
.aspectRatio(1, contentMode: .fit)
|
||||
.shadow(radius: 2)
|
||||
|
||||
Image(systemName: split.systemImage)
|
||||
.font(.system(size: 30))
|
||||
.foregroundColor(.white)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
|
||||
Text(split.name)
|
||||
.font(.headline)
|
||||
.lineLimit(1)
|
||||
|
||||
Text("\(split.exercises?.count ?? 0) exercises")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
}
|
||||
|
||||
// Section (header: Text("Additional Exercises")) {
|
||||
// List {
|
||||
// ForEach(exercises) { exercise in
|
||||
// Button(action: {
|
||||
// onExerciseSelected(exercise)
|
||||
// dismiss()
|
||||
// }) {
|
||||
// Text(exercise.name)
|
||||
// }
|
||||
// .contentShape(Rectangle())
|
||||
// .buttonStyle(.plain)
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .navigationBarLeading) {
|
||||
|
@ -8,6 +8,7 @@
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import SwiftData
|
||||
|
||||
struct WorkoutLogView: View {
|
||||
@Environment(\.modelContext) private var modelContext
|
||||
@ -21,7 +22,7 @@ struct WorkoutLogView: View {
|
||||
var sortedWorkoutLogs: [WorkoutLog] {
|
||||
if let logs = workout.logs {
|
||||
logs.sorted(by: {
|
||||
$0.completed == $1.completed ? $0.exercise!.name < $1.exercise!.name : !$0.completed
|
||||
$0.order == $1.order ? $0.exercise!.name < $1.exercise!.name : $0.order < $1.order
|
||||
})
|
||||
} else {
|
||||
[]
|
||||
@ -33,33 +34,54 @@ struct WorkoutLogView: View {
|
||||
Section (header: Text("\(workout.label)")) {
|
||||
List {
|
||||
ForEach (sortedWorkoutLogs) { log in
|
||||
let badges = log.completed ? [Badge(text: "Completed", color: .green)] : []
|
||||
ListItem(
|
||||
title: log.exercise?.name ?? "Untitled Exercise",
|
||||
subtitle: "\(log.sets) sets × \(log.reps) reps × \(log.weight) lbs",
|
||||
badges: badges
|
||||
// Handle optional status, defaulting to a status based on completed flag if nil
|
||||
let _ = print("DEBUG: workoutLog.status=\(log.status)")
|
||||
|
||||
let workoutLogStatus = log.status?.checkboxStatus ?? (log.completed ? CheckboxStatus.checked : CheckboxStatus.unchecked)
|
||||
|
||||
CheckboxListItem(
|
||||
status: workoutLogStatus,
|
||||
title: log.exercise?.name ?? Exercise.unnamed,
|
||||
subtitle: "\(log.sets) sets × \(log.reps) reps × \(log.weight) lbs"
|
||||
)
|
||||
|
||||
.swipeActions(edge: .leading, allowsFullSwipe: false) {
|
||||
if (log.completed) {
|
||||
let status = log.status ?? WorkoutStatus.notStarted
|
||||
|
||||
if [.inProgress,.completed].contains(status) {
|
||||
Button {
|
||||
withAnimation {
|
||||
log.completed = false
|
||||
log.status = .notStarted
|
||||
try? modelContext.save()
|
||||
}
|
||||
} label: {
|
||||
Label("Complete", systemImage: "circle.fill")
|
||||
Label("Not Started", systemImage: WorkoutStatus.notStarted.checkboxStatus.systemName)
|
||||
}
|
||||
.tint(.green)
|
||||
} else {
|
||||
.tint(WorkoutStatus.notStarted.checkboxStatus.color)
|
||||
}
|
||||
|
||||
if [.notStarted,.completed].contains(status) {
|
||||
Button {
|
||||
withAnimation {
|
||||
log.completed = true
|
||||
log.status = .inProgress
|
||||
try? modelContext.save()
|
||||
}
|
||||
} label: {
|
||||
Label("Reset", systemImage: "checkmark.circle.fill")
|
||||
Label("In Progress", systemImage: WorkoutStatus.inProgress.checkboxStatus.systemName)
|
||||
}
|
||||
.tint(.green)
|
||||
.tint(WorkoutStatus.inProgress.checkboxStatus.color)
|
||||
}
|
||||
|
||||
if [.notStarted,.inProgress].contains(status) {
|
||||
Button {
|
||||
withAnimation {
|
||||
log.status = .completed
|
||||
try? modelContext.save()
|
||||
}
|
||||
} label: {
|
||||
Label("Complete", systemImage: WorkoutStatus.completed.checkboxStatus.systemName)
|
||||
}
|
||||
.tint(WorkoutStatus.completed.checkboxStatus.color)
|
||||
}
|
||||
}
|
||||
.swipeActions(edge: .trailing, allowsFullSwipe: false) {
|
||||
@ -89,13 +111,14 @@ struct WorkoutLogView: View {
|
||||
}
|
||||
.sheet(isPresented: $showingAddSheet) {
|
||||
ExercisePickerView { exercise in
|
||||
let setsRepsWeight = getSetsRepsWeight(exercise, in: modelContext)
|
||||
let workoutLog = WorkoutLog(
|
||||
workout: workout,
|
||||
exercise: exercise,
|
||||
date: Date(),
|
||||
sets: exercise.sets,
|
||||
reps: exercise.reps,
|
||||
weight: exercise.weight,
|
||||
sets: setsRepsWeight.sets,
|
||||
reps: setsRepsWeight.reps,
|
||||
weight: setsRepsWeight.weight,
|
||||
completed: false
|
||||
)
|
||||
workout.logs?.append(workoutLog)
|
||||
@ -130,4 +153,34 @@ struct WorkoutLogView: View {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func getSetsRepsWeight(_ exercise: Exercise, in modelContext: ModelContext) -> SetsRepsWeight {
|
||||
// Use a single expression predicate that works with SwiftData
|
||||
let exerciseID = exercise.persistentModelID
|
||||
|
||||
print("Searching for exercise ID: \(exerciseID)")
|
||||
|
||||
var descriptor = FetchDescriptor<WorkoutLog>(
|
||||
predicate: #Predicate<WorkoutLog> { log in
|
||||
log.exercise?.persistentModelID == exerciseID
|
||||
},
|
||||
sortBy: [SortDescriptor(\WorkoutLog.date, order: .reverse)]
|
||||
)
|
||||
|
||||
descriptor.fetchLimit = 1
|
||||
|
||||
let results = try? modelContext.fetch(descriptor)
|
||||
|
||||
if let log = results?.first {
|
||||
return SetsRepsWeight(sets: log.sets, reps: log.reps, weight: log.weight)
|
||||
} else {
|
||||
return SetsRepsWeight(sets: 3, reps: 10, weight: 40)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SetsRepsWeight {
|
||||
let sets: Int
|
||||
let reps: Int
|
||||
let weight: Int
|
||||
}
|
||||
|
@ -100,10 +100,10 @@ struct WorkoutsView: View {
|
||||
workout: workout,
|
||||
exercise: exercise,
|
||||
date: Date(),
|
||||
order: assignment.order,
|
||||
sets: assignment.sets,
|
||||
reps: assignment.reps,
|
||||
weight: assignment.weight,
|
||||
completed: false
|
||||
weight: assignment.weight
|
||||
)
|
||||
modelContext.insert(workoutLog)
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user