-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(app-general): add centralized loading and error management
- Loading branch information
Showing
12 changed files
with
208 additions
and
4 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { useTranslate } from './useTranslate'; | ||
|
||
const defaultError = 'errors.general'; | ||
|
||
export default function translateError( | ||
t: ReturnType<typeof useTranslate>, | ||
error: { code?: string; errorCode?: string; message?: string }, | ||
scope?: string, | ||
) { | ||
const errorCode = error.code || error.errorCode; | ||
let message = t(`${scope || 'errors.code'}.${errorCode}` as any, { | ||
default: '', | ||
}); | ||
|
||
if (!message) { | ||
message = t(`errors.code.${errorCode}` as any, { | ||
default: error.message, | ||
}); | ||
} | ||
|
||
return message || t(defaultError as any); | ||
} |
This file contains 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
56 changes: 56 additions & 0 deletions
56
packages/game-app/src/_shared/requests-status/createRequestHook.ts
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { Action } from '@reduxjs/toolkit'; | ||
import { useCallback, useEffect, useMemo, useState } from 'react'; | ||
import { useDispatch, useSelector } from 'react-redux'; | ||
import { translateError, useTranslate } from '@pipeline/i18n'; | ||
import { selectRequestStatus } from './selectors'; | ||
import { RequestsKeys } from './requestsKeys'; | ||
import { actions as requestsActions } from './index'; | ||
import { GeneralHookResponse } from './types'; | ||
|
||
type HookOptions = { | ||
errorMessagesScope?: string; | ||
}; | ||
|
||
export function createRequestHook<T extends Array<any>>( | ||
requestKey: keyof RequestsKeys, | ||
triggerAction: (...args: T) => Action, | ||
options?: HookOptions, | ||
): () => GeneralHookResponse<T> { | ||
return function (): GeneralHookResponse<T> { | ||
const t = useTranslate(); | ||
const dispatch = useDispatch(); | ||
const keySelector = useMemo(() => selectRequestStatus(requestKey), []); | ||
|
||
const { loading, success, error } = useSelector(keySelector); | ||
|
||
const getErrorMessage = (error: any) => { | ||
return error ? translateError(t, error, options?.errorMessagesScope) : undefined; | ||
}; | ||
|
||
const [translatedError, setTranslatedError] = useState(getErrorMessage(error)); | ||
|
||
useEffect(() => { | ||
const errorText = error ? getErrorMessage(error) : undefined; | ||
setTranslatedError(errorText); | ||
}, [error]); | ||
|
||
const call = useCallback( | ||
(...args: T) => { | ||
dispatch(triggerAction(...args)); | ||
}, | ||
[dispatch], | ||
); | ||
|
||
const reset = useCallback(() => { | ||
dispatch(requestsActions.resetStatus(requestKey)); | ||
}, [dispatch]); | ||
|
||
useEffect(() => { | ||
return () => { | ||
dispatch(requestsActions.resetStatus(requestKey)); | ||
}; | ||
}, []); | ||
|
||
return { loading, success, error, translatedError, call, reset }; | ||
}; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import reducer, { actions, name } from './slice'; | ||
import { RequestsKeys } from './requestsKeys'; | ||
import { addRequestStatusManagement } from './sagaIntegrations'; | ||
import { selectRequestStatus } from './selectors'; | ||
import { GeneralHookResponse, RequestStatus } from './types'; | ||
import { createRequestHook } from './createRequestHook'; | ||
|
||
export { actions, addRequestStatusManagement, createRequestHook, name, reducer, selectRequestStatus }; | ||
|
||
export type { GeneralHookResponse, RequestStatus, RequestsKeys }; |
7 changes: 7 additions & 0 deletions
7
packages/game-app/src/_shared/requests-status/requestsKeys.ts
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* @packageDocumentation | ||
*/ | ||
|
||
export interface RequestsKeys { | ||
signup: null; | ||
} |
19 changes: 19 additions & 0 deletions
19
packages/game-app/src/_shared/requests-status/sagaIntegrations.ts
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { RequestsKeys } from './requestsKeys'; | ||
import { call, put } from 'redux-saga/effects'; | ||
import { actions as loadingActions } from './index'; | ||
import { SagaIterator } from 'redux-saga'; | ||
|
||
export function addRequestStatusManagement<T = any, Fn extends (...args: any[]) => SagaIterator<T> = () => any>( | ||
gen: Fn, | ||
requestKey: keyof RequestsKeys, | ||
) { | ||
return function* composed(...args: Parameters<Fn>) { | ||
try { | ||
yield put(loadingActions.startRequest(requestKey)); | ||
yield call(gen, ...args); | ||
yield put(loadingActions.requestSuccess(requestKey)); | ||
} catch (e) { | ||
yield put(loadingActions.requestError({ key: requestKey, error: e })); | ||
} | ||
}; | ||
} |
13 changes: 13 additions & 0 deletions
13
packages/game-app/src/_shared/requests-status/selectors.ts
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { createSelector } from 'reselect'; | ||
import { State as RequestsState, name } from './slice'; | ||
import { RequestsKeys } from './requestsKeys'; | ||
|
||
type State = {} & { [name]: RequestsState }; | ||
|
||
const getRequestsStatusState = (state: State) => state[name]; | ||
|
||
export const selectRequestStatus = (key: keyof RequestsKeys) => | ||
createSelector( | ||
getRequestsStatusState, | ||
requests => requests[key] || { loading: false, error: undefined, success: false }, | ||
); |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
import { RequestsKeys } from './requestsKeys'; | ||
import { RequestStatus } from './types'; | ||
import { createSlice, PayloadAction } from '@reduxjs/toolkit'; | ||
|
||
export type State = { | ||
[key in keyof RequestsKeys]?: RequestStatus; | ||
}; | ||
|
||
const requestManagementSlice = createSlice({ | ||
name: 'requestsStatus', | ||
initialState: {} as State, | ||
reducers: { | ||
resetStatus(state, action: PayloadAction<keyof RequestsKeys>) { | ||
state[action.payload] = { | ||
loading: false, | ||
success: false, | ||
error: undefined, | ||
}; | ||
}, | ||
startRequest(state, action: PayloadAction<keyof RequestsKeys>) { | ||
state[action.payload] = { | ||
loading: true, | ||
success: false, | ||
error: undefined, | ||
}; | ||
}, | ||
requestError(state, action: PayloadAction<{ key: keyof RequestsKeys; error: { message: string; code: string } }>) { | ||
state[action.payload.key] = { | ||
loading: false, | ||
success: false, | ||
error: action.payload.error, | ||
}; | ||
}, | ||
requestSuccess(state, action: PayloadAction<keyof RequestsKeys>) { | ||
state[action.payload] = { | ||
loading: false, | ||
success: true, | ||
error: undefined, | ||
}; | ||
}, | ||
}, | ||
}); | ||
|
||
export default requestManagementSlice.reducer; | ||
|
||
export const actions = requestManagementSlice.actions; | ||
|
||
export const name = requestManagementSlice.name; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
export interface RequestStatus { | ||
loading: boolean; | ||
error?: { | ||
message: string; | ||
code: string; | ||
}; | ||
success: boolean; | ||
} | ||
|
||
export type GeneralHookResponse<T extends Array<any>> = { | ||
loading: boolean; | ||
success: boolean; | ||
error?: { message: string; code: string }; | ||
translatedError?: string; | ||
call: (...args: T) => void; | ||
reset: () => void; | ||
}; |
This file contains 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
This file contains 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