complete Complete User Request Submission section RAD-1
This commit is contained in:
@@ -0,0 +1,249 @@
|
||||
<script setup lang="ts">
|
||||
import {ref, computed, onMounted, watch} from 'vue';
|
||||
import {Link, usePage} from '@inertiajs/inertia-vue3';
|
||||
import type { Ref } from 'vue';
|
||||
import type { MenuItem } from 'primevue/menuitem';
|
||||
import {useGlobalStore} from '../store/Global';
|
||||
|
||||
interface SidebarItem extends MenuItem {
|
||||
label: string;
|
||||
icon?: string;
|
||||
to?: string;
|
||||
expanded?: boolean;
|
||||
items?: SidebarItem[];
|
||||
permission?: string | null;
|
||||
}
|
||||
|
||||
const globalStore = useGlobalStore();
|
||||
const {url ,props} = usePage();
|
||||
const currentUser = ref(props.value.auth.User);
|
||||
|
||||
const userPermissions = computed(() => props.value.auth.permissions ?? []);
|
||||
|
||||
function hasPermission(permission) {
|
||||
if (!permission) return true;
|
||||
return userPermissions.value.includes(permission);
|
||||
}
|
||||
|
||||
function filterSidebarItems(items) {
|
||||
return items
|
||||
.filter(item => hasPermission(item.permission))
|
||||
.map(item => {
|
||||
if (item.items) {
|
||||
const filteredChildren = filterSidebarItems(item.items);
|
||||
if (filteredChildren.length > 0) {
|
||||
return { ...item, items: filteredChildren };
|
||||
} else if (!item.permission) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return item;
|
||||
})
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
const filteredItems = computed(() => filterSidebarItems(items.value));
|
||||
|
||||
// @ts-ignore
|
||||
const items: Ref<SidebarItem[]> = ref([
|
||||
{
|
||||
label: "داشبورد",
|
||||
icon: "fi fi-rr-dashboard",
|
||||
to: "/admin/dashboard",
|
||||
key: 'panel',
|
||||
expanded: false,
|
||||
permission: null,
|
||||
},
|
||||
{
|
||||
label: "همه کیس ها",
|
||||
icon: "fi fi-rr-document",
|
||||
to: "",
|
||||
key: 'pets',
|
||||
permission: null,
|
||||
expanded: false,
|
||||
items: [
|
||||
{ label: "همه کیس ها", icon: "fi fi-rr-wifi-1", to: "/admin/pets" , permission: "pets.index" },
|
||||
{ label: "افزودن کیس جدید", icon: "fi fi-rr-wifi-1", to: "/admin/pets/create" , permission: "pets.create" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "همه پرونده ها",
|
||||
icon: "fi fi-rr-document",
|
||||
to: "",
|
||||
key: 'documents',
|
||||
permission: null,
|
||||
expanded: false,
|
||||
items: [
|
||||
{ label: "همه پرونده ها", icon: "fi fi-rr-wifi-1", to: "/admin/documents" , permission: "documents.index" },
|
||||
{ label: "افزودن پرونده جدید", icon: "fi fi-rr-wifi-1", to: "/admin/documents/create" , permission: "documents.create" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "همه گزارش ها",
|
||||
icon: "fi fi-rr-document",
|
||||
to: "/admin/reports",
|
||||
key: 'reports',
|
||||
permission: "reports.index",
|
||||
expanded: false,
|
||||
},
|
||||
{
|
||||
label: "مدیریت رسانه",
|
||||
icon: "fi fi-rr-gallery",
|
||||
to: "/admin/medium",
|
||||
key: 'medium',
|
||||
permission: "medium.index",
|
||||
},
|
||||
{
|
||||
label: "مدیریت دسترسی ها",
|
||||
icon: "fi fi-rr-user-permissions",
|
||||
key: 'roles',
|
||||
expanded: false,
|
||||
permission: null,
|
||||
items: [
|
||||
{ label: " مدیریت مقام ها", icon: "fi fi-rr-wifi-1", to: "/admin/roles", permission: "roles.index" },
|
||||
{ label: "مدیریت سطح ها", icon: "fi fi-rr-wifi-1", to: "/admin/permissions", permission: "permissions.index" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "کاربران",
|
||||
icon: "fi fi-rr-user",
|
||||
key: 'users',
|
||||
expanded: false,
|
||||
permission: null,
|
||||
items: [
|
||||
{ label: "همه کاربران", icon: "fi fi-rr-wifi-1", to: "/admin/users", permission: "users.index" },
|
||||
{ label: "افزودن کاربر جدید", icon: "fi fi-rr-wifi-1", to: "/admin/users/create", permission: "users.create" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "تنظیمات",
|
||||
icon: "fi fi-rr-settings",
|
||||
key: 'settings',
|
||||
expanded: false,
|
||||
permission: null,
|
||||
items: [
|
||||
{ label: "اطلاعات کاربری",icon: "fi fi-rr-wifi-1", to: "/admin/setting-profile", permission: null },
|
||||
{ label: "تنظیمات امنیتی", icon: "fi fi-rr-wifi-1", to: "/admin/setting-profile/security", permission: null },
|
||||
{ label: "دستگاه های فعال", icon: "fi fi-rr-wifi-1", to: "/admin/setting-profile/sessions", permission: null },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "خروج از حساب",
|
||||
icon: "fi fi-rr-sign-out-alt",
|
||||
to: "/admin/auth/logout",
|
||||
permission: null,
|
||||
},
|
||||
]);
|
||||
const toggleSubmenu = (item: SidebarItem) => {
|
||||
// expandedKeys.value = {};
|
||||
// item.expanded = !item.expanded;
|
||||
};
|
||||
|
||||
const closeSidebarOnClick = () => {
|
||||
globalStore.sidebarOpen = false;
|
||||
};
|
||||
|
||||
const expandedKeys = ref<Record<string, boolean>>({});
|
||||
|
||||
|
||||
onMounted(() => {
|
||||
globalStore.current_user = currentUser;
|
||||
const saved = localStorage.getItem('expandedKeys')
|
||||
if (saved) expandedKeys.value = JSON.parse(saved)
|
||||
updateExpandedKeys()
|
||||
|
||||
document.addEventListener('click', (e) => {
|
||||
if (e.target.closest('.p-panelmenu-content a')) {
|
||||
globalStore.sidebarOpen = false;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
watch(expandedKeys, v => {
|
||||
localStorage.setItem('expandedKeys', JSON.stringify(v))
|
||||
})
|
||||
watch(() => url.value, () => {
|
||||
updateExpandedKeys()
|
||||
})
|
||||
|
||||
const isActive = (item: SidebarItem): boolean => {
|
||||
return expandedKeys.value[item.key] === true;
|
||||
};
|
||||
|
||||
const updateExpandedKeys = () => {
|
||||
const newKeys = {}
|
||||
const currentPath = url.value.split('?')[0];
|
||||
|
||||
items.value.forEach(item => {
|
||||
if (item.to === currentPath || item.items?.some(c => {
|
||||
const itemPath = c.to || '';
|
||||
return currentPath.startsWith(itemPath) && itemPath !== '';
|
||||
})) {
|
||||
newKeys[item.key] = true
|
||||
}
|
||||
})
|
||||
expandedKeys.value = newKeys
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="globalStore.sidebarOpen"
|
||||
class="fixed inset-0 bg-black/10 backdrop-blur-sm bg-opacity-50 z-10 sm:hidden"
|
||||
@click="globalStore.sidebarOpen = false">
|
||||
</div>
|
||||
<aside class="!bg-white shadow-all shadow-client-gray/5 w-[16rem]
|
||||
py-4 z-10 pb-8 fixed sm:relative inset-y-0 right-0 sm:inset-auto transition-transform duration-300 z-20"
|
||||
:class="[globalStore.sidebarOpen ? 'translate-x-0' : 'translate-x-full sm:translate-x-0']">
|
||||
<section class="sticky top-10 right-0 ">
|
||||
<div class="grid grid-cols-a border-b-[1px] border-client-gray/5 pb-6 justify-center gap-2 items-center">
|
||||
<figure class="grid grid-cols-a justify-center">
|
||||
<Avatar v-if="globalStore.current_user?.profile_url" :image="globalStore.current_user?.profile_url" size="xlarge" shape="circle" />
|
||||
<Avatar v-else image="/images/profile_default.png" size="xlarge" shape="circle" />
|
||||
</figure>
|
||||
<div class="text-xl grid grid-cols-a text-center text-client-Fontcolor font-semibold">
|
||||
<span class="text-lg font-extrabold mt-2">{{ (globalStore.current_user.first_name ?? '' ) + ' ' + (globalStore.current_user.last_name ?? '')}} </span>
|
||||
<span class="text-xs mt-1">{{ globalStore.current_user.email }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overflow-y-auto h-full">
|
||||
<PanelMenu
|
||||
:pt="{
|
||||
header: 'custom-header',
|
||||
headerAction: 'custom-header-action',
|
||||
menuContent: 'custom-menu-content',
|
||||
menuitem: 'custom-menuitem',
|
||||
action: 'custom-action',
|
||||
icon: 'custom-icon',
|
||||
submenuIcon: 'custom-submenu-icon !text-xl',
|
||||
}"
|
||||
v-model:expanded-keys="expandedKeys"
|
||||
:model="filteredItems"
|
||||
class="custom-menu px-4">
|
||||
<template #item="{ item, root, hasSubmenu, toggle }">
|
||||
<div
|
||||
:class="(url.split('?')[0]) === item.to ? 'bg-client-primary !text-white font-bold' : 'text-client-Fontcolor'"
|
||||
class="flex items-center h-10 justify-between pl-2 text-client-Fontcolor rounded-lg cursor-pointer w-full"
|
||||
@click="hasSubmenu ? toggleSubmenu(item) : null">
|
||||
<div class="px-2 flex w-full items-center">
|
||||
<Link v-if="item.to" :href="item.to" class="flex items-center h-10 w-full" @click="globalStore.sidebarOpen = false">
|
||||
<i v-if="item.icon" :class="item.icon" class="flex !text-[1.2rem] -mt-0.5"></i>
|
||||
<div class="flex items-center font-normal text-sm p-2 gap-2 w-full">
|
||||
{{ item.label }}
|
||||
</div>
|
||||
</Link>
|
||||
<div v-else class="flex items-center h-10 w-full">
|
||||
<i v-if="item.icon" :class="item.icon" class="flex !text-[1.2rem] -mt-0.5"></i>
|
||||
<span class="w-full p-2 text-sm text-client-Fontcolor">{{ item.label }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<i v-if="hasSubmenu"
|
||||
class="fi fi-rr-angle-small-left !text-sm flex transition-transform duration-300"
|
||||
:class="[{ 'rotate-90': item.expanded || isActive }]">
|
||||
</i>
|
||||
</div>
|
||||
</template>
|
||||
</PanelMenu>
|
||||
</div>
|
||||
</section>
|
||||
</aside>
|
||||
</template>
|
||||
Reference in New Issue
Block a user