solve issue #19
This commit is contained in:
27
package-lock.json
generated
27
package-lock.json
generated
@@ -16,6 +16,7 @@
|
|||||||
"date-fns": "^2.25.0",
|
"date-fns": "^2.25.0",
|
||||||
"pinia": "^2.0.0-rc.13",
|
"pinia": "^2.0.0-rc.13",
|
||||||
"pinia-plugin-persist": "^0.0.92",
|
"pinia-plugin-persist": "^0.0.92",
|
||||||
|
"uuid": "^8.3.2",
|
||||||
"vue": "^3.2.20",
|
"vue": "^3.2.20",
|
||||||
"vue-router": "^4.0.12",
|
"vue-router": "^4.0.12",
|
||||||
"vue-tsc": "^0.3.0"
|
"vue-tsc": "^0.3.0"
|
||||||
@@ -23,6 +24,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bootstrap": "^5.1.6",
|
"@types/bootstrap": "^5.1.6",
|
||||||
"@types/node": "^16.11.1",
|
"@types/node": "^16.11.1",
|
||||||
|
"@types/uuid": "^8.3.1",
|
||||||
"@vitejs/plugin-vue": "^1.9.3",
|
"@vitejs/plugin-vue": "^1.9.3",
|
||||||
"sass": "^1.43.2",
|
"sass": "^1.43.2",
|
||||||
"typescript": "^4.4.4",
|
"typescript": "^4.4.4",
|
||||||
@@ -129,6 +131,12 @@
|
|||||||
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
|
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/uuid": {
|
||||||
|
"version": "8.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz",
|
||||||
|
"integrity": "sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@vitejs/plugin-vue": {
|
"node_modules/@vitejs/plugin-vue": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.9.3.tgz",
|
||||||
@@ -1470,6 +1478,14 @@
|
|||||||
"yarn": "*"
|
"yarn": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vite": {
|
"node_modules/vite": {
|
||||||
"version": "2.6.10",
|
"version": "2.6.10",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.6.10.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-2.6.10.tgz",
|
||||||
@@ -1801,6 +1817,12 @@
|
|||||||
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
|
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"@types/uuid": {
|
||||||
|
"version": "8.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.1.tgz",
|
||||||
|
"integrity": "sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"@vitejs/plugin-vue": {
|
"@vitejs/plugin-vue": {
|
||||||
"version": "1.9.3",
|
"version": "1.9.3",
|
||||||
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.9.3.tgz",
|
"resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-1.9.3.tgz",
|
||||||
@@ -2760,6 +2782,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz",
|
||||||
"integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w=="
|
"integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w=="
|
||||||
},
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "8.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
|
||||||
|
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg=="
|
||||||
|
},
|
||||||
"vite": {
|
"vite": {
|
||||||
"version": "2.6.10",
|
"version": "2.6.10",
|
||||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.6.10.tgz",
|
"resolved": "https://registry.npmjs.org/vite/-/vite-2.6.10.tgz",
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"date-fns": "^2.25.0",
|
"date-fns": "^2.25.0",
|
||||||
"pinia": "^2.0.0-rc.13",
|
"pinia": "^2.0.0-rc.13",
|
||||||
"pinia-plugin-persist": "^0.0.92",
|
"pinia-plugin-persist": "^0.0.92",
|
||||||
|
"uuid": "^8.3.2",
|
||||||
"vue": "^3.2.20",
|
"vue": "^3.2.20",
|
||||||
"vue-router": "^4.0.12",
|
"vue-router": "^4.0.12",
|
||||||
"vue-tsc": "^0.3.0"
|
"vue-tsc": "^0.3.0"
|
||||||
@@ -22,6 +23,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/bootstrap": "^5.1.6",
|
"@types/bootstrap": "^5.1.6",
|
||||||
"@types/node": "^16.11.1",
|
"@types/node": "^16.11.1",
|
||||||
|
"@types/uuid": "^8.3.1",
|
||||||
"@vitejs/plugin-vue": "^1.9.3",
|
"@vitejs/plugin-vue": "^1.9.3",
|
||||||
"sass": "^1.43.2",
|
"sass": "^1.43.2",
|
||||||
"typescript": "^4.4.4",
|
"typescript": "^4.4.4",
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
|
{{notifications}}
|
||||||
|
|
||||||
<transition-group name="toasts" tag="div" class="toast-container position-absolute top-0 start-50 mt-3 translate-middle-x">
|
<transition-group name="toasts" tag="div" class="toast-container position-absolute top-0 start-50 mt-3 translate-middle-x">
|
||||||
<div v-for="(note, index) in notifications" :key="note.randomKey" class="show toast border-0 text-white" :class="`bg-${note.type}`" role="alert" aria-live="assertive" aria-atomic="true">
|
<div v-for="(note) in notifications" :key="note[0]" class="show toast border-0 text-white" :class="`bg-${note[1].type}`" role="alert" aria-live="assertive" aria-atomic="true">
|
||||||
<div class="d-flex">
|
<div class="d-flex">
|
||||||
<div class="toast-body">
|
<div class="toast-body">
|
||||||
{{note.text}}
|
{{note[1].text}}
|
||||||
</div>
|
</div>
|
||||||
<button type="button" @click="destroyAlert(index)" class="btn-close btn-close-white me-2 m-auto"></button>
|
<button type="button" @click="destroyAlert(note[0])" class="btn-close btn-close-white me-2 m-auto"></button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition-group>
|
</transition-group>
|
||||||
@@ -20,8 +22,8 @@ import { storeToRefs } from 'pinia'
|
|||||||
const notes = useNotifications()
|
const notes = useNotifications()
|
||||||
const { notifications } = storeToRefs(notes)
|
const { notifications } = storeToRefs(notes)
|
||||||
|
|
||||||
function destroyAlert(index : number) {
|
function destroyAlert(id : string) {
|
||||||
notes.removeAlert(index)
|
notes.remove(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,16 +1,27 @@
|
|||||||
import { defineStore, acceptHMRUpdate } from 'pinia'
|
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||||
|
import { v4 as uuidv4 } from 'uuid'
|
||||||
|
|
||||||
export const useNotifications = defineStore('notifications', {
|
export const useNotifications = defineStore('notifications', {
|
||||||
state: () => {
|
state: () => {
|
||||||
return {
|
return {
|
||||||
/**@type {{type: string, text: string, randomKey: string}[]} */
|
/**@type {Map<string, {type: string, text: string}>} */
|
||||||
notifications: new Array<{type: string, text: string, randomKey: string}>()
|
notifications: new Map<string, {type: string, text: string}>()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
removeAlert(index : number) : void {
|
remove(id : string) : void {
|
||||||
this.notifications.splice(index, 1)
|
this.notifications.delete(id)
|
||||||
|
},
|
||||||
|
|
||||||
|
add(type : string, text: string) : void {
|
||||||
|
this.notifications.set(
|
||||||
|
uuidv4(),
|
||||||
|
{
|
||||||
|
type:type,
|
||||||
|
text:text,
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ export const useUser = defineStore({
|
|||||||
actions: {
|
actions: {
|
||||||
async login(username: string, password: string, rememberMe: boolean): Promise<boolean> {
|
async login(username: string, password: string, rememberMe: boolean): Promise<boolean> {
|
||||||
|
|
||||||
const { notifications } = storeToRefs(useNotifications())
|
const notifications = useNotifications()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await axios.post<AuthSuccResult>('http://localhost:3333/api/v1/login', {
|
const response = await axios.post<AuthSuccResult>('http://localhost:3333/api/v1/login', {
|
||||||
@@ -63,26 +63,17 @@ export const useUser = defineStore({
|
|||||||
this.user = response.data.user
|
this.user = response.data.user
|
||||||
this.role = response.data.role
|
this.role = response.data.role
|
||||||
this.token = response.data.token
|
this.token = response.data.token
|
||||||
|
|
||||||
notifications.value.push({
|
notifications.add(response.data.notification.type, response.data.notification.text)
|
||||||
type: response.data.notification.type,
|
|
||||||
text: response.data.notification.text,
|
|
||||||
randomKey: getUnixTime(new Date()).toString()
|
|
||||||
})
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
} catch(err : unknown) {
|
} catch(err : unknown) {
|
||||||
if (axios.isAxiosError(err) && err.response && err.response.data){
|
if (axios.isAxiosError(err) && err.response && err.response.data){
|
||||||
|
|
||||||
const data = err.response.data as AuthErrResult
|
const data = err.response.data as AuthErrResult
|
||||||
|
|
||||||
|
notifications.add(data.notification.type, data.notification.text)
|
||||||
|
|
||||||
const note = {
|
|
||||||
type: data.notification.type,
|
|
||||||
text: data.notification.text,
|
|
||||||
randomKey: getUnixTime(new Date()).toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
notifications.value.push(note)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@@ -92,7 +83,7 @@ export const useUser = defineStore({
|
|||||||
|
|
||||||
async logout(): Promise<boolean> {
|
async logout(): Promise<boolean> {
|
||||||
|
|
||||||
const { notifications } = storeToRefs(useNotifications())
|
const notifications = useNotifications()
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const ai = axios.create({
|
const ai = axios.create({
|
||||||
@@ -104,11 +95,8 @@ export const useUser = defineStore({
|
|||||||
})
|
})
|
||||||
await ai.post('/logout')
|
await ai.post('/logout')
|
||||||
|
|
||||||
notifications.value.push({
|
|
||||||
type: 'success',
|
notifications.add('success','Logged out successfully')
|
||||||
text: 'Logged out successfully',
|
|
||||||
randomKey: getUnixTime(new Date()).toString()
|
|
||||||
})
|
|
||||||
|
|
||||||
this.$reset()
|
this.$reset()
|
||||||
|
|
||||||
@@ -116,14 +104,8 @@ export const useUser = defineStore({
|
|||||||
}
|
}
|
||||||
catch(error) {
|
catch(error) {
|
||||||
if(error instanceof Error) {
|
if(error instanceof Error) {
|
||||||
const notification = {
|
|
||||||
type: 'danger',
|
|
||||||
text: error.message,
|
|
||||||
randomKey: getUnixTime(new Date()).toString()
|
|
||||||
/**TODO #19 Generate randomKey in notification-store! */
|
|
||||||
}
|
|
||||||
|
|
||||||
notifications.value.push(notification)
|
notifications.add('danger', error.message)
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user