implemented notification component and logic
This commit is contained in:
24
src/App.vue
24
src/App.vue
@@ -1,15 +1,24 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-app>
|
<v-app>
|
||||||
<v-main>
|
<v-main>
|
||||||
<div class="container shadow p-3 text-center">
|
<Notification />
|
||||||
<router-view></router-view>
|
<div class="container shadow p-3 text-center">
|
||||||
</div>
|
<nav class="nav justify-content-center border-bottom mb-4 pb-2">
|
||||||
</v-main>
|
<a href="" class="nav-link">Logout</a>
|
||||||
</v-app>
|
<router-link class="nav-link" to="/">Home</router-link>
|
||||||
|
<router-link to="Login" class="nav-link">Login</router-link>
|
||||||
|
</nav>
|
||||||
|
<router-view></router-view>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</v-main>
|
||||||
|
</v-app>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
|
||||||
|
import Notification from '@/components/Notification.vue';
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
@@ -18,6 +27,5 @@
|
|||||||
-webkit-font-smoothing: antialiased;
|
-webkit-font-smoothing: antialiased;
|
||||||
-moz-osx-font-smoothing: grayscale;
|
-moz-osx-font-smoothing: grayscale;
|
||||||
color: #2c3e50;
|
color: #2c3e50;
|
||||||
margin-top: 60px;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
41
src/components/Notification.vue
Normal file
41
src/components/Notification.vue
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<div class="toast-container position-absolute top-0 start-50 mt-3 translate-middle-x">
|
||||||
|
<transition-group name="fade">
|
||||||
|
<div v-for="(note, index) in notifications" :key="index" data-bs-delay="2000" data-bs-autohide="true" class="show fade toast border-0 text-white" :class="toastClasses(note.type)" role="alert" aria-live="assertive" aria-atomic="true">
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="toast-body">
|
||||||
|
{{note.text}}
|
||||||
|
</div>
|
||||||
|
<button type="button" @click="destroyAlert(index)" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition-group>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useNotifications } from '@/stores/notifications'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
|
||||||
|
const notes = useNotifications()
|
||||||
|
const { notifications } = storeToRefs(notes)
|
||||||
|
|
||||||
|
function destroyAlert(index : number) {
|
||||||
|
notes.removeAlert(index)
|
||||||
|
}
|
||||||
|
|
||||||
|
function toastClasses(type : string){
|
||||||
|
return {
|
||||||
|
'bg-danger': type === 'danger',
|
||||||
|
'bg-success' : type === 'success',
|
||||||
|
'bg-warning' : type === 'warning'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
20
src/stores/notifications.ts
Normal file
20
src/stores/notifications.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { defineStore, acceptHMRUpdate } from 'pinia'
|
||||||
|
|
||||||
|
export const useNotifications = defineStore('notifications', {
|
||||||
|
state: () => {
|
||||||
|
return {
|
||||||
|
/**@type {{type: string, text: string}[]} */
|
||||||
|
notifications: new Array<{type: string, text: string}>()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
removeAlert(index : number) : void {
|
||||||
|
this.notifications.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if(import.meta.hot) {
|
||||||
|
import.meta.hot.accept(acceptHMRUpdate(useNotifications, import.meta.hot))
|
||||||
|
}
|
||||||
@@ -1,5 +1,22 @@
|
|||||||
import { defineStore } from 'pinia'
|
import { defineStore, storeToRefs } from 'pinia'
|
||||||
import axios, {AxiosResponse, AxiosError} from 'axios'
|
import axios, {AxiosResponse, AxiosError} from 'axios'
|
||||||
|
import { useNotifications } from './notifications'
|
||||||
|
|
||||||
|
type AuthSuccResult = {
|
||||||
|
notification: {
|
||||||
|
type: string,
|
||||||
|
text: string
|
||||||
|
}
|
||||||
|
user: string,
|
||||||
|
role: string
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthErrResult = {
|
||||||
|
notification: {
|
||||||
|
text: string,
|
||||||
|
type: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export const useUser = defineStore('userStore', {
|
export const useUser = defineStore('userStore', {
|
||||||
state: () => {
|
state: () => {
|
||||||
@@ -12,27 +29,37 @@ export const useUser = defineStore('userStore', {
|
|||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
async login(username: string, password: string) : Promise<boolean> {
|
async login(username: string, password: string) : Promise<boolean> {
|
||||||
|
const { notifications } = storeToRefs(useNotifications())
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response: AxiosResponse<{
|
const response = await axios.post<AuthSuccResult>('http://localhost:3333/api/v1/login', {
|
||||||
user: string,
|
|
||||||
role: string,
|
|
||||||
Message: string
|
|
||||||
}> = await axios.post('http://localhost:3333/api/v1/login', {
|
|
||||||
username: username,
|
username: username,
|
||||||
password: password
|
password: password
|
||||||
})
|
})
|
||||||
|
|
||||||
console.log(response.data)
|
|
||||||
this.isLoggedIn = true
|
this.isLoggedIn = true
|
||||||
this.user = response.data.user
|
this.user = response.data.user
|
||||||
this.role = response.data.role
|
this.role = response.data.role
|
||||||
|
|
||||||
|
notifications.value.push({
|
||||||
|
type: response.data.notification.type,
|
||||||
|
text: response.data.notification.text,
|
||||||
|
})
|
||||||
|
|
||||||
return true
|
return true
|
||||||
} catch(err) {
|
} catch(err : unknown) {
|
||||||
if (axios.isAxiosError(err)){
|
if (axios.isAxiosError(err) && err.response && err.response.data){
|
||||||
console.log(err.response)
|
|
||||||
|
const data = err.response.data as AuthErrResult
|
||||||
|
|
||||||
|
const note = {
|
||||||
|
type: data.notification.type,
|
||||||
|
text: data.notification.text
|
||||||
|
}
|
||||||
|
|
||||||
|
notifications.value.push(note)
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<template lang="pug">
|
<template lang="pug">
|
||||||
|
|
||||||
p {{ state }}
|
//- p {{ state }}
|
||||||
|
|
||||||
MonthPicker(:selectedMonth="selectedMonth" :selectedYear="selectedYear" @getMonth="selectedMonth = $event" @getYear="selectedYear = $event")
|
MonthPicker(:selectedMonth="selectedMonth" :selectedYear="selectedYear" @getMonth="selectedMonth = $event" @getYear="selectedYear = $event")
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
|
||||||
<img src="/src/assets/logo.png">
|
<img src="/src/assets/logo.png">
|
||||||
<form class="m-auto">
|
<form class="m-auto">
|
||||||
<h1 class="h3 mb-3">Bitte einloggen</h1>
|
<h1 class="h3 mb-3">Bitte einloggen</h1>
|
||||||
@@ -24,22 +27,26 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useUser } from '@/stores/user'
|
import { useUser } from '@/stores/user'
|
||||||
import { onMounted, reactive } from 'vue'
|
import { useNotifications } from '@/stores/notifications'
|
||||||
|
import { reactive } from 'vue'
|
||||||
|
import { storeToRefs } from 'pinia'
|
||||||
|
import { useRouter } from 'vue-router'
|
||||||
|
|
||||||
const userStore = useUser()
|
const userStore = useUser()
|
||||||
|
const noteStore = useNotifications()
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const input = reactive({
|
const input = reactive({
|
||||||
username: '',
|
username: '',
|
||||||
password: ''
|
password: ''
|
||||||
})
|
})
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
async function onClick() {
|
async function onClick() {
|
||||||
|
|
||||||
userStore.login(input.username, input.password)
|
if(await userStore.login(input.username, input.password)) {
|
||||||
|
router.push({name: 'Home'})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user