import isNil from "lodash/isNil";
import makePristine from "../makePristine";
import { updateBatch } from "../reducerUtils";
import * as actionTypes from "../actionTypes";
import createReducer from "../createReducer";
/**
* @typedef {Object} memberHoax.ReducerWithInit
* @property {function} reducer - the reducer to be used along with provider
* @property {function} init - the function to initialize the reducer's state
*/
/**
* @function memberHoax.makeReducer
* @access private
* @param {function} getInitialState - a function that returns the initialState
* @param {function} customReducer - a custom reducer
* @return {memberHoax.ReducerWithInit}
*/
export default (getInitialState, customReducer) => {
const {
getInitialPristineState,
updatePristine,
removePristine
} = makePristine("pristine");
const init = (state = {}) => ({
...getInitialState(),
...state,
...getInitialPristineState()
});
const getValidValue = (attr, value) =>
isNil(value) ? getInitialState()[attr] : value;
const update = (state, attr, value) => {
value = getValidValue(attr, value);
state = updatePristine(state, attr, value);
return {
...state,
[attr]: value
};
};
const reducerHandlers = {
[actionTypes.initialize]: (state, action) => init(action.values),
[actionTypes.update]: (state, action) => update(state, action.attr, action.value),
[actionTypes.updateBatch]: (state, action) => updateBatch(update, state, action.values),
[actionTypes.reset]: (state, action) => init(),
[actionTypes.resetPristine]: (state, action) => removePristine(state),
[actionTypes.resetPristineKey]: (state, action) => removePristine(state, action.attr),
[actionTypes.startProcess]: (state, action) => ({ ...state, processing: true }),
[actionTypes.doneProcess]: (state, action) => ({ ...state, processing: false }),
[actionTypes.startFetch]: (state, action) => ({ ...state, loading: true }),
[actionTypes.doneFetch]: (state, action) => init({
...action.values,
loading: false,
loaded: true
}),
[actionTypes.failFetch]: (state, action) => ({ ...state, loading: false }),
...customReducer
};
const reducer = createReducer(reducerHandlers);
return { reducer, init };
};