Client - handle error on api calls

This commit is contained in:
Sam 2021-08-11 21:12:20 +02:00
parent cd418c9be2
commit 7df5ea9870
14 changed files with 87 additions and 15 deletions

View File

@ -43,11 +43,12 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent, reactive, ref } from 'vue' import { computed, defineComponent, reactive } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import { useStore } from 'vuex' import { useStore } from 'vuex'
import { IFormData } from '@/interfaces.ts' import { IFormData } from '@/interfaces.ts'
import { USER_STORE } from '@/store/constants' import { ROOT_STORE, USER_STORE } from '@/store/constants'
export default defineComponent({ export default defineComponent({
name: 'UserForm', name: 'UserForm',
@ -75,7 +76,9 @@
} }
return { return {
errorMessage: ref(null), errorMessage: computed(
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGE]
),
t, t,
formData, formData,
onSubmit, onSubmit,

View File

@ -1,5 +1,6 @@
{ {
"not-found": { "UNKNOWN": "Error. Please try again or contact the administrator.",
"NOT_FOUND": {
"PAGE": "Page not found" "PAGE": "Page not found"
} }
} }

View File

@ -1,5 +1,6 @@
{ {
"not-found": { "UNKNOWN": "Erreur. Veuillez réessayer ou contacter l'administrateur.",
"NOT_FOUND": {
"PAGE": "Page introuvable" "PAGE": "Page introuvable"
} }
} }

View File

@ -1,4 +1,4 @@
import { RootMutations } from '@/store/modules/root/enums' import { RootGetters, RootMutations } from '@/store/modules/root/enums'
import { import {
UserActions, UserActions,
UserGetters, UserGetters,
@ -6,6 +6,7 @@ import {
} from '@/store/modules/user/enums' } from '@/store/modules/user/enums'
export const ROOT_STORE = { export const ROOT_STORE = {
GETTERS: RootGetters,
MUTATIONS: RootMutations, MUTATIONS: RootMutations,
} }

View File

@ -1,3 +1,9 @@
export enum RootGetters {
ERROR_MESSAGE = 'ERROR_MESSAGE',
}
export enum RootMutations { export enum RootMutations {
EMPTY_ERROR_MESSAGE = 'EMPTY_ERROR_MESSAGE',
SET_ERROR_MESSAGE = 'SET_ERROR_MESSAGE',
UPDATE_LANG = 'UPDATE_LANG', UPDATE_LANG = 'UPDATE_LANG',
} }

View File

@ -0,0 +1,9 @@
import { GetterTree } from 'vuex'
import { ROOT_STORE } from '@/store/constants'
import { IRootState, IRootGetters } from '@/store/modules/root/interfaces'
export const getters: GetterTree<IRootState, IRootState> & IRootGetters = {
[ROOT_STORE.GETTERS.ERROR_MESSAGE]: (state: IRootState) => {
return state.errorMessage
},
}

View File

@ -1,4 +1,5 @@
import { Module, ModuleTree } from 'vuex' import { Module, ModuleTree } from 'vuex'
import { getters } from '@/store/modules/root/getters'
import { IRootState } from '@/store/modules/root/interfaces' import { IRootState } from '@/store/modules/root/interfaces'
import { mutations } from '@/store/modules/root/mutations' import { mutations } from '@/store/modules/root/mutations'
import { state } from '@/store/modules/root/state.ts' import { state } from '@/store/modules/root/state.ts'
@ -10,6 +11,7 @@ const modules: ModuleTree<IRootState> = {
const root: Module<IRootState, IRootState> = { const root: Module<IRootState, IRootState> = {
state, state,
getters,
mutations, mutations,
modules, modules,
} }

View File

@ -1,5 +1,11 @@
import { ROOT_STORE } from '@/store/constants'
export interface IRootState { export interface IRootState {
root: boolean root: boolean
language: string language: string
errorMessage: string | null errorMessage: string | null
} }
export interface IRootGetters {
[ROOT_STORE.GETTERS.ERROR_MESSAGE](state: IRootState): string | null
}

View File

@ -4,6 +4,15 @@ import { IRootState } from '@/store/modules/root/interfaces'
import { TRootMutations } from '@/store/modules/root/types' import { TRootMutations } from '@/store/modules/root/types'
export const mutations: MutationTree<IRootState> & TRootMutations = { export const mutations: MutationTree<IRootState> & TRootMutations = {
[ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGE](state: IRootState) {
state.errorMessage = null
},
[ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGE](
state: IRootState,
errorMessage: string
) {
state.errorMessage = errorMessage
},
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: IRootState, language: string) { [ROOT_STORE.MUTATIONS.UPDATE_LANG](state: IRootState, language: string) {
state.language = language state.language = language
}, },

View File

@ -2,5 +2,7 @@ import { ROOT_STORE } from '@/store/constants'
import { IRootState } from '@/store/modules/root/interfaces' import { IRootState } from '@/store/modules/root/interfaces'
export type TRootMutations<S = IRootState> = { export type TRootMutations<S = IRootState> = {
[ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGE](state: S): void
[ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGE](state: S, errorMessage: string): void
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: S, language: string): void [ROOT_STORE.MUTATIONS.UPDATE_LANG](state: S, language: string): void
} }

View File

@ -1,9 +1,12 @@
import { ActionContext, ActionTree } from 'vuex' import { ActionContext, ActionTree } from 'vuex'
import { USER_STORE } from '@/store/constants' import { ROOT_STORE, USER_STORE } from '@/store/constants'
import { IUserActions } from '@/store/modules/user/interfaces' import {
import { IUserState } from '@/store/modules/user/interfaces' ILoginOrRegisterData,
IUserActions,
IUserState,
} from '@/store/modules/user/interfaces'
import { IRootState } from '@/store/modules/root/interfaces' import { IRootState } from '@/store/modules/root/interfaces'
import { ILoginOrRegisterData } from '@/store/modules/user/interfaces' import { handleError } from '@/utils'
import api from '@/api/defaultApi' import api from '@/api/defaultApi'
import authApi from '@/api/authApi' import authApi from '@/api/authApi'
import router from '@/router' import router from '@/router'
@ -12,6 +15,7 @@ export const actions: ActionTree<IUserState, IRootState> & IUserActions = {
[USER_STORE.ACTIONS.GET_USER_PROFILE]( [USER_STORE.ACTIONS.GET_USER_PROFILE](
context: ActionContext<IUserState, IRootState> context: ActionContext<IUserState, IRootState>
): void { ): void {
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGE)
authApi authApi
.get('auth/profile') .get('auth/profile')
.then((res) => { .then((res) => {
@ -20,26 +24,31 @@ export const actions: ActionTree<IUserState, IRootState> & IUserActions = {
USER_STORE.MUTATIONS.UPDATE_AUTH_USER_PROFILE, USER_STORE.MUTATIONS.UPDATE_AUTH_USER_PROFILE,
res.data.data res.data.data
) )
} else {
handleError(context, null)
} }
}) })
.catch((err) => console.log(err)) .catch((error) => handleError(context, error))
}, },
[USER_STORE.ACTIONS.LOGIN_OR_REGISTER]( [USER_STORE.ACTIONS.LOGIN_OR_REGISTER](
context: ActionContext<IUserState, IRootState>, context: ActionContext<IUserState, IRootState>,
data: ILoginOrRegisterData data: ILoginOrRegisterData
): void { ): void {
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGE)
api api
.post(`/auth/${data.actionType}`, data.formData) .post(`/auth/${data.actionType}`, data.formData)
.then((res) => { .then((res) => {
if (res.status == 200 && res.data.status === 'success') { if (res.data.status === 'success') {
const token = res.data.auth_token const token = res.data.auth_token
window.localStorage.setItem('authToken', token) window.localStorage.setItem('authToken', token)
context.commit(USER_STORE.MUTATIONS.UPDATE_AUTH_TOKEN, token) context.commit(USER_STORE.MUTATIONS.UPDATE_AUTH_TOKEN, token)
context context
.dispatch(USER_STORE.ACTIONS.GET_USER_PROFILE) .dispatch(USER_STORE.ACTIONS.GET_USER_PROFILE)
.then(() => router.push('/')) .then(() => router.push('/'))
} else {
handleError(context, null)
} }
}) })
.catch((err) => console.log(err)) .catch((error) => handleError(context, error))
}, },
} }

View File

@ -37,7 +37,7 @@ export interface IUserState {
} }
export interface IUserGetters { export interface IUserGetters {
[USER_STORE.GETTERS.AUTH_TOKEN](state: IUserState): string [USER_STORE.GETTERS.AUTH_TOKEN](state: IUserState): string | null
[USER_STORE.GETTERS.IS_AUTHENTICATED](state: IUserState): boolean [USER_STORE.GETTERS.IS_AUTHENTICATED](state: IUserState): boolean
} }

View File

@ -1,5 +1,28 @@
import { AxiosError } from 'axios'
import { ActionContext } from 'vuex'
import { ROOT_STORE } from '@/store/constants'
import { IUserState } from '@/store/modules/user/interfaces'
import { IRootState } from '@/store/modules/root/interfaces'
export const getApiUrl = (): string => { export const getApiUrl = (): string => {
return process.env.NODE_ENV === 'production' return process.env.NODE_ENV === 'production'
? '/api' ? '/api'
: 'http://localhost:5000/api' : 'http://localhost:5000/api'
} }
export const handleError = (
context: ActionContext<IUserState, IRootState>,
error: AxiosError | null,
msg = 'error.UNKNOWN'
): void => {
const errorMessage = !error
? msg
: error.response
? error.response.data.message
? error.response.data.message
: msg
: error.message
? error.message
: msg
context.commit(ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGE, errorMessage)
}

View File

@ -2,7 +2,7 @@
<div class="not-found"> <div class="not-found">
<Error <Error
title="404" title="404"
:message="t('error.not-found.PAGE')" :message="t('error.NOT_FOUND.PAGE')"
:button-text="t('common.HOME')" :button-text="t('common.HOME')"
/> />
</div> </div>