Skip to content

fix: guard against no-phase programs in timer screen#11

Open
nbucic wants to merge 1 commit intomasterfrom
fix/timer-loading
Open

fix: guard against no-phase programs in timer screen#11
nbucic wants to merge 1 commit intomasterfrom
fix/timer-loading

Conversation

@nbucic
Copy link
Copy Markdown
Owner

@nbucic nbucic commented Apr 14, 2026

Root cause

When a program exists but has no phases yet:

  • Program::totalDuration() returns 0programTotalDuration = 0
  • TimerRunner::start() throws RuntimeException("Program has no phases.") — Livewire silently rolls back the response, so the UI never transitions out of idle and the Start button appears to do nothing

This happens when a user creates a program but navigates to the timer screen before adding any phases.

Changes

TimerScreen::start() — guard against empty phases

Instead of letting TimerRunner::start() throw a RuntimeException (silently swallowed by Livewire), start() now returns early when phases are empty. State is left untouched so the blade can render the "no phases" notice.

timer-screen.blade.php — no-phases notice

When the timer is idle and $phases is empty, the Start button is replaced with an amber warning:

"No phases — edit this program to add at least one phase before starting."

The Edit button in the secondary row remains visible so the user can fix the program immediately.

ProgramEditor::totalDuration() — match timer behaviour

The editor's preview summed every phase's cooldown, including the last phase. But the timer skips the last phase's cooldown (goes straight to COMPLETED after the final rep). This made the preview total higher than the actual run duration for any program with a last-phase cooldown. Fixed to subtract the last phase's cooldown, matching Program::totalDuration().

Test plan

  • Open a program with no phases → timer screen shows amber "No phases" notice; no Start button
  • Click Edit from that screen, add a phase, save → redirected to timer, Start button visible
  • Start a program with phases → 5-second PREPARE countdown plays, timer counts down correctly
  • Open the program editor on a program whose last phase has a non-zero cooldown → preview total matches the actual timer run (last cooldown excluded)

https://claude.ai/code/session_01GWCpmWmmUb8R1EE23kC29k

Root cause: when a program exists but has no phases yet,
`Program::totalDuration()` returns 0 (programTotalDuration = 0) and
`TimerRunner::start()` throws RuntimeException("Program has no phases.").
Livewire silently rolls back the response, so the UI never transitions
out of idle — the Start button appears to do nothing.

Changes:

- `TimerScreen::start()`: return early when phases are empty; avoids the
  unhandled exception and leaves the idle state intact so the user can
  still navigate to the editor.

- `timer-screen.blade.php`: replace the Start button with an amber
  warning notice ("No phases — edit this program…") when `$phases` is
  empty and state is idle, so the user immediately understands why the
  timer cannot start.

- `ProgramEditor::totalDuration()`: add an empty-phases guard (returns 0)
  and subtract the last phase's cooldown, matching `Program::totalDuration()`
  which already skips it (the timer goes straight to COMPLETED after the
  final rep, never entering the last cooldown).

https://claude.ai/code/session_01GWCpmWmmUb8R1EE23kC29k
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.

2 participants