Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | 'use client' import { useState, useEffect, useRef } from 'react' import type { WorksheetFormState } from '@/app/create/worksheets/types' import { extractConfigFields } from '../utils/extractConfigFields' interface UseWorksheetAutoSaveReturn { isSaving: boolean lastSaved: Date | null saveError: string | null } /** * Auto-save worksheet settings to server * * Features: * - Debounced auto-save (1000ms delay) * - Persists settings including seed and prngAlgorithm for problem reproducibility * - Excludes transient state (date, rows, total) * - Persists V4 fields: mode, digitRange, displayRules, difficultyProfile, manualPreset * - Silent error handling (auto-save is not critical) * - StrictMode-safe (handles double renders) */ export function useWorksheetAutoSave( formState: WorksheetFormState, worksheetType: 'addition' ): UseWorksheetAutoSaveReturn { const [isSaving, setIsSaving] = useState(false) const [lastSaved, setLastSaved] = useState<Date | null>(null) const [saveError, setSaveError] = useState<string | null>(null) // Store the previous formState for auto-save to detect real changes const prevAutoSaveFormStateRef = useRef(formState) // Auto-save settings when they change (debounced) - skip on initial mount useEffect(() => { // Skip auto-save if formState hasn't actually changed (handles StrictMode double-render) if (formState === prevAutoSaveFormStateRef.current) { console.log('[useWorksheetAutoSave] Skipping auto-save - formState reference unchanged') return } prevAutoSaveFormStateRef.current = formState console.log('[useWorksheetAutoSave] Settings changed, will save in 1s...') const timer = setTimeout(async () => { console.log('[useWorksheetAutoSave] Attempting to save settings...') setIsSaving(true) setSaveError(null) // Clear previous errors try { // Extract persisted config fields (includes seed/prngAlgorithm, excludes date and derived state) const config = extractConfigFields(formState) const response = await fetch('/api/worksheets/settings', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ type: worksheetType, config, }), }) if (response.ok) { const data = await response.json() console.log('[useWorksheetAutoSave] Save response:', data) if (data.success) { console.log('[useWorksheetAutoSave] ✓ Settings saved successfully') setLastSaved(new Date()) setSaveError(null) } else if (data.error) { // Validation error from server console.error('[useWorksheetAutoSave] Validation error:', data.error) setSaveError(data.error) } else { console.log('[useWorksheetAutoSave] Save skipped') } } else { const errorText = await response.text() console.error('[useWorksheetAutoSave] Save failed with status:', response.status) setSaveError(`Failed to save settings (${response.status}): ${errorText}`) } } catch (error) { // Surface error to user const errorMessage = error instanceof Error ? error.message : 'Unknown error' console.error('[useWorksheetAutoSave] Settings save error:', error) setSaveError(`Failed to save settings: ${errorMessage}`) } finally { setIsSaving(false) } }, 1000) // 1 second debounce for auto-save return () => clearTimeout(timer) }, [formState, worksheetType]) return { isSaving, lastSaved, saveError, } } |