Client - error message style (wip)
Need some updates api side.
This commit is contained in:
parent
4bbfb800cb
commit
6c770ed76b
41
fittrackee_client/src/components/Common/ErrorMessage.vue
Normal file
41
fittrackee_client/src/components/Common/ErrorMessage.vue
Normal 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>
|
@ -36,9 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<button type="submit">{{ t(buttonText) }}</button>
|
<button type="submit">{{ t(buttonText) }}</button>
|
||||||
</form>
|
</form>
|
||||||
<p v-if="errorMessage">
|
<ErrorMessage :message="errorMessages" v-if="errorMessages" />
|
||||||
{{ errorMessage }}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -51,9 +49,13 @@
|
|||||||
import { IFormData } from '@/interfaces'
|
import { IFormData } from '@/interfaces'
|
||||||
import { ROOT_STORE, USER_STORE } from '@/store/constants'
|
import { ROOT_STORE, USER_STORE } from '@/store/constants'
|
||||||
import { useStore } from '@/use/useStore'
|
import { useStore } from '@/use/useStore'
|
||||||
|
import ErrorMessage from '@/components/Common/ErrorMessage.vue'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'LoginForm',
|
name: 'LoginForm',
|
||||||
|
components: {
|
||||||
|
ErrorMessage,
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
action: {
|
action: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -73,8 +75,8 @@
|
|||||||
const buttonText: ComputedRef<string> = computed(() =>
|
const buttonText: ComputedRef<string> = computed(() =>
|
||||||
props.action === 'register' ? 'buttons.REGISTER' : 'buttons.LOGIN'
|
props.action === 'register' ? 'buttons.REGISTER' : 'buttons.LOGIN'
|
||||||
)
|
)
|
||||||
const errorMessage: ComputedRef<string | null> = computed(
|
const errorMessages: ComputedRef<string | string[] | null> = computed(
|
||||||
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGE]
|
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||||
)
|
)
|
||||||
|
|
||||||
function onSubmit(actionType: string) {
|
function onSubmit(actionType: string) {
|
||||||
@ -87,7 +89,7 @@
|
|||||||
return {
|
return {
|
||||||
t,
|
t,
|
||||||
buttonText,
|
buttonText,
|
||||||
errorMessage,
|
errorMessages,
|
||||||
formData,
|
formData,
|
||||||
onSubmit,
|
onSubmit,
|
||||||
}
|
}
|
||||||
@ -119,6 +121,7 @@
|
|||||||
|
|
||||||
@media screen and (max-width: $medium-limit) {
|
@media screen and (max-width: $medium-limit) {
|
||||||
height: auto;
|
height: auto;
|
||||||
|
margin-bottom: 50px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
10
fittrackee_client/src/locales/en/api.json
Normal file
10
fittrackee_client/src/locales/en/api.json
Normal 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."
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import AdministrationTranslations from './administration.json'
|
import AdministrationTranslations from './administration.json'
|
||||||
|
import ApiTranslations from './api.json'
|
||||||
import ButtonsTranslations from './buttons.json'
|
import ButtonsTranslations from './buttons.json'
|
||||||
import CommonTranslations from './common.json'
|
import CommonTranslations from './common.json'
|
||||||
import DashboardTranslations from './dashboard.json'
|
import DashboardTranslations from './dashboard.json'
|
||||||
@ -9,6 +10,7 @@ import WorkoutsTranslations from './workouts.json'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
administration: AdministrationTranslations,
|
administration: AdministrationTranslations,
|
||||||
|
api: ApiTranslations,
|
||||||
buttons: ButtonsTranslations,
|
buttons: ButtonsTranslations,
|
||||||
common: CommonTranslations,
|
common: CommonTranslations,
|
||||||
dashboard: DashboardTranslations,
|
dashboard: DashboardTranslations,
|
||||||
|
10
fittrackee_client/src/locales/fr/api.json
Normal file
10
fittrackee_client/src/locales/fr/api.json
Normal 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."
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import AdministrationTranslations from './administration.json'
|
import AdministrationTranslations from './administration.json'
|
||||||
|
import ApiTranslations from './api.json'
|
||||||
import ButtonsTranslations from './buttons.json'
|
import ButtonsTranslations from './buttons.json'
|
||||||
import CommonTranslations from './common.json'
|
import CommonTranslations from './common.json'
|
||||||
import DashboardTranslations from './dashboard.json'
|
import DashboardTranslations from './dashboard.json'
|
||||||
@ -9,6 +10,7 @@ import WorkoutsTranslations from './workouts.json'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
administration: AdministrationTranslations,
|
administration: AdministrationTranslations,
|
||||||
|
api: ApiTranslations,
|
||||||
buttons: ButtonsTranslations,
|
buttons: ButtonsTranslations,
|
||||||
common: CommonTranslations,
|
common: CommonTranslations,
|
||||||
dashboard: DashboardTranslations,
|
dashboard: DashboardTranslations,
|
||||||
|
@ -14,4 +14,7 @@
|
|||||||
--footer-border-color: #ebeef3;
|
--footer-border-color: #ebeef3;
|
||||||
--footer-color: #8b8c8c;
|
--footer-color: #8b8c8c;
|
||||||
|
|
||||||
|
--error-background-color: #ffd2d2;
|
||||||
|
--error-color: #db1924;
|
||||||
|
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
export enum RootGetters {
|
export enum RootGetters {
|
||||||
ERROR_MESSAGE = 'ERROR_MESSAGE',
|
ERROR_MESSAGES = 'ERROR_MESSAGES',
|
||||||
LANGUAGE = 'LANGUAGE',
|
LANGUAGE = 'LANGUAGE',
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum RootMutations {
|
export enum RootMutations {
|
||||||
EMPTY_ERROR_MESSAGE = 'EMPTY_ERROR_MESSAGE',
|
EMPTY_ERROR_MESSAGES = 'EMPTY_ERROR_MESSAGES',
|
||||||
SET_ERROR_MESSAGE = 'SET_ERROR_MESSAGE',
|
SET_ERROR_MESSAGES = 'SET_ERROR_MESSAGES',
|
||||||
UPDATE_LANG = 'UPDATE_LANG',
|
UPDATE_LANG = 'UPDATE_LANG',
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ import { ROOT_STORE } from '@/store/constants'
|
|||||||
import { IRootState, IRootGetters } from '@/store/modules/root/interfaces'
|
import { IRootState, IRootGetters } from '@/store/modules/root/interfaces'
|
||||||
|
|
||||||
export const getters: GetterTree<IRootState, IRootState> & IRootGetters = {
|
export const getters: GetterTree<IRootState, IRootState> & IRootGetters = {
|
||||||
[ROOT_STORE.GETTERS.ERROR_MESSAGE]: (state: IRootState) => {
|
[ROOT_STORE.GETTERS.ERROR_MESSAGES]: (state: IRootState) => {
|
||||||
return state.errorMessage
|
return state.errorMessages
|
||||||
},
|
},
|
||||||
[ROOT_STORE.GETTERS.LANGUAGE]: (state: IRootState) => {
|
[ROOT_STORE.GETTERS.LANGUAGE]: (state: IRootState) => {
|
||||||
return state.language
|
return state.language
|
||||||
|
@ -3,10 +3,12 @@ import { ROOT_STORE } from '@/store/constants'
|
|||||||
export interface IRootState {
|
export interface IRootState {
|
||||||
root: boolean
|
root: boolean
|
||||||
language: string
|
language: string
|
||||||
errorMessage: string | null
|
errorMessages: string | string[] | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IRootGetters {
|
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
|
[ROOT_STORE.GETTERS.LANGUAGE](state: IRootState): string
|
||||||
}
|
}
|
||||||
|
@ -5,14 +5,14 @@ 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) {
|
[ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES](state: IRootState) {
|
||||||
state.errorMessage = null
|
state.errorMessages = null
|
||||||
},
|
},
|
||||||
[ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGE](
|
[ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGES](
|
||||||
state: IRootState,
|
state: IRootState,
|
||||||
errorMessage: string
|
errorMessages: string
|
||||||
) {
|
) {
|
||||||
state.errorMessage = errorMessage
|
state.errorMessages = errorMessages
|
||||||
},
|
},
|
||||||
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: IRootState, language: string) {
|
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: IRootState, language: string) {
|
||||||
state.language = language
|
state.language = language
|
||||||
|
@ -3,5 +3,5 @@ import { IRootState } from '@/store/modules/root/interfaces'
|
|||||||
export const state: IRootState = {
|
export const state: IRootState = {
|
||||||
root: true,
|
root: true,
|
||||||
language: 'en',
|
language: 'en',
|
||||||
errorMessage: null,
|
errorMessages: null,
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,11 @@ import { ROOT_STORE } from '@/store/constants'
|
|||||||
import { IRootGetters, IRootState } from '@/store/modules/root/interfaces'
|
import { IRootGetters, 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.EMPTY_ERROR_MESSAGES](state: S): void
|
||||||
[ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGE](state: S, errorMessage: string): void
|
[ROOT_STORE.MUTATIONS.SET_ERROR_MESSAGES](
|
||||||
|
state: S,
|
||||||
|
errorMessages: string
|
||||||
|
): void
|
||||||
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: S, language: string): void
|
[ROOT_STORE.MUTATIONS.UPDATE_LANG](state: S, language: string): void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,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)
|
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||||
authApi
|
authApi
|
||||||
.get('auth/profile')
|
.get('auth/profile')
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@ -49,7 +49,7 @@ export const actions: ActionTree<IUserState, IRootState> & IUserActions = {
|
|||||||
context: ActionContext<IUserState, IRootState>,
|
context: ActionContext<IUserState, IRootState>,
|
||||||
data: ILoginOrRegisterData
|
data: ILoginOrRegisterData
|
||||||
): void {
|
): void {
|
||||||
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGE)
|
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||||
api
|
api
|
||||||
.post(`/auth/${data.actionType}`, data.formData)
|
.post(`/auth/${data.actionType}`, data.formData)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
@ -71,7 +71,7 @@ export const actions: ActionTree<IUserState, IRootState> & IUserActions = {
|
|||||||
): void {
|
): void {
|
||||||
localStorage.removeItem('authToken')
|
localStorage.removeItem('authToken')
|
||||||
context.commit(USER_STORE.MUTATIONS.CLEAR_AUTH_USER_TOKEN)
|
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')
|
router.push('/login')
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,15 @@ export const getApiUrl = (): string => {
|
|||||||
: 'http://localhost:5000/api'
|
: '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 = (
|
export const handleError = (
|
||||||
context: ActionContext<IUserState, IRootState>,
|
context: ActionContext<IUserState, IRootState>,
|
||||||
error: AxiosError | null,
|
error: AxiosError | null,
|
||||||
msg = 'error.UNKNOWN'
|
msg = 'UNKNOWN'
|
||||||
): void => {
|
): void => {
|
||||||
const errorMessage = !error
|
let errorMessages = !error
|
||||||
? msg
|
? msg
|
||||||
: error.response
|
: error.response
|
||||||
? error.response.data.message
|
? error.response.data.message
|
||||||
@ -24,5 +27,13 @@ export const handleError = (
|
|||||||
: error.message
|
: error.message
|
||||||
? error.message
|
? error.message
|
||||||
: msg
|
: 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)}`
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user