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:
@@ -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
|
||||
Reference in New Issue
Block a user