Last active
December 18, 2020 18:52
-
-
Save joseaquino/f27cf3d05f59ea44e0a4d9dd9b9122aa to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ========================================================================== | |
* Utility Types and Functions | |
* ========================================================================== */ | |
export type StateAction<T extends string, P = undefined> = P extends void | |
? { | |
type: T | |
} | |
: { | |
type: T | |
payload: P | |
} | |
type GenericAction = { | |
type: string | |
payload?: any | |
} | |
export type Payload<Actions extends GenericAction, ActionType> = Extract< | |
Actions, | |
{ type: ActionType } | |
> extends { payload: any } | |
? Extract<Actions, { type: ActionType }>['payload'] | |
: undefined | |
export type ReducerCollection< | |
Actions extends StateAction<string, any>, | |
TState | |
> = { | |
[ActionType in Actions['type'] | 'DEFAULT']: ( | |
state: TState, | |
payload: Payload<Actions, ActionType> | |
) => ActionType extends 'DEFAULT' ? void | TState : TState | |
} | |
export const reducerCollection = <C extends StateAction<string, any>, TState>( | |
cases: ReducerCollection<C, TState> | |
) => { | |
function getCase( | |
state: TState, | |
action: C extends StateAction<string, infer A> | |
? StateAction<C['type'], A> | |
: StateAction<C['type']> | |
): TState | any { | |
if (cases.hasOwnProperty(action.type)) { | |
return cases[action.type as keyof typeof cases]( | |
state, | |
(action as GenericAction).payload | |
) | |
} else { | |
return cases['DEFAULT'](state, (action as GenericAction).payload) | |
} | |
} | |
return getCase | |
} | |
/* ========================================================================== | |
* Actions Constants | |
* ========================================================================== */ | |
enum CONFIG_ACTION_NAMES { | |
smsPaymentLoading = 'Configurations API/Loading SMS Payment', | |
smsPaymentUpdating = 'Configurations API/Updating SMS Payment', | |
smsPaymentSuccess = 'Configurations API/Commerce SMS Payment Loaded', | |
smsPaymentFailure = 'Configuration API/Commerce SMS Payment Failed', | |
} | |
/* ========================================================================== | |
* Types & Interfaces | |
* ========================================================================== */ | |
export interface ConfigurationState { | |
smsPayment: { | |
value: string | null | |
request: BasicRequest | |
} | |
} | |
type SMSPaymentLoading = StateAction<CONFIG_ACTION_NAMES.smsPaymentLoading> | |
type SMSPaymentUpdating = StateAction<CONFIG_ACTION_NAMES.smsPaymentUpdating> | |
type SMSPaymentSuccess = StateAction< | |
CONFIG_ACTION_NAMES.smsPaymentSuccess, | |
{ value: string } | |
> | |
type SMSPaymentFailure = StateAction< | |
CONFIG_ACTION_NAMES.smsPaymentFailure, | |
{ | |
errorType: RequestError | |
} | |
> | |
type ConfigurationActionTypes = | |
| SMSPaymentLoading | |
| SMSPaymentUpdating | |
| SMSPaymentSuccess | |
| SMSPaymentFailure | |
/* ========================================================================== | |
* State Management | |
* ========================================================================== */ | |
const reducers = reducerCollection< | |
ConfigurationActionTypes, | |
ConfigurationState | |
>({ | |
DEFAULT: () => { | |
throw new Error( | |
'useConfigurationsApi: An action was dispatched which has no matching reducer.' | |
) | |
}, | |
// SMS Payment Loading reducer | |
[CONFIG_ACTION_NAMES.smsPaymentLoading]: (state) => ({ | |
...state, | |
smsPayment: { | |
value: null, | |
request: { | |
status: 'LOADING', | |
error: null, | |
}, | |
}, | |
}), | |
// SMS Payment Updating reducer | |
[CONFIG_ACTION_NAMES.smsPaymentUpdating]: (state) => ({ | |
...state, | |
smsPayment: { | |
value: state.smsPayment.value, | |
request: { | |
status: 'UPDATING', | |
error: null, | |
}, | |
}, | |
}), | |
// SMS Payment Success reducer | |
[CONFIG_ACTION_NAMES.smsPaymentSuccess]: (state, { value }) => ({ | |
...state, | |
smsPayment: { | |
value, | |
request: { | |
status: 'IDLE', | |
error: null, | |
}, | |
}, | |
}), | |
// SMS Payment Failure reducer | |
[CONFIG_ACTION_NAMES.smsPaymentFailure]: (state, { errorType }) => ({ | |
...state, | |
smsPayment: { | |
value: state.smsPayment.value, | |
request: { | |
status: 'ERROR', | |
error: errorType, | |
}, | |
}, | |
}), | |
}) | |
const initialState: ConfigurationState = { | |
smsPayment: { | |
value: null, | |
request: { | |
status: 'IDLE', | |
error: null, | |
}, | |
}, | |
} | |
/* ========================================================================== | |
* Component Definition | |
* ========================================================================== */ | |
const ConfigurationsComponent = () => { | |
const [state, dispatch] = useReducer(reducers, initialState) | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment