Skip to content

Instantly share code, notes, and snippets.

@SuperOleg39
Created January 25, 2018 08:54
Show Gist options
  • Select an option

  • Save SuperOleg39/042c88c312ed62b57cf5fa0a5f9b06e6 to your computer and use it in GitHub Desktop.

Select an option

Save SuperOleg39/042c88c312ed62b57cf5fa0a5f9b06e6 to your computer and use it in GitHub Desktop.
/**
* Store part
*/
export interface IWithOrders extends IWithApplication, IWithConfig, IWithWidgetDictionaries {
orders: IOrdersState;
}
/**
* State
*/
export interface IOrdersState {
data: IData;
create: IRequestState<IErrorResponse>;
upgrade: IRequestState<IErrorResponse>;
}
interface IData {
order: IOrderNormalized;
products: IProductsNormalized,
counterparties: ICounterPartiesNormalized;
expressOrderCreated?: boolean;
}
export const initialData: IData = {
order: null,
products: null,
counterparties: null,
expressOrderCreated: false,
};
/**
* Selectors
*/
export const selectors = {
getOrderId: (state: IWithOrders): number => state.orders.data.order ? state.orders.data.order.id : null,
hasExpressOrder: (state: IWithOrders): boolean => state.orders.data.expressOrderCreated,
};
/**
* Constants
*/
export enum constants {
CREATE_REQUEST = 'orders/CREATE_REQUEST',
CREATE_SUCCESS = 'orders/CREATE_SUCCESS',
CREATE_FAILURE = 'orders/CREATE_FAILURE',
UPGRADE_REQUEST = 'orders/UPGRADE_REQUEST',
UPGRADE_SUCCESS = 'orders/UPGRADE_SUCCESS',
UPGRADE_FAILURE = 'orders/UPGRADE_FAILURE',
}
/**
* Actions
*/
/* tslint:disable:interface-over-type-literal */
type actions = {
createRequest: {
type: constants.CREATE_REQUEST;
};
createSuccess: {
type: constants.CREATE_SUCCESS;
response: IResponse<IOrder>;
dictionary: Dictionary<ICounterPartyDictionary>;
express?: boolean;
};
createFailure: {
type: constants.CREATE_FAILURE;
error: IErrorResponse;
};
upgradeRequest: {
type: constants.UPGRADE_REQUEST;
};
upgradeSuccess: {
type: constants.UPGRADE_SUCCESS;
response: IResponse<IOrder>;
dictionary: Dictionary<ICounterPartyDictionary>;
express?: boolean;
};
upgradeFailure: {
type: constants.UPGRADE_FAILURE;
error: IErrorResponse;
};
};
type RootAction = actions[keyof actions];
/**
* Reducers
*/
export function dataReducer(state = initialData, action: RootAction): IData {
switch (action.type) {
case constants.CREATE_SUCCESS:
case constants.UPGRADE_SUCCESS:
const nextState: IData = {
order: normalizeOrder(action.response.data),
products: normalizeProducts(action.response.data.products),
counterparties: normalizeCounterparties(
action.response.data.products,
action.dictionary,
),
};
if ('express' in action && !state.expressOrderCreated) {
nextState.expressOrderCreated = action.express;
}
return nextState;
default:
return state;
}
}
const rootReducer = combineReducers({
data: dataReducer,
create: createRequestReducer([constants.CREATE_REQUEST, constants.CREATE_SUCCESS, constants.CREATE_FAILURE]),
upgrade: createRequestReducer([constants.UPGRADE_REQUEST, constants.UPGRADE_SUCCESS, constants.UPGRADE_FAILURE]),
});
export default rootReducer;
/**
* Action creators
*/
export const actionCreators = {
createRequest: (): actions['createRequest'] => ({ type: constants.CREATE_REQUEST }),
createSuccess: (
response: ICreateResponse,
dictionary: Dictionary<ICounterPartyDictionary>,
express?: boolean,
): actions['createSuccess'] => ({ type: constants.CREATE_SUCCESS, response, dictionary, express }),
createFailure: (error: IErrorResponse): actions['createFailure'] => ({ type: constants.CREATE_FAILURE, error }),
upgradeRequest: (): actions['upgradeRequest'] => ({ type: constants.UPGRADE_REQUEST }),
upgradeSuccess: (
response: ICreateResponse,
dictionary: Dictionary<ICounterPartyDictionary>,
): actions['upgradeSuccess'] => ({ type: constants.UPGRADE_SUCCESS, response, dictionary }),
upgradeFailure: (error: IErrorResponse): actions['upgradeFailure'] => ({ type: constants.UPGRADE_FAILURE, error }),
};
/**
* Thunk actions
*/
export const thunkActions = {
createOrUpgrade: (express?: boolean, saveOnly?: boolean) => {
return async (dispatch: Dispatch<{}>, getState: () => IWithOrders) => {
const expressOrderCreated = selectors.hasExpressOrder(getState());
const orderId = selectors.getOrderId(getState());
try {
return expressOrderCreated && orderId
? await dispatch(thunkActions.upgrade(orderId, saveOnly))
: await dispatch(thunkActions.create(express, saveOnly));
} catch (error) {
throw error;
}
};
},
create: (express?: boolean, saveOnly?: boolean) => {
return async (dispatch: Dispatch<{}>, getState: () => IWithOrders) => {
const config = getState().config;
const widgetEdition = config.widgetEdition;
const calculation = config.loansCalculation;
const dictionary = dictionarySelector(getState(), 'counterparties');
const application = transformApplication(getState().application);
const params: ICreateParams = {
cart: config.productsCart,
filter: config.productsFilter,
creator_id: config.applicationCreatorId,
save_only: saveOnly,
};
application.initial_payment = calculation.initial_payment;
application.loan_period = calculation.period;
dispatch(actionCreators.createRequest());
if (express) {
params.application_express = application;
} else if (widgetEdition === 'one') {
params.application = application;
} else if (widgetEdition === 'extended') {
params.application_full = application;
}
try {
const response = await create(params);
dispatch(actionCreators.createSuccess(response, dictionary, express));
return response;
} catch (reason) {
const error = reason.response.data;
dispatch(actionCreators.createFailure(error));
throw error;
}
};
},
upgrade: (id: number, saveOnly?: boolean) => {
return async (dispatch: Dispatch<{}>, getState: () => IWithOrders) => {
const config = getState().config;
const widgetEdition = config.widgetEdition;
const calculation = config.loansCalculation;
const dictionary = dictionarySelector(getState(), 'counterparties');
const application = transformApplication(getState().application);
const params: IUpgradeParams = {
cart: config.productsCart,
filter: config.productsFilter,
creator_id: config.applicationCreatorId,
save_only: saveOnly,
};
application.initial_payment = calculation.initial_payment;
application.loan_period = calculation.period;
dispatch(actionCreators.upgradeRequest());
if (widgetEdition === 'one') {
params.application = application;
} else if (widgetEdition === 'extended') {
params.application_full = application;
}
try {
const response = await upgrade(id, params);
dispatch(actionCreators.upgradeSuccess(response, dictionary));
return response;
} catch (reason) {
const error = reason.response.data;
dispatch(actionCreators.upgradeFailure(error));
throw error;
}
};
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment