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 cf85e9e314
commit 475cf10b17
3 changed files with 628 additions and 10 deletions
+65
View File
@@ -0,0 +1,65 @@
import { useEffect, useState } from 'react'
/**
* useDraftWorkout - Manages draft workout state with localStorage persistence
*
* @param {number} workoutId - Unique workout ID (used as localStorage key)
* @param {array} initialExercises - Initial exercise list
* @returns {object} { exercises, setExercises, clearDraft, hasDraft, restoreDraft }
*/
export function useDraftWorkout(workoutId, initialExercises = []) {
const [exercises, setExercises] = useState(initialExercises)
const [hasDraft, setHasDraft] = useState(false)
const draftKey = `workout-draft-${workoutId}`
// Load draft from localStorage on mount
useEffect(() => {
const saved = localStorage.getItem(draftKey)
if (saved) {
try {
const draft = JSON.parse(saved)
setExercises(draft)
setHasDraft(true)
} catch (err) {
console.error('Failed to parse draft:', err)
localStorage.removeItem(draftKey) // Clear corrupted draft
}
}
}, [workoutId, draftKey])
// Auto-save to localStorage whenever exercises change
useEffect(() => {
if (exercises.length > 0) {
localStorage.setItem(draftKey, JSON.stringify(exercises))
}
}, [exercises, draftKey])
const clearDraft = () => {
localStorage.removeItem(draftKey)
setHasDraft(false)
}
const restoreDraft = () => {
const saved = localStorage.getItem(draftKey)
if (saved) {
try {
const draft = JSON.parse(saved)
setExercises(draft)
return true
} catch (err) {
console.error('Failed to restore draft:', err)
return false
}
}
return false
}
return {
exercises,
setExercises,
clearDraft,
hasDraft,
restoreDraft
}
}