feat: add fake auth store
This commit is contained in:
parent
4004d8aa2e
commit
2ea16d8d12
@ -6,13 +6,15 @@
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vue-tsc -b && vite build",
|
||||
"preview": "vite preview"
|
||||
"preview": "vite preview",
|
||||
"lint": "eslint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@vee-validate/zod": "^4.15.0",
|
||||
"vee-validate": "^4.15.0",
|
||||
"vue": "3.5.13",
|
||||
"vue-router": "4.5.0",
|
||||
"vuex": "^4.0.2",
|
||||
"zod": "^3.24.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@ -20,6 +20,9 @@ importers:
|
||||
vue-router:
|
||||
specifier: 4.5.0
|
||||
version: 4.5.0(vue@3.5.13(typescript@5.7.3))
|
||||
vuex:
|
||||
specifier: ^4.0.2
|
||||
version: 4.0.2(vue@3.5.13(typescript@5.7.3))
|
||||
zod:
|
||||
specifier: ^3.24.1
|
||||
version: 3.24.1
|
||||
@ -945,6 +948,11 @@ packages:
|
||||
typescript:
|
||||
optional: true
|
||||
|
||||
vuex@4.0.2:
|
||||
resolution: {integrity: sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==}
|
||||
peerDependencies:
|
||||
vue: ^3.0.2
|
||||
|
||||
which@2.0.2:
|
||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||
engines: {node: '>= 8'}
|
||||
@ -1769,6 +1777,11 @@ snapshots:
|
||||
optionalDependencies:
|
||||
typescript: 5.7.3
|
||||
|
||||
vuex@4.0.2(vue@3.5.13(typescript@5.7.3)):
|
||||
dependencies:
|
||||
'@vue/devtools-api': 6.6.4
|
||||
vue: 3.5.13(typescript@5.7.3)
|
||||
|
||||
which@2.0.2:
|
||||
dependencies:
|
||||
isexe: 2.0.0
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
</router-link>
|
||||
</li>
|
||||
<li>
|
||||
<router-link to="/">
|
||||
<router-link :to="PAGE_URL[PAGE.HELP]">
|
||||
Помощь
|
||||
</router-link>
|
||||
</li>
|
||||
@ -17,15 +17,28 @@
|
||||
<a href="#">Сообщения</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#">Выход</a>
|
||||
<a
|
||||
href="#"
|
||||
@click.prevent="onExit"
|
||||
>
|
||||
Выход
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
<script setup>
|
||||
import { useStore } from 'vuex';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { PAGE, PAGE_URL } from '../router';
|
||||
|
||||
|
||||
const store = useStore();
|
||||
const router = useRouter();
|
||||
const onExit = () => {
|
||||
store.dispatch('auth/logout');
|
||||
router.push({name: PAGE.AUTH});
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { useStore } from 'vuex';
|
||||
import * as z from 'zod';
|
||||
import { useField, useForm } from 'vee-validate';
|
||||
import { toTypedSchema } from '@vee-validate/zod';
|
||||
import { computed, watch } from 'vue';
|
||||
import router, { PAGE } from '../router';
|
||||
|
||||
const useLoginForm = () => {
|
||||
const store = useStore();
|
||||
const schema = z.object({
|
||||
email: z
|
||||
.string()
|
||||
@ -23,8 +26,9 @@ const useLoginForm = () => {
|
||||
validationSchema: toTypedSchema(schema)
|
||||
});
|
||||
|
||||
const onSubmit = handleSubmit((values) => {
|
||||
console.log(values);
|
||||
const onSubmit = handleSubmit(async (values) => {
|
||||
await store.dispatch('auth/login', values);
|
||||
await router.push({name: PAGE.HOME});
|
||||
})
|
||||
|
||||
const {value: email, errorMessage: eError, handleBlur: eBlur} = useField('email');
|
||||
|
||||
@ -2,7 +2,9 @@ import { createApp } from 'vue'
|
||||
import './style.css';
|
||||
import App from './App.vue'
|
||||
import router from './router';
|
||||
import store from './store';
|
||||
|
||||
createApp(App)
|
||||
.use(router)
|
||||
.use(store)
|
||||
.mount('#app');
|
||||
|
||||
@ -1,28 +1,43 @@
|
||||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import store from '../store';
|
||||
|
||||
export enum PAGE {
|
||||
HOME= 'Home',
|
||||
AUTH = 'Auth',
|
||||
HELP = 'Help'
|
||||
}
|
||||
|
||||
export const PAGE_URL: Record<PAGE, string> = {
|
||||
[PAGE.HOME]: '/',
|
||||
[PAGE.AUTH]: '/auth',
|
||||
[PAGE.HELP]: '/help'
|
||||
}
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Home',
|
||||
component: () => import('../views/Home.vue'),
|
||||
path: PAGE_URL[PAGE.HOME],
|
||||
name: PAGE.HOME,
|
||||
component: () => import('../views/HomePage.vue'),
|
||||
meta: {
|
||||
layout: 'main'
|
||||
layout: 'main',
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/help',
|
||||
name: 'Help',
|
||||
component: () => import('../views/Help.vue'),
|
||||
path: PAGE_URL[PAGE.HELP],
|
||||
name: PAGE.HELP,
|
||||
component: () => import('../views/HelpPage.vue'),
|
||||
meta: {
|
||||
layout: 'main'
|
||||
layout: 'main',
|
||||
auth: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/auth',
|
||||
name: 'Auth',
|
||||
component: () => import('../views/Auth.vue'),
|
||||
path: PAGE_URL[PAGE.AUTH],
|
||||
name: PAGE.AUTH,
|
||||
component: () => import('../views/AuthPage.vue'),
|
||||
meta: {
|
||||
layout: 'auth'
|
||||
layout: 'auth',
|
||||
}
|
||||
},
|
||||
]
|
||||
@ -32,5 +47,18 @@ const router = createRouter({
|
||||
routes,
|
||||
});
|
||||
|
||||
router.beforeEach((to, from, next) => {
|
||||
const requiredAuth = to.meta.auth;
|
||||
if (!requiredAuth) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (store.getters['auth/iseAuth']) {
|
||||
next();
|
||||
} else {
|
||||
next('/auth?message=auth-required');
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
export default router;
|
||||
|
||||
15
src/store/index.ts
Normal file
15
src/store/index.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { createLogger, createStore } from 'vuex'
|
||||
import authModule from './modules/auth.module.ts';
|
||||
|
||||
const isDev = process.env.NODE_ENV === 'development';
|
||||
|
||||
const store = createStore({
|
||||
plugins: [
|
||||
isDev && createLogger()
|
||||
].filter(Boolean),
|
||||
modules: {
|
||||
auth: authModule
|
||||
},
|
||||
})
|
||||
|
||||
export default store;
|
||||
49
src/store/modules/auth.module.ts
Normal file
49
src/store/modules/auth.module.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import type { Module } from 'vuex';
|
||||
|
||||
const LOCAL_STORAGE_KEY = 'jwt-token';
|
||||
|
||||
const authModule: Module<any, any> = {
|
||||
namespaced: true,
|
||||
state: {
|
||||
token: localStorage.getItem(LOCAL_STORAGE_KEY)
|
||||
},
|
||||
mutations: {
|
||||
setToken(state, payload) {
|
||||
state.token = payload;
|
||||
|
||||
localStorage.setItem(LOCAL_STORAGE_KEY, payload)
|
||||
},
|
||||
removeToken(state) {
|
||||
state.token = null;
|
||||
|
||||
localStorage.removeItem(LOCAL_STORAGE_KEY)
|
||||
},
|
||||
},
|
||||
actions: {
|
||||
async login(context, payload) {
|
||||
const { commit } = context;
|
||||
const token = await new Promise((res) => {
|
||||
setTimeout(() => {
|
||||
const token = payload.email + payload.password;
|
||||
res(token);
|
||||
}, 1500)
|
||||
});
|
||||
commit('setToken', token);
|
||||
},
|
||||
logout(context) {
|
||||
const { commit } = context;
|
||||
|
||||
commit('removeToken');
|
||||
}
|
||||
},
|
||||
getters: {
|
||||
token: (state) => {
|
||||
return state.token;
|
||||
},
|
||||
iseAuth: (state) => {
|
||||
return Boolean(state.token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default authModule;
|
||||
6
src/vuex.d.ts
vendored
Normal file
6
src/vuex.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
declare module "vuex" {
|
||||
export * from "vuex/types/index.d.ts";
|
||||
export * from "vuex/types/helpers.d.ts";
|
||||
export * from "vuex/types/logger.d.ts";
|
||||
export * from "vuex/types/vue.d.ts";
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user