Show only the day's docket on the Today board and add ad hoc Now workouts
- Due-filter schedules: daily always, fixed days by weekday, one-offs on their date; rest days get an empty state - Workouts with no due schedule row (ad hoc or off-day starts) now render as their own board rows - The + sheet is now "New Workout" with a "When" picker; "Now" (offered when adding on today) skips the schedule and starts the workout directly - Remove the times-per-week scheduling mode everywhere (enum, document, entity, mappers, planner, seeds, tests)
This commit is contained in:
@@ -24,7 +24,6 @@ struct ScheduleFacts: Sendable, Equatable {
|
||||
var goal: GoalKind?
|
||||
var recurrence: ScheduleRecurrence
|
||||
var weekdays: [Int]? // Calendar weekday numbers 1 (Sun) – 7 (Sat); .fixedDays only
|
||||
var timesPerWeek: Int? // .frequency only
|
||||
var onceDate: Date? // .once only
|
||||
var createdAt: Date
|
||||
var routineID: String // live-resolved
|
||||
@@ -69,8 +68,8 @@ struct WeekMark: Sendable, Equatable {
|
||||
struct ScheduleTrack: Sendable, Equatable {
|
||||
var schedule: ScheduleFacts
|
||||
var weeks: [WeekMark?]
|
||||
/// The current week can no longer be met (a daily's missed day, too few days left
|
||||
/// for the remaining frequency count). Distinct from "not yet hit".
|
||||
/// The current week can no longer be met (a daily's missed day, or too few days
|
||||
/// left to cover a fixed day already missed). Distinct from "not yet hit".
|
||||
var currentWeekBroken: Bool
|
||||
|
||||
var currentWeek: WeekMark? { weeks.last ?? nil }
|
||||
@@ -224,8 +223,6 @@ enum ProgressPlanner {
|
||||
/// - `.daily` / `.fixedDays`: expected counts only required days **up to today**;
|
||||
/// met counts distinct completed days in that same window (so a Tuesday make-up
|
||||
/// for a missed fixed Monday still counts — catch-ups are honored).
|
||||
/// - `.frequency`: expected is the full weekly target (clamped to the days the
|
||||
/// schedule existed that week); mid-week it reads "1 of 2" until actually met.
|
||||
/// - `.once`: expected 1, only in the week containing its date.
|
||||
static func weekMark(
|
||||
schedule: ScheduleFacts,
|
||||
@@ -248,9 +245,6 @@ enum ProgressPlanner {
|
||||
let required = window.elapsedDays
|
||||
.filter { wanted.contains(calendar.component(.weekday, from: $0)) }.count
|
||||
return WeekMark(weekStart: weekStart, met: min(done, required), expected: required)
|
||||
case .frequency:
|
||||
let target = min(max(schedule.timesPerWeek ?? 0, 0), window.fullDays.count)
|
||||
return WeekMark(weekStart: weekStart, met: min(done, target), expected: target)
|
||||
case .once:
|
||||
guard let once = schedule.onceDate,
|
||||
calendar.dateInterval(of: .weekOfYear, for: once)?.start == weekStart
|
||||
@@ -261,7 +255,7 @@ enum ProgressPlanner {
|
||||
|
||||
/// True when the current week can no longer be met: the days remaining (today
|
||||
/// included) are fewer than the requirement still outstanding. A daily's missed
|
||||
/// yesterday breaks immediately; a 2×/week with one done and two days left doesn't.
|
||||
/// yesterday breaks immediately; fixed days with catch-up days still left don't.
|
||||
static func currentWeekBroken(
|
||||
schedule: ScheduleFacts,
|
||||
doneDays: Set<Date>,
|
||||
@@ -285,8 +279,6 @@ enum ProgressPlanner {
|
||||
let wanted = Set(schedule.weekdays ?? [])
|
||||
fullRequirement = window.fullDays
|
||||
.filter { wanted.contains(calendar.component(.weekday, from: $0)) }.count
|
||||
case .frequency:
|
||||
fullRequirement = min(max(schedule.timesPerWeek ?? 0, 0), window.fullDays.count)
|
||||
case .once:
|
||||
guard let once = schedule.onceDate,
|
||||
calendar.dateInterval(of: .weekOfYear, for: once)?.start == weekStart
|
||||
|
||||
Reference in New Issue
Block a user