{workout.name}
{exercises.length} övningar
import { useState } from 'react' import { Icon } from '../components/Icons' import ExercisePicker from '../components/ExercisePicker' import { useDraftWorkout } from '../hooks/useDraftWorkout' import './WorkoutEditPage.css' export default function WorkoutEditPage({ workout, onBack, onSave }) { const { exercises, setExercises, clearDraft, hasDraft, restoreDraft } = useDraftWorkout(workout.id, workout.exercises || []) const [pickerOpen, setPickerOpen] = useState(false) const [swapIndex, setSwapIndex] = useState(null) // null = adding, number = swapping const [saving, setSaving] = useState(false) const [error, setError] = useState(null) const [syncStatus, setSyncStatus] = useState('idle') // idle | saving | saved | error const [draftPromptShown, setDraftPromptShown] = useState(false) const [retryCount, setRetryCount] = useState(0) const [lastSavePayload, setLastSavePayload] = useState(null) // Show draft recovery prompt on first render const handleRecoverDraft = () => { if (hasDraft && !draftPromptShown) { setDraftPromptShown(true) // Prompt is shown via conditional rendering below } } const handleOpenPicker = (index = null) => { setSwapIndex(index) setPickerOpen(true) } const handleSelectExercise = (exercise) => { if (swapIndex !== null) { // Swap setExercises(prev => prev.map((ex, i) => { if (i === swapIndex) { return { ...ex, exercise_id: exercise.id, name: exercise.name, muscle_group: exercise.muscle_group, // Keep existing sets/reps } } return ex })) } else { // Add setExercises(prev => [...prev, { exercise_id: exercise.id, name: exercise.name, muscle_group: exercise.muscle_group, sets: 3, reps_min: 8, reps_max: 12 }]) } setPickerOpen(false) } const handleRemove = (index) => { setExercises(prev => prev.filter((_, i) => i !== index)) } const handleUpdate = (index, field, value) => { setExercises(prev => prev.map((ex, i) => { if (i === index) { return { ...ex, [field]: value } } return ex })) // Clear error state on user edit if (error) setError(null) } /** * Determine specific error message based on error type */ const getErrorMessage = (err) => { // Network errors if (!err || err instanceof TypeError && err.message.includes('fetch')) { return 'Anslutning misslyckades. Försök igen?' } // Check if error has a response (API error) if (err.status) { if (err.status === 400) { return 'Ogiltiga ändringar. Kontrollera dina inmatningar.' } if (err.status === 401 || err.status === 403) { return 'Du har inte behörighet att spara denna träning.' } if (err.status >= 500) { return 'Serverfel. Försök igen senare.' } if (err.status >= 400) { return 'Ett fel uppstod när träningen skulle sparas. Försök igen.' } } // Fallback return err.message || 'Sparning misslyckades. Försök igen.' } const handleSave = async () => { setSaving(true) setSyncStatus('saving') setError(null) setRetryCount(prev => prev + 1) try { // Format for API const payload = { exercises: exercises.map(ex => ({ exercise_id: ex.exercise_id || ex.id, // Handle both structures sets: parseInt(ex.sets) || 3, reps_min: parseInt(ex.reps_min) || 8, reps_max: parseInt(ex.reps_max) || 12 })) } // Store payload for potential retry setLastSavePayload(payload) // Call the save callback await onSave(workout.id, payload) // Success: clear draft and show confirmation clearDraft() setSyncStatus('saved') setRetryCount(0) // Reset retry count on success // Log success console.log('Workout saved successfully', { workoutId: workout.id, exerciseCount: exercises.length, retryCount }) // Reset status after 2 seconds setTimeout(() => setSyncStatus('idle'), 2000) } catch (err) { // Log error with context for debugging console.error('Failed to save workout:', { error: err, workoutId: workout.id, exerciseCount: exercises.length, retryCount, payload: lastSavePayload }) // Determine error message based on error type const errorMessage = getErrorMessage(err) setError(errorMessage) setSyncStatus('error') // Keep draft on error so user doesn't lose work // (useDraftWorkout already auto-saves, so no action needed here) } finally { setSaving(false) } } const handleRetry = () => { // Log retry attempt console.log('User retrying save', { workoutId: workout.id, retryCount }) handleSave() } const handleDiscardDraft = () => { clearDraft() setDraftPromptShown(true) // Reset exercises to original setExercises(workout.exercises || []) } // Show draft recovery prompt if we have a draft and haven't shown it yet const showDraftPrompt = hasDraft && !draftPromptShown if (showDraftPrompt) { handleRecoverDraft() } return (
Vi hittade ett utkast från din senaste redigering. Vill du fortsätta eller börja om?
{exercises.length} övningar