1
0

feat: add logout for navbar

This commit is contained in:
2026-05-15 09:39:15 +08:00
parent 2a280dcba0
commit e484ded5be
3 changed files with 73 additions and 38 deletions

View File

@@ -1,58 +1,92 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue';
import { useLanguageStore } from './stores/language'; import { useLanguageStore } from './stores/language';
import { useTokenStore } from './stores/token'; import { useTokenStore } from './stores/token';
import MessageBox from '@/components/MessageBox.vue';
import { logout as apiCommonLogout } from './api/common';
import { goToHome } from '@/router';
const language = useLanguageStore(); const language = useLanguageStore();
const token = useTokenStore(); const token = useTokenStore();
const isBurgerActive = ref<boolean>(false);
const messagebox = ref<InstanceType<typeof MessageBox> | null>(null);
const logout = async () => {
const tokenStore = useTokenStore();
const rv = await apiCommonLogout(tokenStore.currentToken);
if (rv) {
// OK. We logged out.
// Clear token.
tokenStore.logout();
// And go to Home page
goToHome();
} else {
// Show logout error.
messagebox.value?.show("Fail to logout due to unknow reason. Consider refreshing page to solve problem.");
}
}
// Process burger menu.
// This is copied from Bulma website and modified for Vue.
// Check for click events on the navbar burger icon
const toggleBurger = () => {
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
isBurgerActive.value = !isBurgerActive
}
</script> </script>
<template> <template>
<nav class="navbar has-shadow is-spaced bd-navbar" role="navigation" aria-label="main navigation"> <nav class="navbar has-shadow is-spaced bd-navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand"> <div class="navbar-brand">
<router-link class="navbar-item" to="/"> <router-link class="navbar-item" to="/">
<img src="/public/favicon.ico"><b style="margin:0 0 0 14px;">coconut-leaf</b> <img src="/public/favicon.ico"><b style="margin:0 0 0 14px;">coconut-leaf</b>
</router-link> </router-link>
<a role="button" class="navbar-burger burger" aria-label="menu" aria-expanded="false" <a role="button" class="navbar-burger burger" :class="{ 'is-active': isBurgerActive }" @click="toggleBurger"
data-target="coleaf-navbar"> aria-label="menu" aria-expanded="false" data-target="coleaf-navbar">
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
<span aria-hidden="true"></span> <span aria-hidden="true"></span>
</a> </a>
</div>
<div id="coleaf-navbar" class="navbar-menu" :class="{ 'is-active': isBurgerActive }">
<div class="navbar-start">
<router-link class="navbar-item" to="/home">Home</router-link>
<router-link v-if="token.isLoggedIn" class="navbar-item" to="/collection">Collection</router-link>
<router-link v-if="token.isLoggedIn" class="navbar-item" to="/calendar">Calendar</router-link>
<router-link v-if="token.isLoggedIn" class="navbar-item" to="/todo">Todo</router-link>
<router-link v-if="token.isLoggedIn" class="navbar-item" to="/admin">Admin</router-link>
</div> </div>
<div id="coleaf-navbar" class="navbar-menu"> <div class="navbar-end">
<div class="navbar-start"> <p class="navbar-item">
<router-link class="navbar-item" to="/home">Home</router-link> <router-link v-if="!token.isLoggedIn" class="button is-primary" to="/login">Login</router-link>
<router-link v-if="token.isLoggedIn" class="navbar-item" to="/collection">Collection</router-link> </p>
<router-link v-if="token.isLoggedIn" class="navbar-item" to="/calendar">Calendar</router-link> <p class="navbar-item">
<router-link v-if="token.isLoggedIn" class="navbar-item" to="/todo">Todo</router-link> <a v-if="token.isLoggedIn" class="button is-primary" @click="logout">Logout</a>
<router-link v-if="token.isLoggedIn" class="navbar-item" to="/admin">Admin</router-link> </p>
</div>
<div class="navbar-end"> <div class="navbar-item has-dropdown is-hoverable">
<p class="navbar-item"> <a v-if="language.isEnglish" class="navbar-link">English</a>
<router-link v-if="!token.isLoggedIn" class="button is-primary" to="/login">Login</router-link> <a v-else-if="language.isSimplifiedChinese" class="navbar-link">简体中文</a>
</p>
<p class="navbar-item">
<a v-if="token.isLoggedIn" class="button is-primary">Logout</a>
</p>
<div class="navbar-item has-dropdown is-hoverable"> <div class="navbar-dropdown">
<a v-if="language.isEnglish" class="navbar-link">English</a> <a @click="language.changeToEnglish()" class="navbar-item">English</a>
<a v-else-if="language.isSimplifiedChinese" class="navbar-link">简体中文</a> <a @click="language.changeToSimplifiedChinese()" class="navbar-item">简体中文</a>
<div class="navbar-dropdown">
<a @click="language.changeToEnglish()" class="navbar-item">English</a>
<a @click="language.changeToSimplifiedChinese()" class="navbar-item">简体中文</a>
</div>
</div> </div>
</div> </div>
</div> </div>
</nav> </div>
<!-- The output result of router --> </nav>
<router-view></router-view>
<!-- The output result of router -->
<router-view></router-view>
<MessageBox ref="messagebox" />
</template> </template>
<style scoped></style> <style scoped></style>

View File

@@ -11,6 +11,7 @@ export const useTokenStore = defineStore('token', {
getters: { getters: {
isLoggedIn: (state) => typeof state.token === 'string', isLoggedIn: (state) => typeof state.token === 'string',
currentToken: (state) => state.token as string,
}, },
actions: { actions: {

View File

@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue'; import { ref } from 'vue';
import MessageBox from '@/components/MessageBox.vue';
import { useTokenStore } from '@/stores/token'; import { useTokenStore } from '@/stores/token';
import MessageBox from '@/components/MessageBox.vue';
import { webLogin as apiCommonWebLogin } from '@/api/common'; import { webLogin as apiCommonWebLogin } from '@/api/common';
import { goToHome } from '@/router'; import { goToHome } from '@/router';