import { createContext, useContext, useReducer, useCallback } from 'react'; import { DEFAULT_CONFIG } from '../utils/constants.js'; const AppContext = createContext(null); const AppDispatch = createContext(null); const initialState = { // Step 1 files: { d: null, p: null, r: null }, dictCSV: null, panelCSV: null, selectedPanels: new Set(), p1ColFilters: {}, fromPastResult: false, // Restore buffers from past result _rPanels: null, _rVars: null, _rC: null, _rMap: null, _rFix: null, // Step 2 allRows: [], // dict rows with _sel flag _dictToken: null, // Step 3 contributions: {}, // { actKey: { panelKey: {min,max} } } // Step 4 panelMap: {}, // { panelKey: { varName: bool } } // Step 5 fixedVars: {}, // { panelKey: varName[] } // Step 6 modelParams: {}, // { "pk|var": {min_Adstock, ...} } // Step 7 config: JSON.parse(JSON.stringify(DEFAULT_CONFIG)), }; function reducer(state, action) { switch (action.type) { case 'SET_DICT_CSV': return { ...state, dictCSV: action.payload }; case 'SET_PANEL_CSV': return { ...state, panelCSV: action.payload }; case 'SET_FILE': return { ...state, files: { ...state.files, [action.key]: action.value } }; case 'SET_SELECTED_PANELS': return { ...state, selectedPanels: action.payload }; case 'SET_P1_COL_FILTERS': return { ...state, p1ColFilters: action.payload }; case 'SET_ALL_ROWS': return { ...state, allRows: action.payload, _dictToken: action.token }; case 'TOGGLE_VAR_SEL': { const rows = state.allRows.map(r => r.__id === action.id ? { ...r, _sel: !r._sel } : r); return { ...state, allRows: rows }; } case 'SET_ALL_VARS_SEL': { const rows = state.allRows.map(r => action.ids.has(r.__id) ? { ...r, _sel: action.on } : r); return { ...state, allRows: rows }; } case 'SET_CONTRIBUTIONS': return { ...state, contributions: action.payload }; case 'SET_PANEL_MAP': return { ...state, panelMap: action.payload }; case 'SET_FIXED_VARS': return { ...state, fixedVars: action.payload }; case 'SET_MODEL_PARAMS': return { ...state, modelParams: action.payload }; case 'SET_CONFIG': return { ...state, config: action.payload }; case 'SET_RESTORE_BUFFERS': return { ...state, ...action.payload }; case 'SET_FROM_PAST_RESULT': return { ...state, fromPastResult: action.payload }; case 'RESET_ALL': return { ...initialState, config: JSON.parse(JSON.stringify(DEFAULT_CONFIG)) }; default: return state; } } export function AppProvider({ children }) { const [state, dispatch] = useReducer(reducer, initialState); return ( {children} ); } export function useAppState() { return useContext(AppContext); } export function useAppDispatch() { return useContext(AppDispatch); } // Derived helpers export function useSelPanelRows() { const { panelCSV, selectedPanels } = useAppState(); if (!panelCSV) return []; return panelCSV.rows.filter(r => selectedPanels.has(String(r.__id))); } export function useSelVars() { const { allRows } = useAppState(); return allRows.filter(r => r._sel).map(r => r.VARIABLE); } export function useActivityGroups() { const { allRows } = useAppState(); const g = {}; allRows.filter(r => r._sel).forEach(r => { const a = r.SN_ACTIVITY_LEVEL_1 || '(Unassigned)'; if (!g[a]) g[a] = []; g[a].push(r.VARIABLE); }); return g; }