feat: add alerts
This commit is contained in:
parent
2ed124c918
commit
002f8d1b18
35
src/components/ui/AppAlert.vue
Normal file
35
src/components/ui/AppAlert.vue
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="error.message"
|
||||||
|
class="alert"
|
||||||
|
:class="[error.type]"
|
||||||
|
>
|
||||||
|
<p class="alert-title">
|
||||||
|
{{ error.title }}
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
{{ error.message }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<span
|
||||||
|
class="alert-close"
|
||||||
|
@click="onClose"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { useStore } from 'vuex';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
const store = useStore();
|
||||||
|
const error = computed(() => store.state.alert);
|
||||||
|
|
||||||
|
const onClose = () => store.commit('alert/clearAlert');
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -27,8 +27,10 @@ const useLoginForm = () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = handleSubmit(async (values) => {
|
const onSubmit = handleSubmit(async (values) => {
|
||||||
await store.dispatch('auth/login', values);
|
try {
|
||||||
await router.push({name: PAGE.HOME});
|
await store.dispatch('auth/login', values);
|
||||||
|
await router.push({name: PAGE.HOME});
|
||||||
|
} catch (e) {}
|
||||||
})
|
})
|
||||||
|
|
||||||
const {value: email, errorMessage: eError, handleBlur: eBlur} = useField('email');
|
const {value: email, errorMessage: eError, handleBlur: eBlur} = useField('email');
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
<app-alert />
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<router-view />
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
@ -7,8 +8,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default {
|
|
||||||
|
|
||||||
|
import AppAlert from '../components/ui/AppAlert.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {AppAlert},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
import { createLogger, createStore } from 'vuex'
|
import { createLogger, createStore } from 'vuex'
|
||||||
import authModule from './modules/auth.module.ts';
|
import authModule from './modules/auth.module.ts';
|
||||||
|
import alertModule from './modules/alert.module.ts';
|
||||||
|
|
||||||
const isDev = process.env.NODE_ENV === 'development';
|
const isDev = process.env.NODE_ENV === 'development';
|
||||||
|
|
||||||
@ -8,7 +9,8 @@ const store = createStore({
|
|||||||
isDev && createLogger()
|
isDev && createLogger()
|
||||||
].filter(Boolean),
|
].filter(Boolean),
|
||||||
modules: {
|
modules: {
|
||||||
auth: authModule
|
auth: authModule,
|
||||||
|
alert: alertModule,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
49
src/store/modules/alert.module.ts
Normal file
49
src/store/modules/alert.module.ts
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import type { Module } from 'vuex';
|
||||||
|
|
||||||
|
type State = {
|
||||||
|
title: string | null;
|
||||||
|
message: string | null;
|
||||||
|
type: 'danger' | 'warning' | 'primary' | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
type SetAlertPayload = {
|
||||||
|
time?: number;
|
||||||
|
title: Required<State['title']>;
|
||||||
|
message: Required<State['message']>;
|
||||||
|
type: Required<State['type']>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const alertModule: Module<State, any> = {
|
||||||
|
namespaced: true,
|
||||||
|
state: {
|
||||||
|
title: null,
|
||||||
|
message: null,
|
||||||
|
type: null,
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
setAlert(state, payload: SetAlertPayload) {
|
||||||
|
state.message = payload.message;
|
||||||
|
state.type = payload.type
|
||||||
|
state.title = payload.title
|
||||||
|
},
|
||||||
|
clearAlert(state) {
|
||||||
|
state.message = null;
|
||||||
|
state.type = null;
|
||||||
|
state.title = null;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setAlert: async (context, payload: SetAlertPayload) => {
|
||||||
|
const { commit } = context;
|
||||||
|
const { time = 3000, ...restPayload } = payload;
|
||||||
|
|
||||||
|
commit('setAlert', restPayload);
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
commit('clearAlert');
|
||||||
|
}, time)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default alertModule;
|
||||||
@ -23,7 +23,7 @@ const authModule: Module<any, any> = {
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async login(context, payload: {email: string, password: string}) {
|
async login(context, payload: {email: string, password: string}) {
|
||||||
const { commit } = context;
|
const { commit, dispatch } = context;
|
||||||
try {
|
try {
|
||||||
const { data } = await authApi.login({
|
const { data } = await authApi.login({
|
||||||
email: payload.email,
|
email: payload.email,
|
||||||
@ -34,8 +34,12 @@ const authModule: Module<any, any> = {
|
|||||||
commit('setToken', data.idToken);
|
commit('setToken', data.idToken);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const message = e.response?.data.error.message as keyof typeof ERROR_MESSAGES;
|
const errorKey = e.response?.data.error.message as keyof typeof ERROR_MESSAGES;
|
||||||
alert(ERROR_MESSAGES?.[message] || 'Ошибка при попытке авторизации');
|
const errorMessage = ERROR_MESSAGES[errorKey] || 'Ошибка при попытке авторизации'
|
||||||
|
|
||||||
|
await dispatch('alert/setAlert', { message: errorMessage, type: 'danger', title: 'Ошибка авторизации', time: 5000 }, {root: true})
|
||||||
|
|
||||||
|
throw new Error(errorMessage)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
logout(context) {
|
logout(context) {
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
export const ERROR_MESSAGES = {
|
export const ERROR_MESSAGES = {
|
||||||
'INVALID_LOGIN_CREDENTIALS': 'Неправильный логин или пароль',
|
'INVALID_LOGIN_CREDENTIALS': 'Неправильный логин или пароль',
|
||||||
|
'auth-required': 'Требуется авторизация',
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,7 +54,21 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import useLoginForm from '../hooks/useLoginForm.ts';
|
import useLoginForm from '../hooks/useLoginForm.ts';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useStore } from 'vuex';
|
||||||
|
import { ERROR_MESSAGES } from '../utils/constants.ts';
|
||||||
|
|
||||||
|
const store = useStore();
|
||||||
|
const route = useRoute();
|
||||||
|
const message = route.query.message;
|
||||||
|
if (message === 'auth-required') {
|
||||||
|
store.dispatch('alert/setAlert', {
|
||||||
|
message: ERROR_MESSAGES[message],
|
||||||
|
type: 'warning',
|
||||||
|
title: 'Ошибка',
|
||||||
|
time: 5000
|
||||||
|
})
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
disabled,
|
disabled,
|
||||||
eBlur,
|
eBlur,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user