04-06: Plan persistence improvements and implement draft persistence

- Created 04-06-PLAN.md outlining persistence improvements phases
- Phase 04-06-01: Draft persistence via localStorage
  - Added useDraftWorkout hook for auto-saving/loading drafts
  - Integrated hook into WorkoutEditPage
  - Added draft recovery prompt UI
  - Drafts cleared after successful save
- Phase 04-06-02: Save error handling & retry (scaffolding)
  - Added error state and syncStatus tracking
  - Added handleRetry() for failed saves
  - Error banner with retry button
- Phase 04-06-03: Sync status UI (scaffolding)
  - Added visual feedback for save progress
  - Status indicators: saving, saved, error
  - Disabled UI during save to prevent conflicts
- Created comprehensive styles for new UI components

Status: 04-06-01 complete and integrated. Ready for testing.
This commit is contained in:
2026-03-02 00:51:11 +01:00
parent b553fa83b4
commit c14d882580
4 changed files with 733 additions and 10 deletions
@@ -0,0 +1,105 @@
# Phase 04-06: Persistence Improvements
**Goal:** Make custom workout modifications resilient to network failures, browser crashes, and session interruptions. Users should never lose edits.
## Problem Statement
Currently, users can modify program workouts and fork them as custom workouts (phases 04-01 through 04-05). However:
- Edits are stored only in React state; closing the browser loses all changes
- Network failures during save have no recovery mechanism (hard failure)
- No indication of sync status or unsaved changes
- No offline support for draft modifications
This creates friction: users may spend time modifying a workout only to have changes disappear.
## Solution: Persistence Layer
We'll implement a three-tier approach:
1. **Draft Persistence** (localStorage) - auto-save edits locally, recover on page reload
2. **Error Recovery** (retry logic) - graceful handling of network failures with user-triggered retry
3. **Sync Status UI** (feedback) - show "unsaved", "saving", "saved", "error" states
## Scope (MVP)
### 04-06-01: Draft Persistence
**Focus:** Save workout edit state to localStorage; restore on page load
**Tasks:**
1. Add custom React hook `useDraftWorkout()` that:
- Syncs exercise state to localStorage after each change
- Loads draft on component mount
- Provides `clearDraft()` for post-save cleanup
- Keys draft by `workout.id` to support multiple concurrent edits
2. Update WorkoutEditPage to use `useDraftWorkout()`
3. Show draft recovery prompt on mount if draft exists
4. Clear draft after successful save
**Success Criteria:**
- [ ] User modifies a workout, closes browser, reopens page → edits are recovered
- [ ] Draft is cleared after successful save
- [ ] Manual "clear draft" option in UI (if user wants to discard changes)
### 04-06-02: Save Error Handling & Retry
**Focus:** Graceful failure + user-controlled retry
**Tasks:**
1. Wrap `handleSave` in try-catch with specific error handling:
- Network errors → show "Connection failed. Retry?" UI
- Validation errors → show specific field errors
- Server errors → show "Server error. Please try again" UI
2. Add `handleRetry()` to re-attempt last failed save
3. Update save button to show states: `Spara``Sparar...``Sparat!` (2s) → `Spara`
4. Show persistent error banner if save fails
5. Log errors for debugging
**Success Criteria:**
- [ ] Network failure during save shows retry option (not hard crash)
- [ ] User can click retry; attempt re-sends
- [ ] Save state is clearly indicated (saving, saved, error)
- [ ] Draft is NOT cleared if save fails
### 04-06-03: Sync Status & Visual Feedback
**Focus:** Users always know if changes are saved
**Tasks:**
1. Add sync status to WorkoutEditPage state: `syncStatus` = 'idle' | 'saving' | 'saved' | 'error'
2. Show status indicator in header:
- `Sparar...` (gray spinner) while saving
- `✓ Sparat` (green) for 2s after success
- `✗ Sparningsfel` (red) if failed
3. Auto-hide error after 5s or on next change
4. Disable back/cancel buttons while saving
**Success Criteria:**
- [ ] User sees real-time feedback of save progress
- [ ] Users cannot accidentally navigate away during save
## Success Criteria (Phase Level)
- [ ] Edits survive browser reload (draft persistence)
- [ ] Network failures are recoverable (retry logic)
- [ ] Users always know sync status (UI feedback)
- [ ] Draft is auto-cleared post-save
- [ ] Error states have clear recovery paths
## Files to Modify/Create
**New:**
- `frontend/src/hooks/useDraftWorkout.js` - Draft persistence hook
**Modified:**
- `frontend/src/pages/WorkoutEditPage.jsx` - Use draft hook, add error handling, show sync status
- `frontend/src/pages/WorkoutEditPage.css` - Add status indicator styles (spinner, checkmark, error)
## Implementation Order
1. Start with 04-06-01 (draft persistence) — simplest, highest value
2. Then 04-06-02 (error recovery) — integrates with draft
3. Then 04-06-03 (UI feedback) — polish and completeness
## Out of Scope
- Offline queue (sync when reconnected) — v2 feature
- Conflict resolution (concurrent edits) — v2 feature
- Analytics/telemetry — v2 feature
- Undo/redo — v2 feature