import React, { createContext, useContext, useState, useEffect, useCallback } from 'react'; import { wpApiFetch } from '../hooks/useApi'; import { CHECKLIST_DATA } from '@cra-compliance/shared'; import type { UserChecklistProgress, ChecklistItem } from '@cra-compliance/types'; interface ComplianceContextType { progress: Record; loading: boolean; loadError: string | null; toggleItem: (item: ChecklistItem) => Promise; saveNotes: (itemId: string, notes: string) => Promise; savingItemId: string | null; savingNotesId: string | null; totalItems: number; completedItems: number; compliancePercent: number; } const ComplianceContext = createContext(null); export function ComplianceProvider({ children }: { children: React.ReactNode }) { const [progress, setProgress] = useState>({}); const [loading, setLoading] = useState(true); const [loadError, setLoadError] = useState(null); const [savingItemId, setSavingItemId] = useState(null); const [savingNotesId, setSavingNotesId] = useState(null); useEffect(() => { wpApiFetch<{ data: Record }>('checklist') .then((res) => { setProgress(res.data || {}); setLoadError(null); }) .catch((err: unknown) => { const msg = err instanceof Error ? err.message : 'Failed to load checklist'; setLoadError(msg); console.error('[CRA Checklist] Failed to load progress:', msg); }) .finally(() => setLoading(false)); }, []); const toggleItem = useCallback(async (item: ChecklistItem) => { const currentlyCompleted = progress[item.id]?.completed || false; const newCompleted = !currentlyCompleted; setSavingItemId(item.id); try { await wpApiFetch(`checklist/${item.id}`, { method: 'POST', body: JSON.stringify({ completed: newCompleted, notes: progress[item.id]?.notes || '' }), }); setProgress((prev) => ({ ...prev, [item.id]: { item_id: item.id, completed: newCompleted, completed_at: newCompleted ? new Date().toISOString() : null, notes: prev[item.id]?.notes || '', }, })); } catch { // Revert on error - state unchanged since we update after success } finally { setSavingItemId(null); } }, [progress]); const saveNotes = useCallback(async (itemId: string, notes: string) => { setSavingNotesId(itemId); try { const isCompleted = progress[itemId]?.completed || false; await wpApiFetch(`checklist/${itemId}`, { method: 'POST', body: JSON.stringify({ completed: isCompleted, notes }), }); setProgress((prev) => ({ ...prev, [itemId]: { ...prev[itemId], item_id: itemId, notes }, })); } finally { setSavingNotesId(null); } }, [progress]); const totalItems = CHECKLIST_DATA.reduce((acc, cat) => acc + cat.items.length, 0); const completedItems = Object.values(progress).filter((p) => p.completed).length; const compliancePercent = totalItems > 0 ? Math.round((completedItems / totalItems) * 100) : 0; return ( {children} ); } export function useCompliance() { const context = useContext(ComplianceContext); if (!context) { throw new Error('useCompliance must be used within a ComplianceProvider'); } return context; }