Client - error message style (wip)

Need some updates api side.
This commit is contained in:
Sam 2021-08-15 10:50:39 +02:00
parent 4bbfb800cb
commit 6c770ed76b
15 changed files with 114 additions and 27 deletions

View File

@ -0,0 +1,41 @@
<template>
<div class="error-message">
<ul v-if="Array.isArray(message)">
<li v-for="(submessage, index) in message" :key="index">
{{ t(submessage) }}
</li>
</ul>
<div v-else>{{ t(message) }}</div>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
import { useI18n } from 'vue-i18n'
export default defineComponent({
name: 'ErrorMessage',
props: {
message: [String, Array],
},
setup() {
const { t } = useI18n()
return {
t,
}
},
})
</script>
<style scoped lang="scss">
@import '~@/scss/base';
.error-message {
background: var(--error-background-color);
color: var(--error-color);
border-radius: 4px;
margin: $default-margin;
padding: $default-padding;
}
</style>

View File

@ -36,9 +36,7 @@
</div>
<button type="submit">{{ t(buttonText) }}</button>
</form>
<p v-if="errorMessage">
{{ errorMessage }}
</p>
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
</div>
</div>
</div>
@ -51,9 +49,13 @@
import { IFormData } from '@/interfaces'
import { ROOT_STORE, USER_STORE } from '@/store/constants'
import { useStore } from '@/use/useStore'
import ErrorMessage from '@/components/Common/ErrorMessage.vue'
export default defineComponent({
name: 'LoginForm',
components: {
ErrorMessage,
},
props: {
action: {
type: String,
@ -73,8 +75,8 @@
const buttonText: ComputedRef<string> = computed(() =>
props.action === 'register' ? 'buttons.REGISTER' : 'buttons.LOGIN'
)
const errorMessage: ComputedRef<string | null> = computed(
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGE]
const errorMessages: ComputedRef<string | string[] | null> = computed(
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
)
function onSubmit(actionType: string) {
@ -87,7 +89,7 @@
return {
t,
buttonText,
errorMessage,
errorMessages,
formData,
onSubmit,
}
@ -119,6 +121,7 @@
@media screen and (max-width: $medium-limit) {
height: auto;
margin-bottom: 50px;
}
}
</style>

View File

@ -0,0 +1,10 @@
{
"ERROR": {
"UNKNOWN": "Error. Please try again or contact the administrator.",
"Invalid credentials": "Invalid credentials.",
"Password and password confirmation don't match": "Password and password confirmation don't match.",
"Password: 8 characters required": "Password: 8 characters required.",
"Username: 3 to 12 characters required": "Username: 3 to 12 characters required.",
"Valid email must be provided": "Valid email must be provided."
}
}

View File

@ -1,4 +1,5 @@
import AdministrationTranslations from './administration.json'
import ApiTranslations from './api.json'
import ButtonsTranslations from './buttons.json'
import CommonTranslations from './common.json'
import DashboardTranslations from './dashboard.json'
@ -9,6 +10,7 @@ import WorkoutsTranslations from './workouts.json'
export default {
administration: AdministrationTranslations,
api: ApiTranslations,
buttons: ButtonsTranslations,
common: CommonTranslations,
dashboard: DashboardTranslations,

View File

@ -0,0 +1,10 @@
{
"ERROR": {
"UNKNOWN": "Erreur. Veuillez réessayer ou contacter l'administrateur.",
"Invalid credentials": "Identifiants invalides.",
"Password and password confirmation don't match": "Les mots de passe saisis sont différents.",
"Password: 8 characters required": "8 caractères minimum pour le mot de passe.",
"Username: 3 to 12 characters required": "3 à 12 caractères requis pour le nom.",
"Valid email must be provided": "L'email fourni n'est pas valide."
}
}

View File

@ -1,4 +1,5 @@
import AdministrationTranslations from './administration.json'
import ApiTranslations from './api.json'
import ButtonsTranslations from './buttons.json'
import CommonTranslations from './common.json'
import DashboardTranslations from './dashboard.json'
@ -9,6 +10,7 @@ import WorkoutsTranslations from './workouts.json'
export default {
administration: AdministrationTranslations,
api: ApiTranslations,
buttons: ButtonsTranslations,
common: CommonTranslations,
dashboard: DashboardTranslations,

View File

@ -14,4 +14,7 @@
--footer-border-color: #ebeef3;
--footer-color: #8b8c8c;
--error-background-color: #ffd2d2;
--error-color: #db1924;
}

View File

@ -1,10 +1,10 @@
export enum RootGetters {
ERROR_MESSAGE = 'ERROR_MESSAGE',
ERROR_MESSAGES = 'ERROR_MESSAGES',
LANGUAGE = 'LANGUAGE',
}
export enum RootMutations {
EMPTY_ERROR_MESSAGE = 'EMPTY_ERROR_MESSAGE',
SET_ERROR_MESSAGE = 'SET_ERROR_MESSAGE',
EMPTY_ERROR_MESSAGES = 'EMPTY_ERROR_MESSAGES',
SET_ERROR_MESSAGES = 'SET_ERROR_MESSAGES',
UPDATE_LANG = 'UPDATE_LANG',
}

View File

@ -4,8 +4,8 @@ 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
[ROOT_STORE.GETTERS.ERROR_MESSAGES]: (state: IRootState) => {
return state.errorMessages
},
[ROOT_STORE.GETTERS.LANGUAGE]: (state: IRootState) => {
return state.language

View File

@ -3,10 +3,12 @@ import { ROOT_STORE } from '@/store/constants'
export interface IRootState {
root: boolean
language: string
errorMessage: string | null
errorMessages: string | string[] | null
}
export interface IRootGetters {
[ROOT_STORE.GETTERS.ERROR_MESSAGE](state: IRootState): string | null
[ROOT_STORE.GETTERS.ERROR_MESSAGES](
state: IRootState
): string | string[] | null
[ROOT_STORE.GETTERS.LANGUAGE](state: IRootState): string
}

View File

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

View File

@ -3,5 +3,5 @@ import { IRootState } from '@/store/modules/root/interfaces'
export const state: IRootState = {
root: true,
language: 'en',
errorMessage: null,
errorMessages: null,
}

View File

@ -4,8 +4,11 @@ import { ROOT_STORE } from '@/store/constants'
import { IRootGetters, IRootState } from '@/store/modules/root/interfaces'
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.EMPTY_ERROR_MESSAGES](state: S): void
[ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGES](
state: S,
errorMessages: string
): void
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: S, language: string): void
}

View File

@ -30,7 +30,7 @@ export const actions: ActionTree<IUserState, IRootState> & IUserActions = {
[USER_STORE.ACTIONS.GET_USER_PROFILE](
context: ActionContext<IUserState, IRootState>
): void {
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGE)
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
authApi
.get('auth/profile')
.then((res) => {
@ -49,7 +49,7 @@ export const actions: ActionTree<IUserState, IRootState> & IUserActions = {
context: ActionContext<IUserState, IRootState>,
data: ILoginOrRegisterData
): void {
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGE)
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
api
.post(`/auth/${data.actionType}`, data.formData)
.then((res) => {
@ -71,7 +71,7 @@ export const actions: ActionTree<IUserState, IRootState> & IUserActions = {
): void {
localStorage.removeItem('authToken')
context.commit(USER_STORE.MUTATIONS.CLEAR_AUTH_USER_TOKEN)
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGE)
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
router.push('/login')
},
}

View File

@ -10,12 +10,15 @@ export const getApiUrl = (): string => {
: 'http://localhost:5000/api'
}
// TODO: update api error messages to remove these workarounds
const removeLastEndOfLine = (text: string): string => text.replace(/\n$/gm, '')
const removeLastDot = (text: string): string => text.replace(/\.$/gm, '')
export const handleError = (
context: ActionContext<IUserState, IRootState>,
error: AxiosError | null,
msg = 'error.UNKNOWN'
msg = 'UNKNOWN'
): void => {
const errorMessage = !error
let errorMessages = !error
? msg
: error.response
? error.response.data.message
@ -24,5 +27,13 @@ export const handleError = (
: error.message
? error.message
: msg
context.commit(ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGE, errorMessage)
errorMessages = removeLastEndOfLine(errorMessages)
context.commit(
ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGES,
errorMessages.includes('\n')
? errorMessages
.split('\n')
.map((m: string) => `api.ERROR.${removeLastDot(m)}`)
: `api.ERROR.${removeLastDot(errorMessages)}`
)
}