Add an "End Workout" flow for partially-done workouts
Replace the in-workout "+" toolbar button with an ellipsis menu offering "Add Exercise" and "End Workout". Ending opens a Save/Discard action sheet: Save marks the remaining exercises as skipped and resolves the workout to completed (stamping end), which drops it off the watch's active list and ends the watch's HealthKit session; Discard soft-deletes it. Teach the status-from-logs derivation that a skipped log is terminal, and consolidate the three duplicated copies into a single shared WorkoutDocument.recomputeStatusFromLogs() so an ended workout stays finished regardless of which screen the next edit comes from. Claude-Session: https://claude.ai/code/session_01SCv7zvGFcKy47KSTnTLxRe
This commit is contained in:
@@ -69,6 +69,33 @@ struct WorkoutDocument: Codable, Sendable, Equatable, Identifiable {
|
||||
}
|
||||
}
|
||||
|
||||
extension WorkoutDocument {
|
||||
/// Derive the aggregate `status` + `end` from the current logs. A log that is
|
||||
/// `.completed` or `.skipped` counts as *resolved*; a workout whose logs are all
|
||||
/// resolved is finished (`.completed`, with `end` stamped). This is the single
|
||||
/// source of the status-from-logs rule — every screen that mutates logs calls it,
|
||||
/// so an ended workout (remaining exercises skipped) stays finished no matter which
|
||||
/// screen the next edit comes from.
|
||||
mutating func recomputeStatusFromLogs() {
|
||||
let statuses: [WorkoutStatus] = logs.map { WorkoutStatus(rawValue: $0.status) ?? .notStarted }
|
||||
let isResolved: (WorkoutStatus) -> Bool = { $0 == .completed || $0 == .skipped }
|
||||
|
||||
let allResolved = !statuses.isEmpty && statuses.allSatisfy(isResolved)
|
||||
let anyStarted = statuses.contains { $0 != .notStarted }
|
||||
|
||||
if allResolved {
|
||||
status = WorkoutStatus.completed.rawValue
|
||||
end = Date()
|
||||
} else if anyStarted {
|
||||
status = WorkoutStatus.inProgress.rawValue
|
||||
end = nil
|
||||
} else {
|
||||
status = WorkoutStatus.notStarted.rawValue
|
||||
end = nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WorkoutLogDocument: Codable, Sendable, Equatable, Identifiable {
|
||||
var id: String // ULID
|
||||
var exerciseName: String
|
||||
|
||||
Reference in New Issue
Block a user