diff --git a/playwright-report/index.html b/playwright-report/index.html index 41a1a21..aa4c3eb 100644 --- a/playwright-report/index.html +++ b/playwright-report/index.html @@ -82,4 +82,4 @@ Error generating stack: `+n.message+`
- \ No newline at end of file + \ No newline at end of file diff --git a/server/test.db b/server/test.db index 8e3a5e9..e74a3de 100644 Binary files a/server/test.db and b/server/test.db differ diff --git a/specs/gymflow-test-plan.md b/specs/gymflow-test-plan.md index b11b250..c1a0c18 100644 --- a/specs/gymflow-test-plan.md +++ b/specs/gymflow-test-plan.md @@ -565,6 +565,60 @@ Comprehensive test plan for the GymFlow web application, covering authentication **Expected Results:** - Each set is logged with the correct specific metric (Height, Distance, Duration, etc.). +#### 3.16. C. Rest Timer - Manual Edit & Validation + +**File:** `tests/rest-timer.spec.ts` + +**Steps:** + 1. Start a Free Workout (or Quick Log). + 2. Expand the Rest Timer FAB. + 3. Click 'Edit'. + 4. Type '90' -> Verify '1:30' (if auto-format implemented) or manual '1:30'. + 5. Attempt to type non-digits -> Verify they are ignored. + 6. Attempt to type '10:99' (invalid seconds) -> Verify it corrects to '10:59'. + 7. Save. + +**Expected Results:** + - Input field accepts only valid characters. + - Seconds are clamped to 59. + - Timer value updates correctly upon save. + +#### 3.17. C. Rest Timer - Context & Persistence + +**File:** `tests/rest-timer.spec.ts` + +**Steps:** + 1. Start a Free Workout (Idle Timer defaults to 2:00 or user profile setting). + 2. Edit timer to '0:45'. + 3. Start timer. + 4. Quit session (or navigate to Quick Log). + 5. Start Quick Log (or new Free Session). + 6. Verify timer default is now '0:45'. + +**Expected Results:** + - Timer value persists across different session modes (active to sporadic). + - Last manually set value becomes the new default for manual modes. + +#### 3.18. C. Rest Timer - Plan Integration + +**File:** `tests/rest-timer.spec.ts` + +**Steps:** + 1. Create a Plan with Step A (Rest: 30s) and Step B (Rest: 60s). + 2. Start the Plan. + 3. Verify Timer shows '0:30'. Start it. + 4. Log Set for Step A while timer is running. + 5. Verify Timer continues running (does not reset). + 6. Reset Timer manually (or wait for finish). + 7. Verify Timer now shows '1:00' (for Step B). + +**Expected Results:** + - Timer accurately reflects specific rest times per step. + - Active timer is NOT interrupted by logging sets (smart non-reset). + - Timer updates duration to next step's rest time once idle/reset, but remains PAUSED/IDLE (does not auto-start). + + + ### 4. IV. Data & Progress diff --git a/specs/requirements.md b/specs/requirements.md index 47e8d48..f9a849b 100644 --- a/specs/requirements.md +++ b/specs/requirements.md @@ -110,10 +110,15 @@ The core feature. States: **Idle**, **Active Session**, **Sporadic Mode**. * **Persistence**: The last manually set value becomes the new default for the user. * **Planned Session**: * **Config**: Each step in a plan can have a specific `restTime` (seconds). - * **Auto-Set**: When a set is logged, the timer resets to the value defined for the *current* step. + * **Auto-Set**: When a set is logged, the timer RESETS (updates duration) to the value defined for the *current* step, but does **NOT** start automatically. * **Fallback**: If plan step has no `restTime`, use User's default. * **Behavior**: - * **Start**: Manual trigger by user. + * **Start**: Manual trigger by user (NEVER auto-starts). + * **Edit Value**: + * **Input**: Manual entry via FAB expand menu. + * **Format**: Strict "MM:SS" format (digits and colon only). + * **Constraints**: Max value `99:59`. Seconds > 59 are automatically clamped to 59. + * **Alignment**: Digits are right-aligned; input width is fixed to tightly fit `00:00`. * **Countdown**: Visual display. * **Completion**: * Audio signal (3 seconds). diff --git a/src/components/Tracker/ActiveSessionView.tsx b/src/components/Tracker/ActiveSessionView.tsx index 05c831e..de206b7 100644 --- a/src/components/Tracker/ActiveSessionView.tsx +++ b/src/components/Tracker/ActiveSessionView.tsx @@ -110,7 +110,7 @@ const ActiveSessionView: React.FC = ({ tracker, activeSe if (timer.status !== 'RUNNING') { timer.reset(nextTime); - timer.start(); + // timer.start(); // Removed per user request: disable auto-start } }; diff --git a/src/components/Tracker/SporadicView.tsx b/src/components/Tracker/SporadicView.tsx index 6b93844..1310af3 100644 --- a/src/components/Tracker/SporadicView.tsx +++ b/src/components/Tracker/SporadicView.tsx @@ -38,7 +38,7 @@ const SporadicView: React.FC = ({ tracker, lang }) => { const handleLogSet = async () => { await handleLogSporadicSet(); // Always usage default/current setting for sporadic - timer.start(); + // timer.start(); // Removed per user request: disable auto-start }; const handleDurationChange = async (newVal: number) => { diff --git a/src/components/ui/RestTimerFAB.tsx b/src/components/ui/RestTimerFAB.tsx index a1ddbb7..fe0b9a4 100644 --- a/src/components/ui/RestTimerFAB.tsx +++ b/src/components/ui/RestTimerFAB.tsx @@ -139,22 +139,53 @@ const RestTimerFAB: React.FC = ({ timer, onDurationChange }) {/* Manual Input Field */} -
+
setInputValue(e.target.value)} + onChange={(e) => { + let val = e.target.value; + + // Filter non-digits and non-colon + val = val.replace(/[^0-9:]/g, ''); + + // Limit length to 5 + if (val.length > 5) { + val = val.substring(0, 5); + } + + // Validate Seconds part if colon exists + if (val.includes(':')) { + const parts = val.split(':'); + if (parts.length > 1) { + const minutes = parts[0]; + let seconds = parts[1]; + + // Clamp seconds to 59 + if (seconds.length > 0) { + const secNum = parseInt(seconds, 10); + if (!isNaN(secNum) && secNum > 59) { + seconds = '59'; + } + } + val = `${minutes}:${seconds}`; + } + } + + setInputValue(val); + }} onFocus={(e) => e.target.select()} onBlur={handleInputBlur} onKeyDown={(e) => { if (e.key === 'Enter') e.currentTarget.blur(); }} + placeholder="00:00" />
- +
) : (
@@ -177,8 +208,8 @@ const RestTimerFAB: React.FC = ({ timer, onDurationChange })