implemented notification component and logic

This commit is contained in:
Sockenklaus
2021-10-21 01:24:46 +02:00
parent 5017be6d42
commit 7e5ab9b445
6 changed files with 129 additions and 26 deletions

View File

@@ -1,15 +1,24 @@
<template>
<v-app>
<v-main>
<div class="container shadow p-3 text-center">
<router-view></router-view>
</div>
</v-main>
</v-app>
<v-app>
<v-main>
<Notification />
<div class="container shadow p-3 text-center">
<nav class="nav justify-content-center border-bottom mb-4 pb-2">
<a href="" class="nav-link">Logout</a>
<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>
<script setup lang="ts">
import Notification from '@/components/Notification.vue';
</script>
<style>
@@ -18,6 +27,5 @@
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
margin-top: 60px;
}
</style>

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

View 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))
}

View File

@@ -1,5 +1,22 @@
import { defineStore } from 'pinia'
import { defineStore, storeToRefs } from 'pinia'
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', {
state: () => {
@@ -12,27 +29,37 @@ export const useUser = defineStore('userStore', {
actions: {
async login(username: string, password: string) : Promise<boolean> {
const { notifications } = storeToRefs(useNotifications())
try {
const response: AxiosResponse<{
user: string,
role: string,
Message: string
}> = await axios.post('http://localhost:3333/api/v1/login', {
const response = await axios.post<AuthSuccResult>('http://localhost:3333/api/v1/login', {
username: username,
password: password
})
console.log(response.data)
this.isLoggedIn = true
this.user = response.data.user
this.role = response.data.role
notifications.value.push({
type: response.data.notification.type,
text: response.data.notification.text,
})
return true
} catch(err) {
if (axios.isAxiosError(err)){
console.log(err.response)
} catch(err : unknown) {
if (axios.isAxiosError(err) && err.response && err.response.data){
const data = err.response.data as AuthErrResult
const note = {
type: data.notification.type,
text: data.notification.text
}
notifications.value.push(note)
}
return false
}

View File

@@ -1,6 +1,6 @@
<template lang="pug">
p {{ state }}
//- p {{ state }}
MonthPicker(:selectedMonth="selectedMonth" :selectedYear="selectedYear" @getMonth="selectedMonth = $event" @getYear="selectedYear = $event")

View File

@@ -1,4 +1,7 @@
<template>
<br />
<img src="/src/assets/logo.png">
<form class="m-auto">
<h1 class="h3 mb-3">Bitte einloggen</h1>
@@ -24,22 +27,26 @@
<script setup lang="ts">
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 noteStore = useNotifications()
const router = useRouter()
const input = reactive({
username: '',
password: ''
})
onMounted(() => {
})
async function onClick() {
userStore.login(input.username, input.password)
if(await userStore.login(input.username, input.password)) {
router.push({name: 'Home'})
}
}