import { useState, useMemo, useEffect } from 'react'; import { useAppState, useAppDispatch, useSelPanelRows, useSelVars } from '../context/AppContext.jsx'; import Header from '../components/Header.jsx'; import { showWarnToast } from '../components/Toast.jsx'; export default function Step4Mapping({ onNext, onBack, onNav }) { const state = useAppState(); const dispatch = useAppDispatch(); const selPanelRows = useSelPanelRows(); const selVars = useSelVars(); const { panelMap, panelCSV, _rMap } = state; const [panelQ, setPanelQ] = useState(''); const [varQ, setVarQ] = useState(''); const labelCol = panelCSV?.headers[0] || 'Panel'; const pHeaders = panelCSV?.headers || []; // Restore from past result useEffect(() => { if (!_rMap || !_rMap.length) return; const newMap = { ...panelMap }; selPanelRows.forEach(pr => { const pk = String(pr.__id); if (!newMap[pk]) newMap[pk] = {}; const matched = _rMap.find(rec => Object.entries(rec.panelData).some(([col, val]) => { if (!val) return false; const rowKey = Object.keys(pr).find(rk => rk.toLowerCase() === col.toLowerCase()) || col; return (pr[rowKey] || '').trim().toLowerCase() === val.toLowerCase(); }) ); if (matched) { selVars.forEach(v => { newMap[pk][v] = true; }); matched.removedVars.forEach(v => { newMap[pk][v] = false; }); } else { selVars.forEach(v => { if (newMap[pk][v] === undefined) newMap[pk][v] = true; }); } }); dispatch({ type: 'SET_PANEL_MAP', payload: newMap }); dispatch({ type: 'SET_RESTORE_BUFFERS', payload: { _rMap: null } }); }, []); // Init panelMap for any missing panels/vars useEffect(() => { const newMap = { ...panelMap }; let changed = false; selPanelRows.forEach(pr => { const pk = String(pr.__id); if (!newMap[pk]) { newMap[pk] = {}; changed = true; } selVars.forEach(v => { if (newMap[pk][v] === undefined) { newMap[pk][v] = true; changed = true; } }); }); if (changed) dispatch({ type: 'SET_PANEL_MAP', payload: newMap }); }, [selPanelRows.length, selVars.length]); const visRows = useMemo(() => selPanelRows.filter(pr => !panelQ || String(pr[labelCol] || String(pr.__id)).toLowerCase().includes(panelQ.toLowerCase())) .map(pr => ({ ...pr, key: String(pr.__id) })) , [selPanelRows, panelQ, labelCol]); const visCols = useMemo(() => selVars.filter(v => !varQ || v.toLowerCase().includes(varQ.toLowerCase())) , [selVars, varQ]); function setCell(pk, varName, val) { const newMap = { ...panelMap, [pk]: { ...(panelMap[pk] || {}), [varName]: val } }; dispatch({ type: 'SET_PANEL_MAP', payload: newMap }); } function toggleRow(pk) { const cur = panelMap[pk] || {}; const allOn = visCols.every(v => cur[v] === true); const newPk = { ...cur }; visCols.forEach(v => { newPk[v] = !allOn; }); dispatch({ type: 'SET_PANEL_MAP', payload: { ...panelMap, [pk]: newPk } }); } function toggleCol(varName) { const allOn = visRows.every(r => (panelMap[r.key] || {})[varName] === true); const newMap = { ...panelMap }; visRows.forEach(r => { newMap[r.key] = { ...(newMap[r.key] || {}), [varName]: !allOn }; }); dispatch({ type: 'SET_PANEL_MAP', payload: newMap }); } function clearAll() { const newMap = { ...panelMap }; selPanelRows.forEach(pr => { const pk = String(pr.__id); newMap[pk] = {}; selVars.forEach(v => { newMap[pk][v] = false; }); }); dispatch({ type: 'SET_PANEL_MAP', payload: newMap }); } const mappedCount = useMemo(() => { let n = 0; Object.values(panelMap).forEach(row => Object.values(row).forEach(v => { if (v === true) n++; })); return n; }, [panelMap]); const anyMapped = mappedCount > 0; return (
|
{h}
|
))}
Toggle
|
{visCols.map(varName => {
const allOn = visRows.every(r => (panelMap[r.key] || {})[varName] === true);
return (
{varName}
|
);
})}
|---|---|---|
| {row[h]} | )}{visCols.map(varName => { const checked = cur[varName] === true; return ( |
setCell(pk, varName, !checked)}>
setCell(pk, varName, e.target.checked)} onClick={e => e.stopPropagation()} />
|
);
})}