Skip to content

Instantly share code, notes, and snippets.

@guzart
Last active March 20, 2017 18:15
Show Gist options
  • Save guzart/1331796c791ced2a5ae1b14f560d7029 to your computer and use it in GitHub Desktop.
Save guzart/1331796c791ced2a5ae1b14f560d7029 to your computer and use it in GitHub Desktop.
// @flow
import { flow } from 'lodash';
import { fromJS, Map } from 'immutable';
import type { User, ValidationErrors, WidgetAction } from 'pivot/types';
import * as t from './types';
import * as actions from './actions';
const EMPTY_ERRORS = new Map();
const initialState: t.State = fromJS({
errors: {},
isBusy: false,
showModal: false,
user: null,
});
const BLANK_USER: User = fromJS({
id: 0,
email: '',
firstName: '',
lastName: '',
name: '',
permissionSet: {
isTimeClockTrackable: false,
},
phone: '',
username: '',
});
type RootActions =
| t.AddAction
| t.CancelAction
| t.ChangeAction
| t.EditAction
| t.SaveAction
| t.SaveErrorAction
| t.SaveSuccessAction;
// Commands
type Cmd = (args: any) => (state: t.State) => t.State;
const changeUser: Cmd = (name: string, value: any) => (state: t.State) =>
state.set('user', state.get('user').setIn(name.split('.'), value));
const clearErrors: Cmd = () => (state: t.State) => state.set('errors', EMPTY_ERRORS);
const hideModal: Cmd = () => (state: t.State) => state.set('showModal', false);
const isBusy: Cmd = () => (state: t.State) => state.set('isBusy', true);
const notBusy: Cmd = () => (state: t.State) => state.set('isBusy', false);
const setErrors: Cmd = (errors: ValidationErrors) => (state: t.State) => state.set('errors', errors);
const setUser: Cmd = (user: User) => (state: t.State) => state.set('user', user);
const showModal: Cmd = () => (state: t.State) => state.set('showModal', true);
function rootReducer(state = initialState, action: RootActions) {
const sequence = (...fn) => state.withMutations(m => flow(...fn)(m));
switch (action.type) {
case actions.ADD:
return sequence(
clearErrors(),
setUser(BLANK_USER),
showModal(),
);
case actions.CANCEL:
return sequence(
hideModal(),
);
case actions.CHANGE:
return sequence(
changeUser(action.payload.name, action.payload.value),
);
case actions.EDIT:
return sequence(
clearErrors(),
setUser(action.payload.user),
showModal(),
);
case actions.SAVE:
return sequence(
clearErrors(),
isBusy(),
);
case actions.SAVE_ERROR:
return sequence(
setErrors(action.payload.errors),
notBusy(),
);
case actions.SAVE_SUCCESS:
return sequence(
notBusy(),
hideModal(),
);
default:
return state;
}
}
export default function buildReducer(id: string) {
return (state: any, action: WidgetAction<*, *>) => {
if (state !== undefined && action.id !== id) {
return state;
}
return rootReducer(state, action);
};
}
// @flow
import type { Record, User, ValidationErrors, WidgetAction } from 'pivot/types';
export type AddActionType = 'widgets/user_editor/ADD';
export type CancelActionType = 'widgets/user_editor/CANCEL';
export type ChangeActionType = 'widgets/user_editor/CHANGE';
export type EditActionType = 'widgets/user_editor/EDIT';
export type SaveActionType = 'widgets/user_editor/SAVE';
export type SaveErrorActionType = 'widgets/user_editor/SAVE_ERROR';
export type SaveSuccessActionType = 'widgets/user_editor/SAVE_SUCCESS';
export type AddAction = WidgetAction<AddActionType, null>;
export type CancelAction = WidgetAction<CancelActionType, null>;
export type ChangePayload = { name: string, value: any };
export type ChangeAction = WidgetAction<ChangeActionType, ChangePayload>;
export type EditPayload = { user: User };
export type EditAction = WidgetAction<EditActionType, EditPayload>;
export type SaveAction = WidgetAction<SaveActionType, null>;
export type SaveErrorPayload = { message: string, errors: ValidationErrors };
export type SaveErrorAction = WidgetAction<SaveErrorActionType, SaveErrorPayload>;
export type SaveSuccessAction = WidgetAction<SaveSuccessActionType, null>;
export type InstanceActions = {
add: () => AddAction,
cancel: () => CancelAction,
change: (payload: ChangePayload) => ChangeAction,
edit: (payload: EditPayload) => EditAction,
save: () => SaveAction,
saveError: (payload: SaveErrorPayload) => SaveErrorAction,
saveSuccess: () => SaveSuccessAction,
};
export type RawState = {
errors: ValidationErrors,
isBusy: boolean,
showModal: boolean,
user: User,
};
export type State = Record<RawState>;
export type RootSelector = () => () => State;
export type InstanceSelectors = {
selectErrors: () => State => ValidationErrors,
selectIsBusy: () => State => boolean,
selectIsUpdate: () => State => boolean,
selectShowModal: () => State => boolean,
selectUser: () => State => User,
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment