Skip to content

feat: rule-based on-call scheduling with Schedule tab (#21)#23

Merged
wiseelf merged 11 commits into
mainfrom
feature/rule-based-scheduling
Jun 26, 2026
Merged

feat: rule-based on-call scheduling with Schedule tab (#21)#23
wiseelf merged 11 commits into
mainfrom
feature/rule-based-scheduling

Conversation

@wiseelf

@wiseelf wiseelf commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds RecurrenceRule + ScheduleException models to TimeTrackerCore — supports day-of-week patterns and interval+duration cycles (e.g. every 3 days, 1 week on / 1 week off)
  • New Schedule tab in the on-call view: define a rule, browse a month calendar pre-filled with on-call days, tap any day to skip it or override its hours
  • Billing engine (OnCallBilling) now evaluates rules and exceptions alongside existing rotation blocks; existing callers compile unchanged (new params default to [])
  • OnCallStore persists rules and exceptions with backward-compatible JSON decoding
  • 37 tests pass: 10 RecurrenceRuleTests, 6 RecurrenceBillingTests, 21 existing OnCallBillingTests
  • Fixes bug where reopening the app after clicking outside the settings panel would land on Settings instead of the main page

Follow-up fixes and improvements (post-initial review)

  • Fix: calendar day cells were not tappable — .contentShape(Rectangle()) added to DayCell to make clear-background cells hit-testable
  • Fix: DayDetailPanel was clipped below fold — removed ScrollView/scrollDisabled from ScheduleTab so ContentView's GeometryReader reports natural height and the window auto-expands
  • Feat: global week-start-day setting (weekStartsOnMonday on OnCallSettings); all day-of-week UIs (calendar grid, rule editor, rotation editor, non-billable add row) respect it
  • Feat: inline rate editing in settings — pencil button opens an edit row per entry (date picker + text field + save/cancel)
  • Feat: non-billable add form hidden behind a + toggle button; shown on demand
  • Feat: passive/active multiplier fields replaced with free-form TextField (commit on blur/return, validated 0–200%, @FocusState for blur detection)

New files

  • Sources/TimeTrackerCore/RecurrenceModels.swift
  • Sources/TimeTracker/RuleEditSheet.swift
  • Sources/TimeTracker/OnCallCalendarGrid.swift
  • Sources/TimeTracker/ScheduleTab.swift
  • Tests/TimeTrackerTests/RecurrenceRuleTests.swift
  • Tests/TimeTrackerTests/RecurrenceBillingTests.swift
  • docs/adr/0001-schedule-tab-for-rule-based-on-call.md

Test plan

  • swift test — all 37 tests pass
  • swift build clean
  • On-call tab shows Week / Month / Schedule segments
  • Schedule tab: + button → Add Rule sheet (day-of-week and interval modes, day toggles, time pickers, anchor/end date)
  • Saving a rule shows it in the rule row; calendar highlights generated days
  • Tap a highlighted day → detail panel opens (window auto-expands); on-call toggle + time pickers work
  • Toggle off adds skip exception (day un-highlights); toggle back removes exception
  • Edit hours → "Reset to rule defaults" appears; clicking restores rule times
  • Week/Month tabs keep independent offsets; summaries include rule-generated days in totals
  • Settings: toggle "Week starts on Monday" → all day pickers reorder (calendar headers, rule editor, rotation editor, non-billable form)
  • Settings: pencil on rate entry → inline edit; save updates the entry
  • Settings: + next to "Non-billable window" shows/hides add form
  • Settings: type a value like "41" or "92" into passive/active field → committed on blur/return
  • Reopen app after clicking outside → lands on main page (not Settings)

wiseelf added 11 commits June 27, 2026 09:12
…uto-expand

- Add weekStartsOnMonday to OnCallSettings with orderedWeekdays helper
- Fix DayCell not tappable: add .contentShape(Rectangle()) for clear-bg cells
- Remove ScrollView from ScheduleTab so panel auto-expands via ContentView geometry
- Propagate weekStartsOnMonday to OnCallCalendarGrid, RuleEditSheet, ScheduleRowEditor
…ltiplier fields

- Rate history: pencil button → inline edit row (DatePicker + TextField + Save/cancel)
- Non-billable section: hide AddNonBillableRuleRow behind + toggle button
- Replace Stepper multiplier rows with MultiplierField (TextField + FocusState commit)
- AddNonBillableRuleRow uses orderedWeekdays from settings
@wiseelf wiseelf merged commit 73a1305 into main Jun 26, 2026
@wiseelf wiseelf deleted the feature/rule-based-scheduling branch June 28, 2026 00:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant