hgh_admin/resources/js/views/front-pages/front-page-navbar.vue
2024-05-29 22:34:28 +05:00

527 lines
14 KiB
Vue

<script setup>
import { useWindowScroll } from '@vueuse/core'
import { useDisplay } from 'vuetify'
import NavbarThemeSwitcher from '@/layouts/components/NavbarThemeSwitcher.vue'
import navImgDark from '@images/front-pages/misc/nav-img-dark.png'
import navImgLight from '@images/front-pages/misc/nav-img-light.png'
import { VNodeRenderer } from '@layouts/components/VNodeRenderer'
import { themeConfig } from '@themeConfig'
const props = defineProps({ activeId: String })
const display = useDisplay()
const route = useRoute()
const router = useRouter()
const navImg = useGenerateImageVariant(navImgLight, navImgDark)
const { y } = useWindowScroll()
const sidebar = ref(false)
watch(() => display, () => {
return display.mdAndUp ? sidebar.value = false : sidebar.value
}, { deep: true })
const isMenuOpen = ref(false)
const menuItems = [
{
listTitle: 'Page',
listIcon: 'ri-layout-grid-line',
navItems: [
{
name: 'Pricing',
to: { name: 'front-pages-pricing' },
},
{
name: 'Payment',
to: { name: 'front-pages-payment' },
},
{
name: 'Checkout',
to: { name: 'front-pages-checkout' },
},
{
name: 'Help Center',
to: { name: 'front-pages-help-center' },
},
],
},
{
listTitle: 'Auth Demo',
listIcon: 'ri-lock-unlock-line',
navItems: [
{
name: 'Login (Basic)',
to: { name: 'pages-authentication-login-v1' },
},
{
name: 'Login (Cover)',
to: { name: 'pages-authentication-login-v2' },
},
{
name: 'Register (Basic)',
to: { name: 'pages-authentication-register-v1' },
},
{
name: 'Register (Cover)',
to: { name: 'pages-authentication-register-v2' },
},
{
name: 'Register (Multi-steps)',
to: { name: 'pages-authentication-register-multi-steps' },
},
{
name: 'Forgot Password (Basic)',
to: { name: 'pages-authentication-forgot-password-v1' },
},
{
name: 'Forgot Password (Cover)',
to: { name: 'pages-authentication-forgot-password-v2' },
},
{
name: 'Reset Password (Basic)',
to: { name: 'pages-authentication-reset-password-v1' },
},
{
name: 'Reset Password (cover )',
to: { name: 'pages-authentication-reset-password-v2' },
},
],
},
{
listTitle: 'Other',
listIcon: 'ri-image-line',
navItems: [
{
name: 'Under Maintenance',
to: { name: 'pages-misc-under-maintenance' },
},
{
name: 'Coming Soon',
to: { name: 'pages-misc-coming-soon' },
},
{
name: 'Not Authorized',
to: { path: '/not-authorized' },
},
{
name: 'Verify Email (Basic)',
to: { name: 'pages-authentication-verify-email-v1' },
},
{
name: 'Verify Email (Cover)',
to: { name: 'pages-authentication-verify-email-v2' },
},
{
name: 'Two Steps (Basic)',
to: { name: 'pages-authentication-two-steps-v1' },
},
{
name: 'Two Steps (Cover)',
to: { name: 'pages-authentication-two-steps-v2' },
},
],
},
]
const isCurrentRoute = to => {
return route.matched.some(_route => _route.path === router.resolve(to).path)
}
const isPageActive = computed(() => menuItems.some(item => item.navItems.some(listItem => isCurrentRoute(listItem.to))))
</script>
<template>
<!-- 👉 Navigation drawer for mobile devices -->
<VNavigationDrawer
v-model="sidebar"
disable-resize-watcher
>
<!-- Nav items -->
<div>
<div class="d-flex flex-column gap-y-4 pa-4">
<RouterLink
v-for="(item, index) in ['Home', 'Features', 'Team', 'FAQ', 'Contact us']"
:key="index"
:to="{ name: 'front-pages-landing-page', hash: `#${item.toLowerCase().replace(' ', '-')}` }"
class="font-weight-medium"
:class="[props.activeId?.toLocaleLowerCase().replace('-', ' ') === item.toLocaleLowerCase() ? 'active-link' : 'text-high-emphasis']"
>
{{ item }}
</RouterLink>
<div
class="text-high-emphasis font-weight-medium cursor-pointer"
:class="isPageActive ? 'active-link' : 'text-high-emphasis'"
>
<div
:class="isMenuOpen ? 'mb-6' : ''"
@click="isMenuOpen = !isMenuOpen"
>
Pages <VIcon :icon="isMenuOpen ? 'ri-arrow-up-s-line' : 'ri-arrow-down-s-line'" />
</div>
<div
v-for="(item, index) in menuItems"
:key="index"
:class="isMenuOpen ? 'd-block' : 'd-none'"
>
<div class="d-flex align-center gap-x-3 mb-4">
<VAvatar
variant="tonal"
color="primary"
rounded
:icon="item.listIcon"
/>
<div class="text-body-1 text-high-emphasis font-weight-medium">
{{ item.listTitle }}
</div>
</div>
<ul class="mb-6">
<li
v-for="listItem in item.navItems"
:key="listItem.name"
style="list-style: none;"
class="text-body-1 mb-4"
>
<RouterLink
:to="listItem.to"
:target="item.listTitle === 'Page' ? '_self' : '_blank'"
class="mega-menu-item"
:class="isCurrentRoute(listItem.to) ? 'active-link' : ''"
>
<VIcon
icon="ri-circle-line"
:size="10"
class="me-2"
/>
<span> {{ listItem.name }}</span>
</RouterLink>
</li>
</ul>
</div>
</div>
<RouterLink
to="/"
target="_blank"
class="text-body-1 font-weight-medium nav-link px-0"
>
Admin
</RouterLink>
</div>
</div>
<!-- Navigation drawer close icon -->
<VIcon
id="navigation-drawer-close-btn"
icon="ri-close-line"
size="20"
@click="sidebar = !sidebar"
/>
</VNavigationDrawer>
<!-- 👉 Navbar for desktop devices -->
<div class="front-page-navbar">
<VAppBar
:class="y > 20 ? 'front-page-navbar-box-shadow' : ''"
elevation="0"
class="rounded-b-lg"
>
<!-- toggle icon for mobile device -->
<VAppBarNavIcon
:class="$vuetify.display.mdAndUp ? 'd-none' : 'd-inline-block'"
class="ms-0 me-1"
color="high-emphasis"
@click="() => sidebar = !sidebar"
/>
<!-- Title and Landing page sections -->
<div class="d-flex align-center">
<VAppBarTitle class="me-6">
<RouterLink
to="/"
class="d-flex gap-x-4"
:class="$vuetify.display.mdAndUp ? 'd-none' : 'd-block'"
>
<div class="d-flex gap-x-3 align-center">
<VNodeRenderer :nodes="themeConfig.app.logo" />
<div
class="nav-title text-uppercase text-truncate"
:class="[$vuetify.display.lgAndUp ? 'd-block' : 'd-none', $vuetify.display.mdAndUp ? 'd-none' : 'd-block']"
>
{{ themeConfig.app.title }}
</div>
</div>
</RouterLink>
</VAppBarTitle>
<!-- landing page sections -->
<div
:class="$vuetify.display.mdAndUp ? 'd-flex' : 'd-none'"
class="text-base align-center gap-x-2"
>
<RouterLink
v-for="(item, index) in ['Home', 'Features', 'Team', 'FAQ', 'Contact us']"
:key="index"
:to="{ name: 'front-pages-landing-page', hash: `#${item.toLowerCase().replace(' ', '-')}` }"
class="nav-link font-weight-medium"
:class="[props.activeId?.toLocaleLowerCase().replace('-', ' ') === item.toLocaleLowerCase() ? 'active-link' : '']"
>
{{ item }}
</RouterLink>
<!-- Pages Menu -->
<span
class="font-weight-medium cursor-pointer nav-link"
:class="isPageActive ? 'active-link' : 'text-high-emphasis'"
>
Pages
<VIcon
icon="ri-arrow-down-s-line"
size="20"
class="ms-2"
/>
<VMenu
open-on-hover
activator="parent"
transition="slide-y-transition"
location="bottom center"
offset="16"
content-class="mega-menu"
location-strategy="static"
close-on-content-click
>
<VCard max-width="1000">
<VCardText class="pa-8">
<div class="nav-menu">
<div
v-for="(item, index) in menuItems"
:key="index"
>
<div class="d-flex align-center gap-x-3 mb-6">
<VAvatar
variant="tonal"
color="primary"
rounded
:icon="item.listIcon"
/>
<div class="text-body-1 text-high-emphasis font-weight-medium">
{{ item.listTitle }}
</div>
</div>
<ul>
<li
v-for="listItem in item.navItems"
:key="listItem.name"
style="list-style: none;"
class="text-body-1 mb-4 text-no-wrap"
>
<RouterLink
class="mega-menu-item"
:to="listItem.to"
:target="item.listTitle === 'Page' ? '_self' : '_blank'"
:class="isCurrentRoute(listItem.to) ? 'active-link' : ''"
>
<div class="d-flex align-center">
<VIcon
icon="ri-circle-line"
:size="10"
class="me-2"
/>
<span>{{ listItem.name }}</span>
</div>
</RouterLink>
</li>
</ul>
</div>
<img
:src="navImg"
alt="Navigation Image"
class="d-inline-block rounded-lg"
style="border: 10px solid rgb(var(--v-theme-background));"
:width="$vuetify.display.lgAndUp ? '330' : '250'"
:height="$vuetify.display.lgAndUp ? '330' : '250'"
>
</div>
</VCardText>
</VCard>
</VMenu>
</span>
<RouterLink
to="/"
target="_blank"
class="nav-link font-weight-medium"
>
Admin
</RouterLink>
</div>
</div>
<VSpacer />
<div class="d-flex gap-x-4 align-center">
<NavbarThemeSwitcher class="me-0 me-sm-2" />
<VBtn
v-if="$vuetify.display.lgAndUp"
prepend-icon="ri-shopping-cart-line"
variant="elevated"
color="primary"
href="https://themeselection.com/item/materio-vuetify-vuejs-laravel-admin-template/"
target="_blank"
rel="noopener noreferrer"
>
Purchase Now
</VBtn>
<VBtn
v-else
variant="elevated"
color="primary"
href="https://themeselection.com/item/materio-vuetify-vuejs-admin-template/"
target="_blank"
rel="noopener noreferrer"
>
<VIcon icon="ri-shopping-cart-line" />
</VBtn>
</div>
</VAppBar>
</div>
</template>
<style lang="scss" scoped>
.front-page-navbar-box-shadow{
/* stylelint-disable-next-line max-line-length */
box-shadow: 0 4px 8px -4px rgba(var(--v-shadow-key-umbra-color), 42%) !important;
}
.nav-menu{
display: flex;
gap: 3rem;
}
.nav-title{
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity)) !important;
font-size: 1.25rem;
font-weight: 600;
letter-spacing: 0.15px;
line-height: 1.5rem;
}
.nav-link{
padding-inline: 0.625rem;
&:not(:hover){
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity))
}
}
@media (min-width: 1920px) {
.front-page-navbar {
.v-toolbar {
max-inline-size: calc(1440px - 32px);
}
}
}
@media (min-width: 1280px) and (max-width: 1919px) {
.front-page-navbar {
.v-toolbar {
max-inline-size: calc(1200px - 32px);
}
}
}
@media (min-width: 960px) and (max-width: 1279px) {
.front-page-navbar {
.v-toolbar {
max-inline-size: calc(900px - 32px);
}
}
.nav-menu{
gap: 2rem;
}
}
@media (min-width: 600px) and (max-width: 959px) {
.front-page-navbar {
.v-toolbar {
max-inline-size: calc(100% - 64px);
}
}
}
@media (max-width: 600px) {
.front-page-navbar {
.v-toolbar {
max-inline-size: calc(100% - 32px);
}
}
}
.nav-item-img {
border: 10px solid rgb(var(--v-theme-background));
border-radius: 10px;
}
.active-link {
color: rgb(var(--v-theme-primary)) !important;
}
.mega-menu-item {
&:not(:hover){
color: rgba(var(--v-theme-on-surface), var(--v-high-emphasis-opacity))
}
}
</style>
<style lang="scss">
@use "@layouts/styles/mixins" as layoutMixins;
.mega-menu{
position: fixed !important;
inset-block-start: 4.1rem;
inset-inline-start: 50%;
transform: translateX(-50%);
}
.front-page-navbar {
.v-toolbar__content {
padding-inline: 2rem !important;
}
.v-toolbar {
inset-inline: 0 !important;
margin-inline: auto !important;
}
}
#navigation-drawer-close-btn {
position: absolute;
cursor: pointer;
inset-block-start: 0.5rem;
inset-inline-end: 1rem;
}
@media (max-width: 600px) {
.front-page-navbar {
.v-toolbar__content {
padding-inline: 0.75rem !important;
}
}
}
@media (min-width: 600px) and (max-width: 959px) {
.front-page-navbar {
.v-toolbar__content {
padding-inline: 1rem !important;
}
}
}
</style>