header sidebar
This commit is contained in:
parent
f88deee0c3
commit
c6c096b312
|
|
@ -1,4 +1,3 @@
|
|||
<!-- app.vue -->
|
||||
<template>
|
||||
<UApp>
|
||||
<NuxtLayout>
|
||||
|
|
@ -11,7 +10,7 @@
|
|||
<script setup lang="ts">
|
||||
import { useHead } from "#imports";
|
||||
import { onMounted } from "vue";
|
||||
import { composSystemTheme } from "~/composables/composSystemTheme";
|
||||
import { composSystemTheme } from "@/composables/composSystemTheme";
|
||||
// تنظیم تم سیستم
|
||||
useHead({
|
||||
script: [
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<div class="col-span-3 lg:col-span-2 xl:col-span-3 hidden lg:block">
|
||||
<template v-if="headerSchema.breadcrumb">
|
||||
<Breadcrumb
|
||||
:breadcrumbData="[]"
|
||||
:breadcrumbData="defaultSidebar.topMenu"
|
||||
:tabs="tabs"
|
||||
:activeTabId="activeTabModel"
|
||||
/>
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
<template v-if="headerSchema.logo">
|
||||
<nuxt-link :to="{ name: 'DashboardBasePage' }">
|
||||
<div class="flex items-center gap-3">
|
||||
<img :src="useSystemTheme.logo.value" alt="" class="h-9 w-9" />
|
||||
<img :src="logoSrc" alt="" class="h-9 w-9" />
|
||||
<div v-if="useSystemTheme.currentTheme.value" class="flex flex-col">
|
||||
<span class="font-bold text-gray-900 dark:text-light-primary">
|
||||
{{ useSystemTheme.currentTheme.value.title || "" }}
|
||||
|
|
@ -29,8 +29,8 @@
|
|||
</div>
|
||||
<div class="col-span-3 lg:col-span-2 xl:col-span-3 lg:hidden">
|
||||
<button
|
||||
@click="toggleSidebarMenu"
|
||||
class="flex items-center justify-center w-8 h-8 rounded-md text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-dark-primary-800 transition-colors duration-200"
|
||||
@click="commonStore.toggleSidebar"
|
||||
class="flex cursor-pointer items-center justify-center w-8 h-8 rounded-md text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-dark-primary-800 transition-colors duration-200"
|
||||
aria-label="باز کردن منو"
|
||||
>
|
||||
<UIcon name="i-heroicons-bars-3" class="w-5 h-5" />
|
||||
|
|
@ -123,6 +123,7 @@
|
|||
import { ref, computed, onMounted } from "vue";
|
||||
import headerItems from "@/json/header/header.json";
|
||||
import { composSystemTheme } from "@/composables/composSystemTheme";
|
||||
import defaultSidebar from "@/json/sidebar/dashboard.json";
|
||||
import { useCommonStore } from "@/stores/commonStore";
|
||||
import { useAuthStore } from "@/stores/authStore";
|
||||
import { useRouter } from "vue-router";
|
||||
|
|
@ -144,7 +145,7 @@ const emit = defineEmits([
|
|||
"tab-change",
|
||||
"user-menu-select",
|
||||
]);
|
||||
|
||||
const logoSrc = ref("");
|
||||
/* ---------------- ACTIVE TAB ---------------- */
|
||||
const activeTabModel = computed({
|
||||
get: () => props.activeTab,
|
||||
|
|
@ -197,9 +198,6 @@ const userMenuItems = computed(() =>
|
|||
|
||||
// const userAvatar = "https://api.dicebear.com/7.x/avataaars/svg?seed=admin";
|
||||
const isClient = ref(false);
|
||||
onMounted(() => {
|
||||
isClient.value = true;
|
||||
});
|
||||
|
||||
const userAvatar = computed(() => {
|
||||
if (!process.client) return null;
|
||||
|
|
@ -237,7 +235,14 @@ const userInitial = computed(() => {
|
|||
return "؟";
|
||||
}
|
||||
});
|
||||
function toggleSidebarMenu() {
|
||||
commonStore.isSidebarOpen();
|
||||
}
|
||||
// function toggleSidebarMenu() {
|
||||
// commonStore.isSidebarOpen();
|
||||
// }
|
||||
onMounted(() => {
|
||||
isClient.value = true;
|
||||
useSystemTheme.applyTheme();
|
||||
setTimeout(() => {
|
||||
logoSrc.value = useSystemTheme.logo.value;
|
||||
}, 300);
|
||||
});
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -4,41 +4,44 @@
|
|||
side="left"
|
||||
:collapsed="collapsed"
|
||||
collapsible
|
||||
:min-size="5"
|
||||
:default-size="10"
|
||||
:max-size="15"
|
||||
:ui="sidebarUI"
|
||||
class="sidebar-gradient"
|
||||
:style="{ width: collapsed ? '2%' : '8%' }"
|
||||
dir="rtl"
|
||||
@update:collapsed="onCollapse"
|
||||
>
|
||||
<template #header>
|
||||
<nuxt-link :to="{ name: 'DashboardBasePage' }">
|
||||
<div class="flex items-center gap-3">
|
||||
<img :src="useSystemTheme.logo.value" alt="" class="h-9 w-9" />
|
||||
<div
|
||||
v-if="useSystemTheme.currentTheme.value && !collapsed"
|
||||
class="flex flex-col"
|
||||
<nuxt-link
|
||||
:to="{ name: 'DashboardBasePage' }"
|
||||
class="w-full flex justify-center items-center"
|
||||
>
|
||||
<span class="font-bold text-gray-900 dark:text-light-primary">
|
||||
{{ useSystemTheme.currentTheme.value.title || "" }}
|
||||
</span>
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ useSystemTheme.currentTheme.value.subTitle || "" }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-3">
|
||||
<img :src="logoSrc" alt="" class="h-9 w-9" />
|
||||
</div>
|
||||
</nuxt-link>
|
||||
</template>
|
||||
|
||||
<!-- <div
|
||||
v-if="useSystemTheme?.currentTheme?.value && !collapsed"
|
||||
class="flex flex-col"
|
||||
>
|
||||
<span class="font-bold text-gray-900 dark:text-light-primary">
|
||||
{{ useSystemTheme?.currentTheme?.value?.title || "" }}
|
||||
</span>
|
||||
<span class="text-xs text-gray-500 dark:text-gray-400">
|
||||
{{ useSystemTheme?.currentTheme?.value?.subTitle || "" }}
|
||||
</span>
|
||||
</div> -->
|
||||
<template #default>
|
||||
<div class="">
|
||||
|
||||
<UNavigationMenu
|
||||
dir="rtl"
|
||||
:collapsed="collapsed"
|
||||
:items="getSideBarSchema()?.topMenu || []"
|
||||
orientation="vertical"
|
||||
:items="getSideBarSchema()?.topMenu || []"
|
||||
:collapsed="collapsed"
|
||||
:ui="navigationUI"
|
||||
class="w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
@ -50,21 +53,36 @@
|
|||
orientation="vertical"
|
||||
:ui="navigationUI"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer="{ collapsed }">
|
||||
<div>
|
||||
<UTooltip
|
||||
arrow
|
||||
dir="rtl"
|
||||
:text="user?.first_name + ' ' + user?.last_name"
|
||||
>
|
||||
<UButton
|
||||
:avatar="{ src: '' }"
|
||||
:label="collapsed ? undefined : 'مدیرفنی سامانه'"
|
||||
:avatar="
|
||||
user?.avatar
|
||||
? { src: user?.avatar }
|
||||
: {
|
||||
label:
|
||||
(user?.first_name?.[0] || '') +
|
||||
(user?.last_name?.[0] || ''),
|
||||
}
|
||||
"
|
||||
:label="
|
||||
collapsed ? '' : user?.first_name + ' ' + user?.last_name || ''
|
||||
"
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
class="w-full"
|
||||
:block="collapsed"
|
||||
/>
|
||||
/></UTooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div>
|
||||
<!-- دکمههای باز/بسته کردن سایدبار -->
|
||||
<div class="flex justify-center items-center gap-2 mt-2">
|
||||
<div class="flex justify-center items-center gap-2 mt-4">
|
||||
<!-- دکمه باز کردن -->
|
||||
<UButton
|
||||
v-if="collapsed"
|
||||
|
|
@ -89,12 +107,85 @@
|
|||
</div>
|
||||
</template>
|
||||
</UDashboardSidebar>
|
||||
<USlideover
|
||||
v-model:open="sidebarOpenComputed"
|
||||
side="right"
|
||||
overlay
|
||||
class="lg:hidden"
|
||||
:dismissible="true"
|
||||
dir="rtl"
|
||||
:title="
|
||||
useSystemTheme?.currentTheme?.value?.title +
|
||||
' - ' +
|
||||
useSystemTheme?.currentTheme?.value?.subTitle || ''
|
||||
"
|
||||
>
|
||||
<template #body>
|
||||
<div class="p-4 flex flex-col h-full">
|
||||
<UNavigationMenu
|
||||
orientation="vertical"
|
||||
:items="filteredSidebar.topMenu"
|
||||
@click="onMenuSelect"
|
||||
dir="rtl"
|
||||
/>
|
||||
|
||||
<div class="mt-auto">
|
||||
<UNavigationMenu
|
||||
orientation="vertical"
|
||||
:items="filteredSidebar.bottomMenu"
|
||||
@click="onMenuSelect"
|
||||
dir="rtl"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer="{ collapsed }">
|
||||
<div>
|
||||
<UButton
|
||||
:avatar="
|
||||
user?.avatar
|
||||
? { src: user?.avatar }
|
||||
: {
|
||||
label:
|
||||
(user?.first_name?.[0] || '') +
|
||||
(user?.last_name?.[0] || ''),
|
||||
}
|
||||
"
|
||||
:label="
|
||||
collapsed ? '' : user?.first_name + ' ' + user?.last_name || ''
|
||||
"
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
class="w-full"
|
||||
:block="collapsed"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</USlideover>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref} from "vue";
|
||||
import { ref, onMounted } from "vue";
|
||||
import { composSystemTheme } from "@/composables/composSystemTheme";
|
||||
import { storeToRefs } from "pinia";
|
||||
import { useCommonStore } from "@/stores/commonStore";
|
||||
|
||||
const commonStore = useCommonStore();
|
||||
const { sidebarOpen } = storeToRefs(commonStore);
|
||||
|
||||
// proxy امن برای v-model:open
|
||||
const sidebarOpenComputed = computed({
|
||||
get: () => sidebarOpen.value,
|
||||
set: (v) => (commonStore.sidebarOpen = v),
|
||||
});
|
||||
const filteredSidebar = computed(
|
||||
() => props.sidebarItems || { topMenu: [], bottomMenu: [] },
|
||||
);
|
||||
|
||||
function onMenuSelect() {
|
||||
// وقتی کاربر آیتم منو رو زد، اسلایداور رو ببند
|
||||
commonStore.closeSidebar();
|
||||
}
|
||||
const useSystemTheme = composSystemTheme();
|
||||
|
||||
const props = defineProps({
|
||||
|
|
@ -110,27 +201,35 @@ const props = defineProps({
|
|||
|
||||
const emit = defineEmits(["update:collapsed"]);
|
||||
|
||||
const logoSrc = ref("");
|
||||
const collapsed = ref(false);
|
||||
|
||||
const user = ref({ first_name: "", last_name: "", avatar: "" });
|
||||
const onCollapse = (value) => {
|
||||
collapsed.value = value;
|
||||
emit("update:collapsed", value);
|
||||
};
|
||||
|
||||
function getSideBarSchema() {
|
||||
|
||||
const config = useRuntimeConfig();
|
||||
const IS_DEVLOP_MODE = config.public.IS_DEVLOP_MODE || 1;
|
||||
const NUXT_PUBLIC_IS_DEVLOP_MODE = Number(
|
||||
config.public?.NUXT_PUBLIC_IS_DEVLOP_MODE ?? 1,
|
||||
);
|
||||
|
||||
const filterMenu = (menu) => {
|
||||
if (NUXT_PUBLIC_IS_DEVLOP_MODE === 1) return menu || [];
|
||||
return (
|
||||
menu?.filter(
|
||||
(el) => el.develop === undefined || Number(el.develop) === 0,
|
||||
) || []
|
||||
);
|
||||
};
|
||||
|
||||
let result = {}
|
||||
const topMenuFiltered = filterMenu(props.sidebarItems?.topMenu);
|
||||
const bottomMenuFiltered = filterMenu(props.sidebarItems?.bottomMenu);
|
||||
|
||||
result.topMenu = props.sidebarItems?.topMenu.filter((el) => (!el.develop || el.develop == IS_DEVLOP_MODE) )
|
||||
result.bottomMenu = props.sidebarItems?.bottomMenu.filter((el) => (!el.develop || el.develop == IS_DEVLOP_MODE) )
|
||||
|
||||
// console.log("SideBar IS_DEVLOP_MODE ", IS_DEVLOP_MODE, result);
|
||||
|
||||
return result
|
||||
return {
|
||||
topMenu: topMenuFiltered,
|
||||
bottomMenu: bottomMenuFiltered,
|
||||
};
|
||||
}
|
||||
|
||||
// تابع برای باز/بسته کردن نرم سایدبار
|
||||
|
|
@ -140,8 +239,6 @@ const toggleSidebar = () => {
|
|||
};
|
||||
|
||||
const sidebarUI = {
|
||||
width: "w-72",
|
||||
collapsed: { width: "w-16" },
|
||||
wrapper:
|
||||
"z-30 h-[calc(100vh-64px)] top-16 rounded-r-2xl border-r border-gray-200/50 dark:border-dark-primary-800/50 backdrop-blur-sm transition-all duration-300",
|
||||
base: "backdrop-blur-sm transition-all duration-300 ease-out",
|
||||
|
|
@ -158,6 +255,21 @@ const navigationUI = {
|
|||
"bg-gradient-to-r from-blue-100 to-blue-50/30 dark:from-blue-900/30 dark:to-blue-900/10 text-blue-600 dark:text-blue-400 font-semibold shadow-sm",
|
||||
icon: { base: "transition-transform duration-300", active: "scale-110" },
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
useSystemTheme.applyTheme();
|
||||
setTimeout(() => {
|
||||
logoSrc.value = useSystemTheme.logo.value;
|
||||
}, 300);
|
||||
const stored = localStorage.getItem("user");
|
||||
if (stored) {
|
||||
try {
|
||||
user.value = JSON.parse(stored);
|
||||
} catch (e) {
|
||||
console.error("خطا در خواندن کاربر از localStorage:", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
|
|
|||
|
|
@ -7,12 +7,6 @@
|
|||
"icon": "i-lucide-list",
|
||||
"active": true
|
||||
},
|
||||
{
|
||||
"id": "RuleEdit",
|
||||
"label": "احکام",
|
||||
"key": "RuleEdit",
|
||||
"icon": "i-lucide-scroll-text"
|
||||
},
|
||||
{
|
||||
"id": "RelationEdit",
|
||||
"key": "RelationEdit",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user