feat: add alerts

This commit is contained in:
Sergey Krylov 2025-02-05 07:50:03 +03:00
parent 2ed124c918
commit 002f8d1b18
8 changed files with 118 additions and 7 deletions

View 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"
>
&times;
</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>

View File

@ -27,8 +27,10 @@ const useLoginForm = () => {
});
const onSubmit = handleSubmit(async (values) => {
try {
await store.dispatch('auth/login', values);
await router.push({name: PAGE.HOME});
} catch (e) {}
})
const {value: email, errorMessage: eError, handleBlur: eBlur} = useField('email');

View File

@ -1,5 +1,6 @@
<template>
<div class="container">
<app-alert />
<div class="card">
<router-view />
</div>
@ -7,8 +8,11 @@
</template>
<script>
export default {
import AppAlert from '../components/ui/AppAlert.vue';
export default {
components: {AppAlert},
}
</script>

View File

@ -1,5 +1,6 @@
import { createLogger, createStore } from 'vuex'
import authModule from './modules/auth.module.ts';
import alertModule from './modules/alert.module.ts';
const isDev = process.env.NODE_ENV === 'development';
@ -8,7 +9,8 @@ const store = createStore({
isDev && createLogger()
].filter(Boolean),
modules: {
auth: authModule
auth: authModule,
alert: alertModule,
},
})

View 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;

View File

@ -23,7 +23,7 @@ const authModule: Module<any, any> = {
},
actions: {
async login(context, payload: {email: string, password: string}) {
const { commit } = context;
const { commit, dispatch } = context;
try {
const { data } = await authApi.login({
email: payload.email,
@ -34,8 +34,12 @@ const authModule: Module<any, any> = {
commit('setToken', data.idToken);
} catch (e) {
// @ts-ignore
const message = e.response?.data.error.message as keyof typeof ERROR_MESSAGES;
alert(ERROR_MESSAGES?.[message] || 'Ошибка при попытке авторизации');
const errorKey = e.response?.data.error.message as keyof typeof ERROR_MESSAGES;
const errorMessage = ERROR_MESSAGES[errorKey] || 'Ошибка при попытке авторизации'
await dispatch('alert/setAlert', { message: errorMessage, type: 'danger', title: 'Ошибка авторизации', time: 5000 }, {root: true})
throw new Error(errorMessage)
}
},
logout(context) {

View File

@ -1,3 +1,4 @@
export const ERROR_MESSAGES = {
'INVALID_LOGIN_CREDENTIALS': 'Неправильный логин или пароль',
'auth-required': 'Требуется авторизация',
}

View File

@ -54,7 +54,21 @@
<script setup>
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 {
disabled,
eBlur,