initial commit
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
<script setup>
|
||||
import navItems from '@/navigation/horizontal'
|
||||
import { useThemeConfig } from '@core/composable/useThemeConfig'
|
||||
import { themeConfig } from '@themeConfig'
|
||||
|
||||
// Components
|
||||
import Footer from '@/layouts/components/Footer.vue'
|
||||
import NavbarThemeSwitcher from '@/layouts/components/NavbarThemeSwitcher.vue'
|
||||
import UserProfile from '@/layouts/components/UserProfile.vue'
|
||||
import { HorizontalNavLayout } from '@layouts'
|
||||
import { VNodeRenderer } from '@layouts/components/VNodeRenderer'
|
||||
|
||||
const { appRouteTransition } = useThemeConfig()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<HorizontalNavLayout :nav-items="navItems">
|
||||
<!-- 👉 navbar -->
|
||||
<template #navbar>
|
||||
<a
|
||||
href="/"
|
||||
class="app-logo d-flex align-center gap-x-3"
|
||||
>
|
||||
<VNodeRenderer :nodes="themeConfig.app.logo" />
|
||||
|
||||
<h1 class="app-title font-weight-bold leading-normal text-xl text-capitalize">
|
||||
{{ themeConfig.app.title }}
|
||||
</h1>
|
||||
</a>
|
||||
<VSpacer />
|
||||
|
||||
<NavbarThemeSwitcher class="me-2" />
|
||||
<UserProfile />
|
||||
</template>
|
||||
|
||||
<!-- 👉 Pages -->
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition
|
||||
:name="appRouteTransition"
|
||||
mode="out-in"
|
||||
>
|
||||
<Component :is="Component" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
|
||||
<!-- 👉 Footer -->
|
||||
<template #footer>
|
||||
<Footer />
|
||||
</template>
|
||||
|
||||
<!-- 👉 Customizer -->
|
||||
<!-- <TheCustomizer /> -->
|
||||
</HorizontalNavLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,119 @@
|
||||
<script setup>
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { useThemeConfig } from '@core/composable/useThemeConfig'
|
||||
import { computed } from 'vue'
|
||||
|
||||
// Components
|
||||
import Footer from '@/layouts/components/Footer.vue'
|
||||
import UserProfile from '@/layouts/components/UserProfile.vue'
|
||||
|
||||
// @layouts plugin
|
||||
import { VerticalNavLayout } from '@layouts'
|
||||
|
||||
const { appRouteTransition, isLessThanOverlayNavBreakpoint } = useThemeConfig()
|
||||
const { width: windowWidth } = useWindowSize()
|
||||
|
||||
const authStore = useAuthStore()
|
||||
|
||||
// DYNAMIC SIDEBAR NAV ITEMS
|
||||
const navItems = computed(()=>{
|
||||
const items = [
|
||||
{ heading: 'Dashboard' },
|
||||
{
|
||||
title: 'Home',
|
||||
to: { name: 'dashboard' },
|
||||
icon: { icon: 'tabler-smart-home' },
|
||||
},
|
||||
]
|
||||
|
||||
if (authStore.role == 'admin') {
|
||||
items.push(...[
|
||||
{ heading: 'User Management' },
|
||||
{
|
||||
title: 'Patient',
|
||||
to: { name: 'admin-patient' },
|
||||
icon: { icon: 'tabler-user-filled' },
|
||||
},
|
||||
{
|
||||
title: 'Doctor',
|
||||
to: { name: 'admin-doctor' },
|
||||
icon: { icon: 'tabler-stethoscope' },
|
||||
},
|
||||
])
|
||||
} else if (authStore.role == 'doctor') {
|
||||
items.push(...[
|
||||
{ heading: 'Patients' },
|
||||
{
|
||||
title: 'My Patients',
|
||||
to: { name: 'doctor-patient' },
|
||||
icon: { icon: 'tabler-user-filled' },
|
||||
},
|
||||
])
|
||||
} else if (authStore.role == 'patient') {
|
||||
items.push(...[
|
||||
{ heading: 'Diagnoses' },
|
||||
{
|
||||
title: 'My Diagnoses',
|
||||
to: { name: 'patient-diagnoses' },
|
||||
icon: { icon: 'tabler-clipboard-check' },
|
||||
},
|
||||
])
|
||||
}
|
||||
|
||||
items.push(...[
|
||||
{ heading: 'Account' },
|
||||
{
|
||||
title: 'Profile',
|
||||
to: { name: 'profile' },
|
||||
icon: { icon: 'tabler-user' },
|
||||
},
|
||||
])
|
||||
|
||||
return items
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VerticalNavLayout :nav-items="navItems">
|
||||
<!-- 👉 navbar -->
|
||||
<template #navbar="{ toggleVerticalOverlayNavActive }">
|
||||
<div class="d-flex h-100 align-center">
|
||||
<IconBtn
|
||||
v-if="isLessThanOverlayNavBreakpoint(windowWidth)"
|
||||
id="vertical-nav-toggle-btn"
|
||||
class="ms-n3"
|
||||
@click="toggleVerticalOverlayNavActive(true)"
|
||||
>
|
||||
<VIcon
|
||||
size="26"
|
||||
icon="tabler-menu-2"
|
||||
/>
|
||||
</IconBtn>
|
||||
|
||||
<!-- <NavbarThemeSwitcher /> -->
|
||||
|
||||
<VSpacer />
|
||||
|
||||
<UserProfile />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 👉 Pages -->
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition
|
||||
:name="appRouteTransition"
|
||||
mode="out-in"
|
||||
>
|
||||
<Component :is="Component" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
|
||||
<!-- 👉 Footer -->
|
||||
<template #footer>
|
||||
<Footer />
|
||||
</template>
|
||||
|
||||
<!-- 👉 Customizer -->
|
||||
<!-- <TheCustomizer /> -->
|
||||
</VerticalNavLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,3 @@
|
||||
<template>
|
||||
<div />
|
||||
</template>
|
||||
@@ -0,0 +1,49 @@
|
||||
<script setup>
|
||||
import { useThemeConfig } from '@core/composable/useThemeConfig'
|
||||
|
||||
import logo from '@images/logo.png'
|
||||
|
||||
// @layouts plugin
|
||||
import { TopNavLayout } from '@layouts'
|
||||
|
||||
const { appRouteTransition } = useThemeConfig()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TopNavLayout>
|
||||
<!-- 👉 navbar -->
|
||||
<template #navbar>
|
||||
<div class="d-flex h-100 align-center">
|
||||
<img
|
||||
:src="logo"
|
||||
alt="MyoScope"
|
||||
height="32"
|
||||
>
|
||||
<h1 class="text-h2 ms-2">
|
||||
MyoScope
|
||||
</h1>
|
||||
|
||||
<VSpacer />
|
||||
|
||||
<VBtn
|
||||
color="primary"
|
||||
outlined
|
||||
to="/login"
|
||||
prepend-icon="mdi-login"
|
||||
>
|
||||
Login
|
||||
</VBtn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 👉 Pages -->
|
||||
<RouterView v-slot="{ Component }">
|
||||
<Transition
|
||||
:name="appRouteTransition"
|
||||
mode="out-in"
|
||||
>
|
||||
<Component :is="Component" />
|
||||
</Transition>
|
||||
</RouterView>
|
||||
</TopNavLayout>
|
||||
</template>
|
||||
@@ -0,0 +1,32 @@
|
||||
<script setup>
|
||||
import NavBarI18n from '@core/components/I18n.vue'
|
||||
import { useThemeConfig } from '@core/composable/useThemeConfig'
|
||||
|
||||
const { isAppRtl } = useThemeConfig()
|
||||
|
||||
const i18nCompLanguages = [
|
||||
{
|
||||
label: 'English',
|
||||
i18nLang: 'en',
|
||||
},
|
||||
{
|
||||
label: 'French',
|
||||
i18nLang: 'fr',
|
||||
},
|
||||
{
|
||||
label: 'Arabic',
|
||||
i18nLang: 'ar',
|
||||
},
|
||||
]
|
||||
|
||||
const handleLangChange = lang => {
|
||||
isAppRtl.value = lang === 'ar'
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<NavBarI18n
|
||||
:languages="i18nCompLanguages"
|
||||
@change="handleLangChange"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,90 @@
|
||||
<script setup>
|
||||
import avatar3 from '@images/avatars/avatar-3.png'
|
||||
import avatar4 from '@images/avatars/avatar-4.png'
|
||||
import avatar5 from '@images/avatars/avatar-5.png'
|
||||
import paypal from '@images/svg/paypal.svg'
|
||||
|
||||
const notifications = ref([
|
||||
{
|
||||
id: 1,
|
||||
img: avatar4,
|
||||
title: 'Congratulation Flora! 🎉',
|
||||
subtitle: 'Won the monthly best seller badge',
|
||||
time: 'Today',
|
||||
isSeen: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
text: 'Tom Holland',
|
||||
title: 'New user registered.',
|
||||
subtitle: '5 hours ago',
|
||||
time: 'Yesterday',
|
||||
isSeen: false,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
img: avatar5,
|
||||
title: 'New message received 👋🏻',
|
||||
subtitle: 'You have 10 unread messages',
|
||||
time: '11 Aug',
|
||||
isSeen: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
img: paypal,
|
||||
title: 'Paypal',
|
||||
subtitle: 'Received Payment',
|
||||
time: '25 May',
|
||||
isSeen: false,
|
||||
color: 'error',
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
img: avatar3,
|
||||
title: 'Received Order 📦',
|
||||
subtitle: 'New order received from john',
|
||||
time: '19 Mar',
|
||||
isSeen: true,
|
||||
},
|
||||
])
|
||||
|
||||
const removeNotification = notificationId => {
|
||||
notifications.value.forEach((item, index) => {
|
||||
if (notificationId === item.id)
|
||||
notifications.value.splice(index, 1)
|
||||
})
|
||||
}
|
||||
|
||||
const markRead = notificationId => {
|
||||
notifications.value.forEach(item => {
|
||||
notificationId.forEach(id => {
|
||||
if (id === item.id)
|
||||
item.isSeen = true
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const markUnRead = notificationId => {
|
||||
notifications.value.forEach(item => {
|
||||
notificationId.forEach(id => {
|
||||
if (id === item.id)
|
||||
item.isSeen = false
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const handleNotificationClick = notification => {
|
||||
if (!notification.isSeen)
|
||||
markRead([notification.id])
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Notifications
|
||||
:notifications="notifications"
|
||||
@remove="removeNotification"
|
||||
@read="markRead"
|
||||
@unread="markUnRead"
|
||||
@click:notification="handleNotificationClick"
|
||||
/>
|
||||
</template>
|
||||
@@ -0,0 +1,231 @@
|
||||
<script setup>
|
||||
import Shepherd from 'shepherd.js'
|
||||
import axios from '@axios'
|
||||
import { useThemeConfig } from '@core/composable/useThemeConfig'
|
||||
|
||||
const { appContentLayoutNav } = useThemeConfig()
|
||||
|
||||
defineOptions({ inheritAttrs: false })
|
||||
|
||||
// 👉 Is App Search Bar Visible
|
||||
const isAppSearchBarVisible = ref(false)
|
||||
|
||||
// 👉 Default suggestions
|
||||
const suggestionGroups = [
|
||||
{
|
||||
title: 'Popular Searches',
|
||||
content: [
|
||||
{
|
||||
icon: 'tabler-chart-donut',
|
||||
title: 'Analytics',
|
||||
url: { name: 'dashboards-analytics' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-chart-bubble',
|
||||
title: 'CRM',
|
||||
url: { name: 'dashboards-crm' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-file',
|
||||
title: 'Invoice List',
|
||||
url: { name: 'apps-invoice-list' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-users',
|
||||
title: 'User List',
|
||||
url: { name: 'apps-user-list' },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Apps & Pages',
|
||||
content: [
|
||||
{
|
||||
icon: 'tabler-calendar',
|
||||
title: 'Calendar',
|
||||
url: { name: 'apps-calendar' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-file-plus',
|
||||
title: 'Invoice Add',
|
||||
url: { name: 'apps-invoice-add' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-currency-dollar',
|
||||
title: 'Pricing',
|
||||
url: { name: 'pages-pricing' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-user',
|
||||
title: 'Account Settings',
|
||||
url: {
|
||||
name: 'pages-account-settings-tab',
|
||||
params: { tab: 'account' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'User Interface',
|
||||
content: [
|
||||
{
|
||||
icon: 'tabler-letter-a',
|
||||
title: 'Typography',
|
||||
url: { name: 'pages-typography' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-square',
|
||||
title: 'Tabs',
|
||||
url: { name: 'components-tabs' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-hand-click',
|
||||
title: 'Buttons',
|
||||
url: { name: 'components-button' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-keyboard',
|
||||
title: 'Statistics',
|
||||
url: { name: 'pages-cards-card-statistics' },
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
title: 'Popular Searches',
|
||||
content: [
|
||||
{
|
||||
icon: 'tabler-list',
|
||||
title: 'Select',
|
||||
url: { name: 'forms-select' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-space',
|
||||
title: 'Combobox',
|
||||
url: { name: 'forms-combobox' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-calendar',
|
||||
title: 'Date & Time Picker',
|
||||
url: { name: 'forms-date-time-picker' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-hexagon',
|
||||
title: 'Rating',
|
||||
url: { name: 'forms-rating' },
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
// 👉 No Data suggestion
|
||||
const noDataSuggestions = [
|
||||
{
|
||||
title: 'Analytics Dashboard',
|
||||
icon: 'tabler-shopping-cart',
|
||||
url: { name: 'dashboards-analytics' },
|
||||
},
|
||||
{
|
||||
title: 'Account Settings',
|
||||
icon: 'tabler-user',
|
||||
url: {
|
||||
name: 'pages-account-settings-tab',
|
||||
params: { tab: 'account' },
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'Pricing Page',
|
||||
icon: 'tabler-cash',
|
||||
url: { name: 'pages-pricing' },
|
||||
},
|
||||
]
|
||||
|
||||
const searchQuery = ref('')
|
||||
const searchResult = ref([])
|
||||
const router = useRouter()
|
||||
|
||||
// 👉 fetch search result API
|
||||
watchEffect(() => {
|
||||
axios.get('/app-bar/search', { params: { q: searchQuery.value } }).then(response => {
|
||||
searchResult.value = response.data
|
||||
})
|
||||
})
|
||||
|
||||
const redirectToSuggestedOrSearchedPage = selected => {
|
||||
router.push(selected.url)
|
||||
isAppSearchBarVisible.value = false
|
||||
searchQuery.value = ''
|
||||
}
|
||||
|
||||
const LazyAppBarSearch = defineAsyncComponent(() => import('@core/components/AppBarSearch.vue'))
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="d-flex align-center cursor-pointer"
|
||||
v-bind="$attrs"
|
||||
style="user-select: none;"
|
||||
@click="isAppSearchBarVisible = !isAppSearchBarVisible"
|
||||
>
|
||||
<!-- 👉 Search Trigger button -->
|
||||
<!-- close active tour while opening search bar using icon -->
|
||||
<IconBtn
|
||||
class="me-1"
|
||||
@click="Shepherd.activeTour?.cancel()"
|
||||
>
|
||||
<VIcon
|
||||
size="26"
|
||||
icon="tabler-search"
|
||||
/>
|
||||
</IconBtn>
|
||||
|
||||
<span
|
||||
v-if="appContentLayoutNav === 'vertical'"
|
||||
class="d-none d-md-flex align-center text-disabled"
|
||||
@click="Shepherd.activeTour?.cancel()"
|
||||
>
|
||||
<span class="me-3">Search</span>
|
||||
<span class="meta-key">⌘K</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<!-- 👉 App Bar Search -->
|
||||
<LazyAppBarSearch
|
||||
v-model:isDialogVisible="isAppSearchBarVisible"
|
||||
v-model:search-query="searchQuery"
|
||||
:search-results="searchResult"
|
||||
:suggestions="suggestionGroups"
|
||||
:no-data-suggestion="noDataSuggestions"
|
||||
@item-selected="redirectToSuggestedOrSearchedPage"
|
||||
>
|
||||
<!--
|
||||
<template #suggestions>
|
||||
use this slot if you want to override default suggestions
|
||||
</template>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<template #noData>
|
||||
use this slot to change the view of no data section
|
||||
</template>
|
||||
-->
|
||||
|
||||
<!--
|
||||
<template #searchResult="{ item }">
|
||||
use this slot to change the search item
|
||||
</template>
|
||||
-->
|
||||
</LazyAppBarSearch>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@use "@styles/variables/_vuetify.scss";
|
||||
|
||||
.meta-key {
|
||||
border: thin solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||
border-radius: 6px;
|
||||
block-size: 1.5625rem;
|
||||
line-height: 1.3125rem;
|
||||
padding-block: 0.125rem;
|
||||
padding-inline: 0.25rem;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,47 @@
|
||||
<script setup>
|
||||
const shortcuts = [
|
||||
{
|
||||
icon: 'tabler-calendar',
|
||||
title: 'Calendar',
|
||||
subtitle: 'Appointments',
|
||||
to: { name: 'apps-calendar' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-file',
|
||||
title: 'Invoice App',
|
||||
subtitle: 'Manage Accounts',
|
||||
to: { name: 'apps-invoice-list' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-user',
|
||||
title: 'Users',
|
||||
subtitle: 'Manage Users',
|
||||
to: { name: 'apps-user-list' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-layout',
|
||||
title: 'Dashboard',
|
||||
subtitle: 'Dashboard Analytics',
|
||||
to: { name: 'dashboards-analytics' },
|
||||
},
|
||||
{
|
||||
icon: 'tabler-settings',
|
||||
title: 'Settings',
|
||||
subtitle: 'Account Settings',
|
||||
to: {
|
||||
name: 'pages-account-settings-tab',
|
||||
params: { tab: 'account' },
|
||||
},
|
||||
},
|
||||
{
|
||||
icon: 'tabler-help',
|
||||
title: 'Help Center',
|
||||
subtitle: 'FAQs & Articles',
|
||||
to: { name: 'pages-help-center' },
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Shortcuts :shortcuts="shortcuts" />
|
||||
</template>
|
||||
@@ -0,0 +1,20 @@
|
||||
<script setup>
|
||||
const themes = [
|
||||
{
|
||||
name: 'system',
|
||||
icon: 'tabler-device-laptop',
|
||||
},
|
||||
{
|
||||
name: 'light',
|
||||
icon: 'tabler-sun-high',
|
||||
},
|
||||
{
|
||||
name: 'dark',
|
||||
icon: 'tabler-moon',
|
||||
},
|
||||
]
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ThemeSwitcher :themes="themes" />
|
||||
</template>
|
||||
@@ -0,0 +1,100 @@
|
||||
<script setup>
|
||||
import axiosIns from '@/plugins/axios'
|
||||
import { showToast } from '@/plugins/toast'
|
||||
import { useAuthStore } from '@/stores/auth'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const router = useRouter()
|
||||
|
||||
const icon = computed(() => {
|
||||
switch (authStore?.user?.role) {
|
||||
case 'admin':
|
||||
return 'tabler-shield-check'
|
||||
case 'doctor':
|
||||
return 'tabler-stethoscope'
|
||||
case 'patient':
|
||||
return 'tabler-user'
|
||||
}
|
||||
|
||||
return 'tabler-user'
|
||||
})
|
||||
|
||||
async function logout() {
|
||||
axiosIns.get('/api/v1/account/logout')
|
||||
.then(response => {
|
||||
authStore.deleteData()
|
||||
showToast('Logout successfully', 'success')
|
||||
router.push('/login')
|
||||
})
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<VCard
|
||||
class="cursor-pointer"
|
||||
color="primary"
|
||||
variant="outlined"
|
||||
:loading="!authStore?.user?.email"
|
||||
>
|
||||
<VCardItem class="py-0 px-2">
|
||||
<template #prepend>
|
||||
<VAvatar
|
||||
color="primary"
|
||||
variant="tonal"
|
||||
>
|
||||
<VIcon :icon="icon" size="32" color="primary" />
|
||||
</VAvatar>
|
||||
</template>
|
||||
<VCardTitle class="text-body-1 text-primary pa-0">
|
||||
{{ authStore?.user?.email }}
|
||||
</VCardTitle>
|
||||
<VCardSubtitle class="text-body-2 text-primary pa-0">
|
||||
{{ authStore?.role }}
|
||||
</VCardSubtitle>
|
||||
</VCardItem>
|
||||
|
||||
<!-- SECTION Menu -->
|
||||
<VMenu
|
||||
activator="parent"
|
||||
width="230"
|
||||
location="bottom end"
|
||||
offset="14px"
|
||||
>
|
||||
<VList>
|
||||
<!-- 👉 Profile -->
|
||||
<VListItem
|
||||
link
|
||||
to="/profile"
|
||||
>
|
||||
<template #prepend>
|
||||
<VIcon
|
||||
class="me-2"
|
||||
icon="tabler-user"
|
||||
size="22"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<VListItemTitle>Profile</VListItemTitle>
|
||||
</VListItem>
|
||||
|
||||
<!-- Divider -->
|
||||
<VDivider class="my-2" />
|
||||
|
||||
<!-- 👉 Logout -->
|
||||
<VListItem @click.prevent="logout">
|
||||
<template #prepend>
|
||||
<VIcon
|
||||
class="me-2"
|
||||
icon="tabler-logout"
|
||||
size="22"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<VListItemTitle>Logout</VListItemTitle>
|
||||
</VListItem>
|
||||
</VList>
|
||||
</VMenu>
|
||||
<!-- !SECTION -->
|
||||
</VCard>
|
||||
</template>
|
||||
Reference in New Issue
Block a user