chore: commit pending admin-panel, api auth and parity doc changes
Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Haiku 5.5
parent
55856cac89
commit
cf014e1f6c
@@ -17,11 +17,18 @@
|
||||
class="vertical-nav-menu"
|
||||
theme="light"
|
||||
>
|
||||
<div class="nav-header">
|
||||
<span v-if="!collapsed" class="nav-title">{{ title }}</span>
|
||||
<div class="nav-header" :class="{ 'is-collapsed': collapsed }">
|
||||
<span class="nav-logo">
|
||||
<img src="../../assets/images/logo/montzar-icon.png" alt="" />
|
||||
</span>
|
||||
<span v-if="!collapsed" class="nav-brand">
|
||||
<span class="nav-title">{{ title }}</span>
|
||||
<span class="nav-subtitle">پنل مدیریت</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<a-menu
|
||||
class="nav-menu"
|
||||
mode="inline"
|
||||
theme="light"
|
||||
:inline-collapsed="collapsed"
|
||||
@@ -78,6 +85,7 @@ const users = useUsersStore();
|
||||
* Preserved deliberately — see docs/ADMIN-PORT-PLAN.md.
|
||||
*/
|
||||
function canSee(node: NavMenuNodeData): boolean {
|
||||
if (node.superAdminOnly && !users.isSuperAdmin) return false;
|
||||
if (!node.permissionId) return true;
|
||||
return Boolean(users.hasPermission(node.permissionId));
|
||||
}
|
||||
@@ -176,17 +184,246 @@ function onClick({ key }: { key: string | number }) {
|
||||
<style scoped>
|
||||
.vertical-nav-menu {
|
||||
height: 100vh;
|
||||
overflow-y: auto; /* pinned in place; its own menu scrolls if it's taller than the viewport */
|
||||
border-left: 1px solid #f0f0f0;
|
||||
border-left: 1px solid #eef0f5;
|
||||
box-shadow: -4px 0 24px -16px rgba(16, 24, 40, 0.12);
|
||||
}
|
||||
.vertical-nav-menu :deep(.ant-layout-sider-children) {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
.nav-header {
|
||||
height: 61px; /* legacy ara/ant.less @layout-header-height */
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
padding: 0 20px;
|
||||
border-bottom: 1px solid #eef0f5;
|
||||
}
|
||||
.nav-header.is-collapsed {
|
||||
justify-content: center;
|
||||
padding: 0;
|
||||
}
|
||||
.nav-logo {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
flex-shrink: 0;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
border-radius: 11px;
|
||||
background: #fff;
|
||||
border: 1px solid #eef0f5;
|
||||
box-shadow: 0 4px 12px -6px rgba(28, 45, 86, 0.35);
|
||||
}
|
||||
.nav-logo img {
|
||||
width: 64%;
|
||||
}
|
||||
.nav-brand {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-width: 0;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.nav-title {
|
||||
font-size: 18px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #1c2d56;
|
||||
}
|
||||
.nav-subtitle {
|
||||
font-size: 11px;
|
||||
color: #8a94a6;
|
||||
}
|
||||
/* pinned in place; only the menu scrolls if it's taller than the viewport */
|
||||
.nav-menu {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding: 12px 0 24px;
|
||||
scrollbar-width: thin;
|
||||
scrollbar-color: #e3e7ef transparent;
|
||||
}
|
||||
.nav-menu::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
.nav-menu::-webkit-scrollbar-thumb {
|
||||
border-radius: 6px;
|
||||
background: #e3e7ef;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!--
|
||||
Unscoped: the mobile drawer teleports outside #app and ant's collapsed popups
|
||||
teleport to <body>. :is(#app, ...) also out-ranks utilities.less's
|
||||
`body #app .ant-menu-item-selected`.
|
||||
-->
|
||||
<style>
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .nav-menu.ant-menu {
|
||||
border-inline-end: none !important;
|
||||
background: transparent;
|
||||
font-size: 13.5px;
|
||||
}
|
||||
|
||||
/* section titles */
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item-group-title {
|
||||
padding: 18px 24px 6px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.3px;
|
||||
color: #a0a8b8;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-inline-collapsed .ant-menu-item-group-title {
|
||||
padding: 12px 0 4px;
|
||||
text-align: center;
|
||||
font-size: 0;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-inline-collapsed .ant-menu-item-group-title::after {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 18px;
|
||||
height: 2px;
|
||||
border-radius: 2px;
|
||||
background: #e3e7ef;
|
||||
}
|
||||
|
||||
/* items + submenu titles */
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-inline .ant-menu-item,
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-inline .ant-menu-submenu-title {
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
margin: 2px 12px;
|
||||
width: calc(100% - 24px);
|
||||
border-radius: 10px;
|
||||
color: #475467;
|
||||
transition: background 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item .ant-menu-item-icon,
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-submenu-title .ant-menu-item-icon {
|
||||
font-size: 16px;
|
||||
color: #98a2b3;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item:not(.ant-menu-item-selected):hover,
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-submenu-title:hover {
|
||||
background: #f5f7fb !important;
|
||||
color: #1c2d56 !important;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item:hover .ant-menu-item-icon,
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-submenu-title:hover .ant-menu-item-icon {
|
||||
color: #1c2d56;
|
||||
}
|
||||
|
||||
/* active item */
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item-selected {
|
||||
position: relative;
|
||||
background: rgba(28, 45, 86, 0.08) !important;
|
||||
color: #1c2d56 !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-item-selected .ant-menu-item-icon {
|
||||
color: #1c2d56;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-inline .ant-menu-item-selected::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: auto;
|
||||
top: 10px;
|
||||
bottom: 10px;
|
||||
width: 3px;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
background: #1c2d56;
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-submenu-selected > .ant-menu-submenu-title,
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-submenu-selected > .ant-menu-submenu-title .ant-menu-item-icon {
|
||||
color: #1c2d56;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* nested lists: no grey slab, a soft guide line instead */
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-sub.ant-menu-inline {
|
||||
position: relative;
|
||||
background: transparent !important;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-sub.ant-menu-inline::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset-inline-start: 32px;
|
||||
top: 4px;
|
||||
bottom: 4px;
|
||||
width: 1px;
|
||||
background: #e8ebf2;
|
||||
}
|
||||
:is(#app, .mobile-nav-drawer) .vertical-nav-menu .ant-menu-sub .ant-menu-item {
|
||||
height: 38px;
|
||||
line-height: 38px;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
/* collapsed rail: submenus open as popups teleported to <body> */
|
||||
.nav-popup.ant-menu-submenu-popup > .ant-menu {
|
||||
padding: 6px;
|
||||
border-radius: 14px;
|
||||
background: #fff;
|
||||
border: 1px solid #eef0f5;
|
||||
box-shadow: 0 12px 32px -12px rgba(16, 24, 40, 0.25);
|
||||
}
|
||||
.nav-popup .ant-menu-item,
|
||||
.nav-popup .ant-menu-submenu-title {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
margin: 2px 0;
|
||||
width: 100%;
|
||||
border-radius: 10px;
|
||||
color: #475467;
|
||||
font-size: 13px;
|
||||
transition: background 0.2s ease, color 0.2s ease;
|
||||
}
|
||||
.nav-popup .ant-menu-item .ant-menu-item-icon,
|
||||
.nav-popup .ant-menu-submenu-title .ant-menu-item-icon {
|
||||
color: #98a2b3;
|
||||
}
|
||||
.nav-popup .ant-menu-item:not(.ant-menu-item-selected):hover,
|
||||
.nav-popup .ant-menu-submenu-title:hover {
|
||||
background: #f5f7fb !important;
|
||||
color: #1c2d56 !important;
|
||||
}
|
||||
.nav-popup .ant-menu-item-selected {
|
||||
position: relative;
|
||||
background: rgba(28, 45, 86, 0.08) !important;
|
||||
color: #1c2d56 !important;
|
||||
font-weight: 500;
|
||||
}
|
||||
.nav-popup .ant-menu-item-selected .ant-menu-item-icon {
|
||||
color: #1c2d56;
|
||||
}
|
||||
.nav-popup .ant-menu-item-selected::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
inset-inline-start: 0;
|
||||
inset-inline-end: auto;
|
||||
top: 10px;
|
||||
bottom: 10px;
|
||||
width: 3px;
|
||||
border: none;
|
||||
border-radius: 3px;
|
||||
background: #1c2d56;
|
||||
opacity: 1;
|
||||
transform: none;
|
||||
}
|
||||
.nav-popup .ant-menu-submenu-selected > .ant-menu-submenu-title {
|
||||
color: #1c2d56;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/* collapsed rail: the icon of the group holding the active page */
|
||||
#app .vertical-nav-menu .ant-menu-inline-collapsed .ant-menu-submenu-selected > .ant-menu-submenu-title,
|
||||
#app .vertical-nav-menu .ant-menu-inline-collapsed > .ant-menu-item-selected {
|
||||
background: rgba(28, 45, 86, 0.08) !important;
|
||||
color: #1c2d56 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user