All files / web/src/app/create/worksheets/hooks useWorksheetAutoSave.ts

0% Statements 0/101
0% Branches 0/1
0% Functions 0/1
0% Lines 0/101

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,
  }
}