/** * Work Assignments Component v2 * * Clean implementation with: * - Array guards before all .map() calls * - Loading & empty states * - User-friendly error handling * - Debug logging */ const { useState, useEffect } = React; // Debug logger function debugLog(context, message, data = null) { if (window.WM_DEBUG_FIELDS) { console.log(`[WorkAssignments-v2] [${context}]`, message, data || ''); } } // Work Assignments Component function WorkAssignmentsV2() { const [assignments, setAssignments] = useState([]); const [fieldConfig, setFieldConfig] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [showModal, setShowModal] = useState(false); const [selectedAssignment, setSelectedAssignment] = useState(null); const [showBin, setShowBin] = useState(false); const [toast, setToast] = useState(null); const [errorLogId, setErrorLogId] = useState(null); // Load field configuration useEffect(() => { loadFieldConfig(); }, []); // Load assignments useEffect(() => { loadAssignments(); }, [showBin]); const loadFieldConfig = async () => { debugLog('loadFieldConfig', 'Starting...'); try { const response = await fetch(`${IWM_DATA.apiUrl}/work-manager/v1/work-assignments/fields`, { headers: { 'X-WP-Nonce': IWM_DATA.nonce } }); const result = await response.json(); debugLog('loadFieldConfig', 'Response:', result); if (result.success && result.data) { // CRITICAL: Guard to ensure array const fields = Array.isArray(result.data) ? result.data : []; debugLog('loadFieldConfig', 'Fields array length:', fields.length); setFieldConfig(fields); } else { throw new Error(result.message || 'Failed to load field configuration'); } } catch (err) { debugLog('loadFieldConfig', 'ERROR:', err); handleError('Failed to load form configuration', err); } }; const loadAssignments = async () => { debugLog('loadAssignments', 'Starting...', { showBin }); setLoading(true); setError(null); try { const endpoint = showBin ? '/work-assignments/bin' : '/work-assignments'; const response = await fetch(`${IWM_DATA.apiUrl}/work-manager/v1${endpoint}`, { headers: { 'X-WP-Nonce': IWM_DATA.nonce } }); const result = await response.json(); debugLog('loadAssignments', 'Response:', result); if (result.success && result.data) { // CRITICAL: Guard to ensure array const assignmentList = Array.isArray(result.data) ? result.data : []; debugLog('loadAssignments', 'Assignments array length:', assignmentList.length); setAssignments(assignmentList); } else { throw new Error(result.message || 'Failed to load assignments'); } } catch (err) { debugLog('loadAssignments', 'ERROR:', err); handleError('Failed to load assignments', err); } finally { setLoading(false); } }; const handleCreateAssignment = async (formData) => { debugLog('handleCreateAssignment', 'Data:', formData); try { const response = await fetch(`${IWM_DATA.apiUrl}/work-manager/v1/work-assignments`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-WP-Nonce': IWM_DATA.nonce }, body: JSON.stringify(formData) }); const result = await response.json(); debugLog('handleCreateAssignment', 'Response:', result); if (result.success) { showToast('Assignment created successfully!', 'success'); setShowModal(false); loadAssignments(); } else { throw new Error(result.message || 'Failed to create assignment'); } } catch (err) { debugLog('handleCreateAssignment', 'ERROR:', err); handleError('Failed to create assignment', err); } }; const handleMoveToBin = async (id) => { debugLog('handleMoveToBin', 'ID:', id); try { const response = await fetch(`${IWM_DATA.apiUrl}/work-manager/v1/work-assignments/${id}/bin`, { method: 'POST', headers: { 'X-WP-Nonce': IWM_DATA.nonce } }); const result = await response.json(); if (result.success) { showToast('Assignment moved to bin', 'success'); loadAssignments(); } else { throw new Error(result.message || 'Failed to move to bin'); } } catch (err) { handleError('Failed to move to bin', err); } }; const handleRestore = async (id) => { debugLog('handleRestore', 'ID:', id); try { const response = await fetch(`${IWM_DATA.apiUrl}/work-manager/v1/work-assignments/${id}/restore`, { method: 'POST', headers: { 'X-WP-Nonce': IWM_DATA.nonce } }); const result = await response.json(); if (result.success) { showToast('Assignment restored', 'success'); loadAssignments(); } else { throw new Error(result.message || 'Failed to restore'); } } catch (err) { handleError('Failed to restore assignment', err); } }; const handleDelete = async (id) => { if (!confirm('Permanently delete this assignment? This action cannot be undone.')) { return; } debugLog('handleDelete', 'ID:', id); try { const response = await fetch(`${IWM_DATA.apiUrl}/work-manager/v1/work-assignments/${id}`, { method: 'DELETE', headers: { 'X-WP-Nonce': IWM_DATA.nonce } }); const result = await response.json(); if (result.success) { showToast('Assignment permanently deleted', 'success'); loadAssignments(); } else { throw new Error(result.message || 'Failed to delete'); } } catch (err) { handleError('Failed to delete assignment', err); } }; const handleError = (userMessage, error) => { const logId = 'ERR_' + Date.now(); console.error(`[${logId}]`, userMessage, error); setError({ message: userMessage, details: error.message, logId: logId }); setErrorLogId(logId); }; const showToast = (message, type = 'success') => { setToast({ message, type }); setTimeout(() => setToast(null), 3000); }; // Loading state if (loading && assignments.length === 0) { return (
{error.details}
Error Log ID: {error.logId} (Check browser console for details)
{showBin ? 'Deleted assignments will appear here for 30 days before auto-deletion.' : 'Get started by creating your first assignment.'}
{!showBin && ( )}Assignee: {assignment.assignee_name}
)} {assignment.description && ({assignment.description}
)}Created: {new Date(assignment.created_at).toLocaleDateString()}