Initial commit
This commit is contained in:
171
app/components/TopMenu.vue
Normal file
171
app/components/TopMenu.vue
Normal file
@@ -0,0 +1,171 @@
|
||||
<template>
|
||||
<nav class="navbar is-fixed-top has-shadow px-3" role="navigation">
|
||||
<div class="navbar-brand mr-5">
|
||||
<span class="navbar-item">
|
||||
<SvgIcon v-bind="{ name: 'dot.svg', size: 18, type: 'primary' }"</SvgIcon>
|
||||
<span class="fsb-20 has-text-primary">{{$dayjs().format('DD/MM')}}</span>
|
||||
</span>
|
||||
<a class="navbar-item header-logo" @click="changeTab(leftmenu[0])"></a>
|
||||
<a
|
||||
role="button"
|
||||
class="navbar-burger"
|
||||
id="burger"
|
||||
aria-label="menu"
|
||||
aria-expanded="false"
|
||||
data-target="navMenu"
|
||||
@click="handleClick()"
|
||||
>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="navbar-menu" id="navMenu">
|
||||
<div class="navbar-start" style="min-width: 650px;">
|
||||
<template v-for="(v, i) in leftmenu" :key="i" :id="v.code">
|
||||
<a class="navbar-item px-2" v-if="!v.submenu" @click="changeTab(v)">
|
||||
<span
|
||||
:class="`fsb-17 ${currentTab.code === v.code ? 'activetab' : ''}`"
|
||||
style="padding: 3px 4px"
|
||||
>
|
||||
{{ v[lang] }}
|
||||
</span>
|
||||
</a>
|
||||
<div class="navbar-item has-dropdown is-hoverable" v-else>
|
||||
<a class="navbar-item px-2" @click="changeTab(v)">
|
||||
<span
|
||||
:class="`icon-text ${currentTab.code === v.code ? 'activetab' : ''}`"
|
||||
style="padding: 3px 4px"
|
||||
>
|
||||
<span class="fsb-16">{{ v[lang] }}</span>
|
||||
<SvgIcon
|
||||
style="padding-top: 5px"
|
||||
v-bind="{ name: 'down2.svg', type: currentTab.code === v.code ? 'white' : 'dark', size: 15 }"
|
||||
>
|
||||
</SvgIcon>
|
||||
</span>
|
||||
</a>
|
||||
<div class="navbar-dropdown has-background-light">
|
||||
<a
|
||||
class="navbar-item has-background-light fs-15 has-text-black py-1 border-bottom"
|
||||
v-for="x in v.submenu"
|
||||
@click="changeTab(v, x)"
|
||||
>
|
||||
{{ x[lang] }}
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
<div class="navbar-end">
|
||||
<a class="navbar-item" @click="changeTab(tabConfig)" v-if="tabConfig">
|
||||
<SvgIcon v-bind="{ name: 'configuration.svg', type: 'findata', size: 24 }"></SvgIcon>
|
||||
</a>
|
||||
<a class="navbar-item" @click="openProfile()" v-if="avatar">
|
||||
<Avatarbox v-bind="avatar"></Avatarbox>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
||||
<script setup>
|
||||
import { watch } from "vue";
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const emit = defineEmits(["changetab", "langChanged"]);
|
||||
const { $find, $filter, $findIndex, $store } = useNuxtApp();
|
||||
const lang = ref($store.lang);
|
||||
var menu = $filter($store.common, { category: "topmenu" });
|
||||
if($store.rights.length>0) {
|
||||
menu = menu.filter(v=>$findIndex($store.rights, {setting: v.id})>=0)
|
||||
}
|
||||
if(menu.length===0) {
|
||||
$snackbar($store.lang==='vi'? 'Bạn không có quyền truy cập' : 'You do not have permission to access.')
|
||||
}
|
||||
menu.map(v=>{
|
||||
let arr = $filter($store.common, {category: 'submenu', classify: v.code})
|
||||
if($store.rights.length>0) {
|
||||
arr = arr.filter(x=>$findIndex($store.rights, {setting: x.id})>=0)
|
||||
}
|
||||
v.submenu = arr.length>0? arr : null
|
||||
})
|
||||
var leftmenu = $filter(menu, {category: 'topmenu', classify: 'left'})
|
||||
var currentTab = ref(leftmenu.length>0? leftmenu[0] : undefined)
|
||||
var subTab = ref();
|
||||
var tabConfig = $find(menu, { code: "configuration" });
|
||||
var avatar = ref();
|
||||
var isAdmin = ref();
|
||||
const handleClick = function () {
|
||||
const target = document.getElementById("burger");
|
||||
target.classList.toggle("is-active");
|
||||
const target1 = document.getElementById("navMenu");
|
||||
target1.classList.toggle("is-active");
|
||||
};
|
||||
const closeMenu = function () {
|
||||
if (!document) return;
|
||||
const target = document.getElementById("burger");
|
||||
const target1 = document.getElementById("navMenu");
|
||||
if (!target) return;
|
||||
if (target.classList.contains("is-active")) {
|
||||
target.classList.remove("is-active");
|
||||
target1.classList.remove("is-active");
|
||||
}
|
||||
};
|
||||
function changeTab(tab, subtab) {
|
||||
if (tab.submenu && tab.submenu.length > 0 && !subtab && !tab.detail) {
|
||||
subtab = tab.submenu[0];
|
||||
}
|
||||
currentTab.value = tab;
|
||||
subTab.value = subtab;
|
||||
emit("changetab", tab, subtab);
|
||||
closeMenu();
|
||||
let query = subtab ? { tab: tab.code, subtab: subtab.code } : { tab: tab.code };
|
||||
router.push({ query: query });
|
||||
}
|
||||
function openProfile() {
|
||||
let modal = { component: "user/Profile", width: "1100px", height: "360px", title: $store.lang==='vi'? 'Thông tin cá nhân' : '"User profile"' };
|
||||
$store.commit("showmodal", modal);
|
||||
}
|
||||
let found = route.query.tab? $find(menu, {code: route.query.tab}) : undefined
|
||||
if(found || currentTab.value) changeTab(found || currentTab.value)
|
||||
onMounted(() => {
|
||||
if (!$store.login) return;
|
||||
avatar.value = {
|
||||
image: null,
|
||||
text: $store.login.fullname.substring(0, 1).toUpperCase(),
|
||||
size: "two",
|
||||
type: "findata",
|
||||
};
|
||||
isAdmin.value = $store.login.type__code === "admin";
|
||||
});
|
||||
watch(
|
||||
() => $store.login,
|
||||
(newVal, oldVal) => {
|
||||
if (!newVal) return;
|
||||
avatar.value = {
|
||||
image: null,
|
||||
text: $store.login.fullname.substring(0, 1).toUpperCase(),
|
||||
size: "two",
|
||||
type: "findata",
|
||||
};
|
||||
isAdmin.value = $store.login.type__code === "admin";
|
||||
lang.value = $store.lang;
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style scoped>
|
||||
.navbar-dropdown {
|
||||
padding-block: 0.375rem;
|
||||
overflow: hidden;
|
||||
}
|
||||
.navbar-dropdown > .navbar-item {
|
||||
&:hover {
|
||||
background-color: hsl(30, 48%, 82%) !important;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user