# 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