feat: add fake auth store
This commit is contained in:
parent
4004d8aa2e
commit
2ea16d8d12
@ -6,13 +6,15 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vue-tsc -b && vite build",
|
"build": "vue-tsc -b && vite build",
|
||||||
"preview": "vite preview"
|
"preview": "vite preview",
|
||||||
|
"lint": "eslint"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@vee-validate/zod": "^4.15.0",
|
"@vee-validate/zod": "^4.15.0",
|
||||||
"vee-validate": "^4.15.0",
|
"vee-validate": "^4.15.0",
|
||||||
"vue": "3.5.13",
|
"vue": "3.5.13",
|
||||||
"vue-router": "4.5.0",
|
"vue-router": "4.5.0",
|
||||||
|
"vuex": "^4.0.2",
|
||||||
"zod": "^3.24.1"
|
"zod": "^3.24.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@ -20,6 +20,9 @@ importers:
|
|||||||
vue-router:
|
vue-router:
|
||||||
specifier: 4.5.0
|
specifier: 4.5.0
|
||||||
version: 4.5.0(vue@3.5.13(typescript@5.7.3))
|
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:
|
zod:
|
||||||
specifier: ^3.24.1
|
specifier: ^3.24.1
|
||||||
version: 3.24.1
|
version: 3.24.1
|
||||||
@ -945,6 +948,11 @@ packages:
|
|||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
|
vuex@4.0.2:
|
||||||
|
resolution: {integrity: sha512-M6r8uxELjZIK8kTKDGgZTYX/ahzblnzC4isU1tpmEuOIIKmV+TRdc+H4s8ds2NuZ7wpUTdGRzJRtoj+lI+pc0Q==}
|
||||||
|
peerDependencies:
|
||||||
|
vue: ^3.0.2
|
||||||
|
|
||||||
which@2.0.2:
|
which@2.0.2:
|
||||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
@ -1769,6 +1777,11 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.7.3
|
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:
|
which@2.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe: 2.0.0
|
isexe: 2.0.0
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<router-link to="/">
|
<router-link :to="PAGE_URL[PAGE.HELP]">
|
||||||
Помощь
|
Помощь
|
||||||
</router-link>
|
</router-link>
|
||||||
</li>
|
</li>
|
||||||
@ -17,16 +17,29 @@
|
|||||||
<a href="#">Сообщения</a>
|
<a href="#">Сообщения</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#">Выход</a>
|
<a
|
||||||
|
href="#"
|
||||||
|
@click.prevent="onExit"
|
||||||
|
>
|
||||||
|
Выход
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
export default {
|
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>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|||||||
@ -1,9 +1,12 @@
|
|||||||
|
import { useStore } from 'vuex';
|
||||||
import * as z from 'zod';
|
import * as z from 'zod';
|
||||||
import { useField, useForm } from 'vee-validate';
|
import { useField, useForm } from 'vee-validate';
|
||||||
import { toTypedSchema } from '@vee-validate/zod';
|
import { toTypedSchema } from '@vee-validate/zod';
|
||||||
import { computed, watch } from 'vue';
|
import { computed, watch } from 'vue';
|
||||||
|
import router, { PAGE } from '../router';
|
||||||
|
|
||||||
const useLoginForm = () => {
|
const useLoginForm = () => {
|
||||||
|
const store = useStore();
|
||||||
const schema = z.object({
|
const schema = z.object({
|
||||||
email: z
|
email: z
|
||||||
.string()
|
.string()
|
||||||
@ -23,8 +26,9 @@ const useLoginForm = () => {
|
|||||||
validationSchema: toTypedSchema(schema)
|
validationSchema: toTypedSchema(schema)
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = handleSubmit((values) => {
|
const onSubmit = handleSubmit(async (values) => {
|
||||||
console.log(values);
|
await store.dispatch('auth/login', values);
|
||||||
|
await router.push({name: PAGE.HOME});
|
||||||
})
|
})
|
||||||
|
|
||||||
const {value: email, errorMessage: eError, handleBlur: eBlur} = useField('email');
|
const {value: email, errorMessage: eError, handleBlur: eBlur} = useField('email');
|
||||||
|
|||||||
@ -2,7 +2,9 @@ import { createApp } from 'vue'
|
|||||||
import './style.css';
|
import './style.css';
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router';
|
import router from './router';
|
||||||
|
import store from './store';
|
||||||
|
|
||||||
createApp(App)
|
createApp(App)
|
||||||
.use(router)
|
.use(router)
|
||||||
|
.use(store)
|
||||||
.mount('#app');
|
.mount('#app');
|
||||||
|
|||||||
@ -1,28 +1,43 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
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 = [
|
const routes = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: PAGE_URL[PAGE.HOME],
|
||||||
name: 'Home',
|
name: PAGE.HOME,
|
||||||
component: () => import('../views/Home.vue'),
|
component: () => import('../views/HomePage.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
layout: 'main'
|
layout: 'main',
|
||||||
|
auth: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/help',
|
path: PAGE_URL[PAGE.HELP],
|
||||||
name: 'Help',
|
name: PAGE.HELP,
|
||||||
component: () => import('../views/Help.vue'),
|
component: () => import('../views/HelpPage.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
layout: 'main'
|
layout: 'main',
|
||||||
|
auth: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/auth',
|
path: PAGE_URL[PAGE.AUTH],
|
||||||
name: 'Auth',
|
name: PAGE.AUTH,
|
||||||
component: () => import('../views/Auth.vue'),
|
component: () => import('../views/AuthPage.vue'),
|
||||||
meta: {
|
meta: {
|
||||||
layout: 'auth'
|
layout: 'auth',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
@ -32,5 +47,18 @@ const router = createRouter({
|
|||||||
routes,
|
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;
|
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