mmm-modeler_app / src /context /AppContext.jsx
aashish-bindal's picture
Initial commit: Dabur MMM Modeler React app
425a907
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 (
<AppContext.Provider value={state}>
<AppDispatch.Provider value={dispatch}>
{children}
</AppDispatch.Provider>
</AppContext.Provider>
);
}
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;
}