<div id="mediq-dashboard" dir="rtl">
<style>
#mediq-dashboard .mq-list-controls{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin:14px 0;font-size:12px}
#mediq-dashboard .mq-list-controls select{border:1px solid #cce2f0;border-radius:8px;padding:7px 12px;background:white;color:#315873}
#mediq-dashboard .mq-assets-btn:disabled{opacity:.4;cursor:default}
#mediq-dashboard .mq-jcalendar{padding:12px;border:1px solid #cce2f0;border-radius:10px;background:#fff;margin-top:7px;max-width:340px}
#mediq-dashboard .mq-jcalendar[hidden]{display:none!important}
#mediq-dashboard .mq-jcal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:4px;text-align:center;margin:10px 0}
#mediq-dashboard .mq-jcal-head{display:flex;justify-content:space-between;align-items:center;gap:8px}
#mediq-dashboard .mq-jcalendar button{border:1px solid #d5e7f2;border-radius:6px;padding:5px;background:#f1f8fd;color:#315873;cursor:pointer;font:inherit}
#mediq-dashboard .mq-jcalendar button:hover{background:#e0f0fa}
/* ============================================================
MEDIQ DASHBOARD - SUPPLY
PRESENTATION VERSION
============================================================ */
#mediq-dashboard,
#mediq-dashboard * {
box-sizing: border-box;
}
#mediq-dashboard {
--navy: #20577b;
--navy-dark: #174565;
--primary: #3997c8;
--primary-dark: #277eaf;
--text: #24475f;
--muted: #7c99ae;
--border: #d5e7f2;
--bg: #f1f7fc;
--white: #ffffff;
position: fixed;
inset: 0;
width: 100vw;
height: 100vh;
z-index: 9999;
overflow: hidden;
direction: rtl;
font-family:
Tahoma,
Arial,
sans-serif;
color: var(--text);
background:
radial-gradient(
circle at 12% 4%,
rgba(57,151,200,.09),
transparent 27%
),
#f1f7fc;
}
/* ============================================================
HIDE CONFLUENCE
============================================================ */
html,
body,
#page,
#full-height-container,
#main,
#content,
#main-content,
.aui-page-panel,
.aui-page-panel-inner,
.aui-page-panel-content,
.content-body {
width: 100% !important;
height: 100% !important;
max-width: none !important;
margin: 0 !important;
padding: 0 !important;
}
html,
body {
overflow: hidden !important;
}
#footer,
footer,
.aui-footer,
#header,
#main-header,
.breadcrumbs,
#breadcrumbs,
.page-metadata {
display: none !important;
}
/* ============================================================
APP
============================================================ */
.mq-app {
width: 100%;
height: 100%;
display: grid;
grid-template-columns:
minmax(0,1fr)
255px;
direction: ltr;
}
/* ============================================================
SIDEBAR - LEAD GRAY THEME
============================================================ */
.mq-sidebar {
grid-column: 2;
height: 100vh;
padding:
24px
17px;
direction: rtl;
color: #fff;
display: flex;
flex-direction: column;
background:
linear-gradient(
180deg,
#4b9dca 0%,
#337fae 45%,
#23658f 100%
);
box-shadow:
-12px 0 38px
rgba(43,49,56,.18);
border-left:
1px solid
rgba(255,255,255,.04);
}
/* LOGO */
.mq-logo {
width: 100%;
text-align: center;
padding:
3px
5px
22px;
border-bottom:
1px solid
rgba(255,255,255,.08);
}
.mq-logo img {
width: 174px;
max-width: 92%;
height: auto;
filter:
drop-shadow(0 2px 10px rgba(0,0,0,.08));
}
/* USER */
.mq-user {
margin-top: 17px;
padding:
14px
15px;
border-radius: 14px;
background:
rgba(255,255,255,.06);
border:
1px solid
rgba(255,255,255,.08);
box-shadow:
inset 0 1px 0 rgba(255,255,255,.04);
}
.mq-user-name {
font-size: 12px;
font-weight: 900;
color: #ffffff;
}
.mq-user-role {
margin-top: 6px;
color:
rgba(255,255,255,.64);
font-size: 9px;
font-weight: 600;
}
/* ============================================================
LIFE CYCLE
============================================================ */
.mq-life-title {
margin:
26px
7px
9px;
color:
rgba(255,255,255,.42);
font-size: 9px;
font-weight: 700;
letter-spacing: .2px;
}
.mq-life {
display: flex;
flex-direction: column;
gap: 7px;
}
.mq-life-item {
position: relative;
min-height: 46px;
padding:
0
13px;
border-radius: 12px;
display: flex;
align-items: center;
gap: 10px;
color:
rgba(255,255,255,.76);
font-size: 11px;
font-weight: 800;
cursor: pointer;
user-select: none;
border:
1px solid
transparent;
transition:
background .18s ease,
color .18s ease,
transform .18s ease,
border-color .18s ease,
box-shadow .18s ease;
}
.mq-life-item:hover {
color: #fff;
background:
rgba(255,255,255,.08);
border-color:
rgba(255,255,255,.07);
}
.mq-life-item.active {
color: #ffffff;
background:
linear-gradient(
90deg,
#3997c8 0%,
#2e85b5 100%
);
border-color:
rgba(255,255,255,.10);
box-shadow:
0 12px 24px rgba(35,40,46,.24);
}
.mq-life-item.active::before {
content: "";
position: absolute;
right: 10px;
top: 50%;
width: 6px;
height: 6px;
border-radius: 50%;
background: #ffffff;
transform: translateY(-50%);
box-shadow:
0 0 0 4px rgba(255,255,255,.10);
}
.mq-life-icon {
width: 28px;
height: 28px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
background:
rgba(255,255,255,.06);
border:
1px solid
rgba(255,255,255,.05);
}
.mq-life-item.active .mq-life-icon {
background:
rgba(255,255,255,.14);
border-color:
rgba(255,255,255,.10);
}
.mq-life-icon svg {
width: 16px;
height: 16px;
fill: none;
stroke: currentColor;
stroke-width: 1.9;
stroke-linecap: round;
stroke-linejoin: round;
}
/* ============================================================
LOGOUT
============================================================ */
.mq-sidebar-bottom {
margin-top: auto;
padding-top: 14px;
border-top:
1px solid
rgba(255,255,255,.07);
}
.mq-logout {
min-height: 43px;
padding:
0
13px;
border-radius: 11px;
display: flex;
align-items: center;
gap: 9px;
color:
rgba(255,255,255,.72);
font-size: 10px;
font-weight: 700;
cursor: pointer;
border:
1px solid
transparent;
transition:
background .18s ease,
color .18s ease,
border-color .18s ease;
}
.mq-logout:hover {
color: #fff;
background:
rgba(255,255,255,.07);
border-color:
rgba(255,255,255,.07);
}
/* ============================================================
MAIN
============================================================ */
.mq-main {
grid-column: 1;
height: 100vh;
direction: rtl;
overflow-y: auto;
padding:
0
clamp(25px,4vw,55px)
45px;
}
/* ============================================================
HEADER
============================================================ */
.mq-header {
min-height: 88px;
border-bottom:
1px solid
var(--border);
display: flex;
align-items: center;
justify-content: space-between;
gap: 20px;
}
.mq-header-right {
min-width: 0;
}
.mq-page-title {
color:
var(--navy);
font-size: 20px;
font-weight: 900;
}
.mq-page-description {
margin-top: 6px;
color:
var(--muted);
font-size: 10px;
font-weight: 600;
}
/* CENTER */
.mq-center {
padding:
10px
14px;
border:
1px solid
var(--border);
border-radius: 11px;
background: #fff;
color:
#536f84;
font-size: 10px;
font-weight: 700;
}
/* ============================================================
BREADCRUMB
============================================================ */
.mq-breadcrumb {
min-height: 54px;
display: flex;
align-items: center;
gap: 7px;
flex-wrap: wrap;
}
.mq-bread-item {
color:
#8197a8;
font-size: 10px;
font-weight: 700;
}
.mq-bread-current {
color:
var(--primary-dark);
font-weight: 900;
}
.mq-bread-separator {
color:
#b6c4cf;
}
/* ============================================================
HERO
============================================================ */
.mq-hero {
position: relative;
overflow: hidden;
min-height: 112px;
padding:
21px
24px;
border-radius: 18px;
color: #fff;
display: flex;
align-items: center;
justify-content: space-between;
background:
linear-gradient(
105deg,
#24475f,
#277eaf
);
box-shadow:
0 15px 35px
rgba(7,53,83,.10);
}
.mq-hero::before {
content: "";
position: absolute;
width: 250px;
height: 250px;
left: -70px;
top: -150px;
border-radius: 50%;
background:
rgba(107,119,131,.14);
}
.mq-hero-title {
position: relative;
z-index: 2;
font-size: 16px;
font-weight: 900;
}
.mq-hero-desc {
position: relative;
z-index: 2;
margin-top: 6px;
color:
rgba(255,255,255,.70);
font-size: 10px;
}
.mq-back-btn {
position: relative;
z-index: 2;
display: none;
min-width: 88px;
height: 36px;
padding:
0
13px;
border:
1px solid
rgba(255,255,255,.25);
border-radius: 10px;
background:
rgba(255,255,255,.10);
color: #fff;
font-family:
inherit;
font-size: 10px;
font-weight: 800;
cursor: pointer;
}
.mq-back-btn:hover {
background:
rgba(255,255,255,.16);
}
/* ============================================================
CONTENT
============================================================ */
.mq-view {
margin-top: 23px;
animation:
mqFade
.22s ease;
}
@keyframes mqFade {
from {
opacity: 0;
transform: translateY(5px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
/* ============================================================
SECTION HEADER
============================================================ */
.mq-section-head {
margin-bottom: 14px;
display: flex;
align-items: center;
justify-content: space-between;
}
.mq-section-title {
color:
var(--navy);
font-size: 14px;
font-weight: 900;
}
.mq-section-desc {
margin-top: 4px;
color:
var(--muted);
font-size: 9px;
}
/* ============================================================
MODULE CARDS
============================================================ */
.mq-card-grid {
display: grid;
grid-template-columns:
repeat(4,minmax(0,1fr));
gap: 14px;
}
.mq-module-card {
position: relative;
min-height: 176px;
padding:
18px;
border:
1px solid
var(--border);
border-radius: 17px;
background: #fff;
cursor: pointer;
box-shadow:
0 9px 26px
rgba(19,65,90,.035);
transition:
transform .17s ease,
box-shadow .17s ease,
border-color .17s ease;
}
.mq-module-card:hover {
transform:
translateY(-4px);
border-color:
rgba(87,96,106,.45);
box-shadow:
0 18px 40px
rgba(19,65,90,.08);
}
.mq-module-icon {
width: 48px;
height: 48px;
margin-bottom: 17px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
color:
var(--primary-dark);
background:
linear-gradient(
145deg,
#eaf4fb,
#e0f0fa
);
}
.mq-module-icon svg {
width: 24px;
height: 24px;
fill: none;
stroke: currentColor;
stroke-width: 1.8;
stroke-linecap: round;
stroke-linejoin: round;
}
.mq-module-name {
color:
var(--navy);
font-size: 12px;
font-weight: 900;
line-height: 1.8;
}
.mq-module-arrow {
position: absolute;
left: 18px;
bottom: 17px;
width: 29px;
height: 29px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color:
#8ea5b5;
background:
#f3f7f9;
font-size: 18px;
}
.mq-module-card:hover
.mq-module-arrow {
color: #fff;
background:
var(--primary);
}
/* ============================================================
LARGE ACTION CARDS
============================================================ */
.mq-action-grid {
display: grid;
grid-template-columns:
repeat(2,minmax(0,1fr));
gap: 15px;
}
.mq-action-card {
min-height: 155px;
padding:
19px;
border:
1px solid
var(--border);
border-radius: 17px;
background: #fff;
cursor: pointer;
display: flex;
align-items: center;
gap: 16px;
transition: .17s;
}
.mq-action-card:hover {
border-color:
rgba(87,96,106,.45);
transform:
translateY(-2px);
box-shadow:
0 15px 35px
rgba(24,74,98,.06);
}
.mq-action-icon {
flex: 0 0 auto;
width: 54px;
height: 54px;
border-radius: 15px;
display: flex;
align-items: center;
justify-content: center;
color:
var(--primary-dark);
background:
#f0f7fc;
}
.mq-action-icon svg {
width: 25px;
height: 25px;
fill: none;
stroke: currentColor;
stroke-width: 1.8;
stroke-linecap: round;
stroke-linejoin: round;
}
.mq-action-title {
color:
var(--navy);
font-size: 13px;
font-weight: 900;
}
.mq-action-sub {
margin-top: 6px;
color:
var(--muted);
font-size: 9px;
}
/* ============================================================
ASSET LIST MENU
============================================================ */
.mq-list-layout {
display: grid;
grid-template-columns:
330px
minmax(0,1fr);
gap: 16px;
direction: ltr;
}
.mq-list-menu,
.mq-preview {
direction: rtl;
border:
1px solid
var(--border);
border-radius: 18px;
background: #fff;
box-shadow:
0 10px 28px
rgba(19,65,90,.035);
}
.mq-list-menu {
padding: 13px;
}
.mq-list-option {
min-height: 52px;
margin-bottom: 5px;
padding:
0
13px;
border-radius: 10px;
display: flex;
align-items: center;
justify-content: space-between;
color:
#536f84;
font-size: 10px;
font-weight: 800;
cursor: pointer;
transition: .15s;
}
.mq-list-option:hover {
color:
var(--primary-dark);
background:
#f3f9fd;
}
.mq-list-option.active {
color:
#2b5672;
background:
#eaf4fc;
}
.mq-option-badge {
width: 26px;
height: 26px;
border-radius: 7px;
display: flex;
align-items: center;
justify-content: center;
background:
rgba(87,96,106,.09);
color:
var(--primary-dark);
}
/* ============================================================
PREVIEW
============================================================ */
.mq-preview {
min-height: 390px;
padding:
23px;
}
.mq-preview-title {
color:
var(--navy);
font-size: 14px;
font-weight: 900;
}
.mq-preview-description {
margin-top: 7px;
color:
var(--muted);
font-size: 9px;
}
/* MOCK CONTENT */
.mq-demo-box {
margin-top: 23px;
padding: 20px;
border:
1px dashed
#bdd4df;
border-radius: 14px;
background:
#f8fbfc;
}
.mq-demo-icon {
width: 48px;
height: 48px;
margin:
0
auto
12px;
border-radius: 14px;
display: flex;
align-items: center;
justify-content: center;
color:
var(--primary-dark);
background:
#eaf4fc;
}
.mq-demo-text {
color:
#4d84a8;
text-align: center;
font-size: 10px;
line-height: 2;
}
.mq-demo-button {
display: block;
min-width: 125px;
height: 38px;
margin:
17px
auto
0;
border: 0;
border-radius: 9px;
background:
linear-gradient(
90deg,
#409fd1,
#2c88bb
);
color: #fff;
font-family: inherit;
font-size: 10px;
font-weight: 800;
cursor: pointer;
}
/* ============================================================
PLACEHOLDER LIFE CYCLE
============================================================ */
.mq-empty-cycle {
min-height: 350px;
border:
1px dashed
#c7dce5;
border-radius: 18px;
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
background:
rgba(255,255,255,.65);
color:
#7890a2;
}
.mq-empty-cycle strong {
color:
var(--navy);
font-size: 15px;
}
.mq-empty-cycle span {
margin-top: 8px;
font-size: 10px;
}
/* ============================================================
TOAST
============================================================ */
.mq-toast {
position: fixed;
left: 30px;
bottom: 27px;
z-index: 10020;
min-width: 260px;
max-width: 360px;
padding:
13px
16px;
border-radius: 11px;
color: #fff;
background:
#073b5c;
box-shadow:
0 16px 40px
rgba(0,0,0,.15);
font-size: 10px;
font-weight: 700;
opacity: 0;
transform:
translateY(12px);
pointer-events: none;
transition:
.2s;
}
.mq-toast.show {
opacity: 1;
transform:
translateY(0);
}
/* ============================================================
RESPONSIVE
============================================================ */
@media(max-width:1300px) {
.mq-card-grid {
grid-template-columns:
repeat(2,minmax(0,1fr));
}
}
@media(max-width:1000px) {
.mq-app {
grid-template-columns:
minmax(0,1fr)
210px;
}
.mq-list-layout {
grid-template-columns:
280px
minmax(0,1fr);
}
}
@media(max-width:800px) {
.mq-sidebar {
display: none;
}
.mq-app {
display: block;
}
.mq-main {
width: 100%;
}
.mq-card-grid,
.mq-action-grid,
.mq-list-layout {
grid-template-columns:
1fr;
}
}
/* ============================================================
MEDIQ SIDEBAR NAVIGATION TREE
============================================================ */
.mq-life-title,
.mq-life {
display: none !important;
}
.mq-tree-title {
margin: 22px 7px 9px;
color: rgba(255,255,255,.39);
font-size: 9px;
font-weight: 700;
}
.mq-tree {
display: flex;
flex-direction: column;
gap: 5px;
overflow-y: auto;
overflow-x: hidden;
padding-left: 2px;
scrollbar-width: thin;
}
.mq-tree::-webkit-scrollbar {
width: 4px;
}
.mq-tree::-webkit-scrollbar-thumb {
background: rgba(255,255,255,.15);
border-radius: 10px;
}
.mq-tree-row {
min-height: 38px;
padding: 0 10px;
border-radius: 9px;
display: flex;
align-items: center;
gap: 8px;
color: rgba(255,255,255,.70);
font-size: 10px;
font-weight: 800;
cursor: pointer;
user-select: none;
transition: background .15s ease, color .15s ease;
}
.mq-tree-row:hover {
color: #fff;
background: rgba(255,255,255,.07);
}
.mq-tree-row.active {
color: #fff;
background: linear-gradient(90deg,#3997c8,#277eaf);
}
.mq-tree-row.parent-active:not(.active) {
color: #fff;
background: rgba(255,255,255,.055);
}
.mq-tree-row.level-1 { padding-right: 10px; }
.mq-tree-row.level-2 { padding-right: 23px; font-size: 9.5px; }
.mq-tree-row.level-3 { padding-right: 36px; font-size: 9px; }
.mq-tree-row.level-4 { padding-right: 49px; font-size: 8.7px; color: rgba(255,255,255,.60); }
.mq-tree-dot {
width: 6px;
height: 6px;
flex: 0 0 6px;
border-radius: 50%;
background: rgba(255,255,255,.32);
}
.mq-tree-row.active .mq-tree-dot {
background: #fff;
}
.mq-tree-arrow {
margin-right: auto;
color: rgba(255,255,255,.45);
font-size: 13px;
transition: transform .18s ease;
}
.mq-tree-row.open > .mq-tree-arrow {
transform: rotate(90deg);
}
.mq-tree-children {
display: none;
margin-top: 2px;
}
.mq-tree-children.open {
display: block;
}
.mq-tree-separator {
height: 1px;
margin: 8px 9px;
background: rgba(255,255,255,.08);
}
/* ============================================================
MEDIQ UI POLISH - LARGER TYPOGRAPHY + TOP WELCOME
============================================================ */
#mediq-dashboard .mq-user-name { font-size: 15px; }
#mediq-dashboard .mq-user-role { font-size: 12px; }
#mediq-dashboard .mq-tree-title { font-size: 12px; }
#mediq-dashboard .mq-tree-row { font-size: 13px; min-height: 42px; }
#mediq-dashboard .mq-tree-row.level-2 { font-size: 12.5px; }
#mediq-dashboard .mq-tree-row.level-3 { font-size: 12px; }
#mediq-dashboard .mq-tree-row.level-4 { font-size: 11.7px; }
#mediq-dashboard .mq-logout { font-size: 13px; }
#mediq-dashboard .mq-page-title { font-size: 23px; }
#mediq-dashboard .mq-page-description { font-size: 13px; }
#mediq-dashboard .mq-center { font-size: 13px; }
#mediq-dashboard .mq-bread-item { font-size: 13px; }
#mediq-dashboard .mq-hero-title { font-size: 19px; }
#mediq-dashboard .mq-hero-desc { font-size: 13px; }
#mediq-dashboard .mq-back-btn { font-size: 13px; }
#mediq-dashboard .mq-section-title { font-size: 17px; }
#mediq-dashboard .mq-section-desc { font-size: 12px; }
#mediq-dashboard .mq-module-name { font-size: 15px; }
#mediq-dashboard .mq-action-title { font-size: 16px; }
#mediq-dashboard .mq-action-sub { font-size: 12px; }
#mediq-dashboard .mq-list-option { font-size: 13px; }
#mediq-dashboard .mq-preview-title { font-size: 17px; }
#mediq-dashboard .mq-preview-description,
#mediq-dashboard .mq-demo-text { font-size: 12px; }
#mediq-dashboard .mq-demo-button { font-size: 13px; }
#mediq-dashboard .mq-empty-cycle strong { font-size: 18px; }
#mediq-dashboard .mq-empty-cycle span { font-size: 13px; }
#mediq-dashboard .mq-toast { font-size: 13px; }
#mediq-dashboard .mq-header-welcome {
display:flex; align-items:center; gap:9px; padding:9px 14px;
border:1px solid rgba(87,96,106,.20); border-radius:999px;
background:rgba(255,255,255,.82); box-shadow:0 7px 22px rgba(7,53,83,.055);
color:#587287; font-size:13px; font-weight:700; white-space:nowrap;
}
#mediq-dashboard .mq-header-welcome strong { color:var(--navy); font-size:14px; font-weight:900; }
#mediq-dashboard .mq-welcome-dot { width:8px; height:8px; border-radius:50%; background:var(--primary); box-shadow:0 0 0 4px rgba(87,96,106,.10); }
#mediq-dashboard .mq-header-left { display:flex; align-items:center; gap:10px; }
#mediq-dashboard .mq-edit-page-btn{
display:inline-flex;
align-items:center;
justify-content:center;
gap:7px;
min-height:38px;
padding:0 14px;
border:1px solid #cfe1e8;
border-radius:12px;
background:#fff;
color:#34414d !important;
font-family:inherit;
font-size:12px;
font-weight:900;
text-decoration:none !important;
cursor:pointer;
box-shadow:0 6px 18px rgba(3,53,83,.06);
transition:.18s ease;
}
#mediq-dashboard .mq-edit-page-btn:hover{
background:#eaf4fb;
border-color:#b8bec5;
color:#326588 !important;
transform:translateY(-1px);
}
#mediq-dashboard .mq-edit-page-btn svg{
width:15px;
height:15px;
stroke:currentColor;
stroke-width:2;
fill:none;
}
#mediq-dashboard .mq-module-card { box-shadow:0 10px 30px rgba(19,65,90,.05); }
#mediq-dashboard .mq-module-card:hover { transform:translateY(-5px); box-shadow:0 20px 45px rgba(19,65,90,.10); }
#mediq-dashboard .mq-hero { box-shadow:0 18px 42px rgba(7,53,83,.12); }
/* ===== FINAL UI REFINEMENTS ===== */
#mediq-dashboard .mq-header { min-height: 92px; }
#mediq-dashboard .mq-header-left { margin-right:auto; }
#mediq-dashboard .mq-header-welcome { padding:10px 16px; }
#mediq-dashboard .mq-breadcrumb { min-height:46px; }
#mediq-dashboard .mq-hero { margin-top:14px; }
#mediq-dashboard .mq-tree { scrollbar-width:none; -ms-overflow-style:none; }
#mediq-dashboard .mq-tree::-webkit-scrollbar { display:none !important; width:0 !important; }
#mediq-dashboard .mq-sidebar { overflow:hidden; }
#mediq-dashboard .mq-bread-link {
cursor: pointer;
transition: color .15s ease, background .15s ease;
border-radius: 7px;
padding: 4px 6px;
}
#mediq-dashboard .mq-bread-link:hover {
color: var(--primary) !important;
background: rgba(87,96,106,.08);
}
/* MEDIQ - REAL PURCHASED ASSETS LIST (table)
============================================================ */
#mediq-dashboard .mq-assets-head {
margin-top: 18px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
#mediq-dashboard .mq-assets-actions {
display: flex;
gap: 8px;
flex-wrap: wrap;
}
#mediq-dashboard .mq-assets-btn {
min-height: 38px;
padding: 0 15px;
border: 1px solid #d8e7ed;
border-radius: 9px;
background: #fff;
color: #47677d;
font-family: inherit;
font-size: 12px;
font-weight: 800;
cursor: pointer;
}
#mediq-dashboard .mq-assets-btn.primary {
border-color: transparent;
color: #fff;
background: linear-gradient(90deg,#409fd1,#2c88bb);
}
#mediq-dashboard .mq-assets-host {
margin-top: 14px;
min-height: 140px;
}
#mediq-dashboard .mq-assets-host > table,
#mediq-dashboard .mq-assets-host table {
width: 100% !important;
border-collapse: collapse !important;
direction: rtl !important;
background: #fff !important;
border: 1px solid #d7dde2 !important;
border-radius: 12px !important;
overflow: hidden !important;
}
#mediq-dashboard .mq-assets-host th {
padding: 12px 14px !important;
text-align: right !important;
background: #f5f9fd !important;
color: #47677d !important;
border-bottom: 1px solid #d7dde2 !important;
font-size: 12px !important;
font-weight: 900 !important;
}
#mediq-dashboard .mq-assets-host td {
padding: 12px 14px !important;
text-align: right !important;
color: #294e68 !important;
border-bottom: 1px solid #e5f0f9 !important;
font-size: 12px !important;
font-weight: 700 !important;
}
#mediq-dashboard .mq-assets-message {
min-height: 140px;
display: flex;
align-items: center;
justify-content: center;
padding: 22px;
border: 1px dashed #c5dce5;
border-radius: 12px;
background: #f8fbfc;
color: #6f8799;
text-align: center;
font-size: 12px;
font-weight: 700;
}
#mediq-dashboard .mq-cf-delete-proxy {
display: inline-flex !important;
align-items: center;
justify-content: center;
min-width: 58px;
min-height: 30px;
padding: 0 10px !important;
border: 1px solid #f1c9c9 !important;
border-radius: 8px !important;
background: #fff7f7 !important;
color: #b42318 !important;
text-decoration: none !important;
font-family: inherit !important;
font-size: 11px !important;
font-weight: 800 !important;
cursor: pointer !important;
}
#mediq-dashboard .mq-cf-delete-proxy:hover {
background: #ffeded !important;
border-color: #e8aaaa !important;
}
#mediq-dashboard .mq-cf-edit-proxy {
min-width: 50px !important;
height: 28px !important;
padding: 0 11px !important;
margin-left: 6px !important;
border: 1px solid rgba(87,96,106,.30) !important;
border-radius: 8px !important;
background: #f4f4f5 !important;
color: #434a51 !important;
font-family: inherit !important;
font-size: 11px !important;
font-weight: 800 !important;
cursor: pointer !important;
text-decoration: none !important;
}
#mediq-dashboard .mq-cf-edit-proxy:hover {
background: #eaebec !important;
border-color: rgba(87,96,106,.55) !important;
}
/* ============================================================
DEDICATED EDIT ASSET WORKSPACE
============================================================ */
#mediq-dashboard .mq-edit-wrap {
border: 1px solid var(--border);
border-radius: 18px;
background: #fff;
padding: 24px;
box-shadow: 0 10px 28px rgba(19,65,90,.035);
}
#mediq-dashboard .mq-edit-toolbar {
margin-top: 18px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
flex-wrap: wrap;
}
#mediq-dashboard .mq-edit-search {
width: min(390px, 100%);
min-height: 40px;
padding: 0 14px;
border: 1px solid #d8e7ed;
border-radius: 10px;
outline: none;
background: #fff;
color: #294e68;
direction: rtl;
font-family: inherit;
font-size: 12px;
font-weight: 700;
}
#mediq-dashboard .mq-edit-search:focus {
border-color: rgba(87,96,106,.65);
box-shadow: 0 0 0 3px rgba(87,96,106,.08);
}
#mediq-dashboard .mq-edit-help {
color: #71899a;
font-size: 12px;
font-weight: 700;
}
#mediq-dashboard .mq-edit-host {
margin-top: 14px;
}
#mediq-dashboard .mq-edit-host table {
width: 100% !important;
border-collapse: collapse !important;
direction: rtl !important;
background: #fff !important;
border: 1px solid #d7dde2 !important;
}
#mediq-dashboard .mq-edit-host th {
padding: 12px 14px !important;
text-align: right !important;
background: #f5f9fd !important;
color: #47677d !important;
border-bottom: 1px solid #d7dde2 !important;
font-size: 12px !important;
font-weight: 900 !important;
}
#mediq-dashboard .mq-edit-host td {
padding: 12px 14px !important;
text-align: right !important;
color: #294e68 !important;
border-bottom: 1px solid #e5f0f9 !important;
font-size: 12px !important;
font-weight: 700 !important;
}
#mediq-dashboard{
--navy:#347da8 !important;
--navy-dark:#215b83 !important;
--primary:#3997c8 !important;
--primary-dark:#277eaf !important;
--text:#315873 !important;
--muted:#7e9bae !important;
--border:#d5e7f2 !important;
--bg:#f1f7fc !important;
}
#mediq-dashboard{background:#f1f7fc !important;}
#mediq-dashboard .mq-sidebar{
background:linear-gradient(180deg,#58a4cf 0%,#3d89b7 52%,#23658f 100%) !important;
box-shadow:-12px 0 42px rgba(27,32,42,.18) !important;
}
#mediq-dashboard .mq-life-item.active{
background:linear-gradient(90deg,#409fd1,#2c88bb) !important;
box-shadow:0 10px 24px rgba(39,126,175,.22) !important;
}
#mediq-dashboard .mq-hero{
background:linear-gradient(105deg,#388cbc 0%,#64b2db 62%,#3997c8 135%) !important;
box-shadow:0 16px 40px rgba(38,44,58,.14) !important;
}
#mediq-dashboard .mq-hero::before{background:rgba(169,218,246,.13) !important;}
#mediq-dashboard .mq-welcome-dot{background:#3997c8 !important;box-shadow:0 0 0 4px rgba(64,159,209,.12) !important;}
#mediq-dashboard .mq-action-card:hover,
#mediq-dashboard .mq-card:hover{
border-color:#a5d1eb !important;
box-shadow:0 16px 34px rgba(39,126,175,.09) !important;
}
#mediq-dashboard .mq-edit-page-btn:hover{
border-color:#a5d1eb !important;
color:#277eaf !important;
}
/* ===== MediQ code-only wizard (standalone) ===== */
#mqWz,#mqDetail{position:fixed;inset:0;z-index:11000;display:none;align-items:center;justify-content:center;padding:18px;background:rgba(28,33,43,.58);backdrop-filter:blur(4px);direction:rtl}
#mqWz.open,#mqDetail.open{display:flex}
#mqWz *,#mqDetail *{box-sizing:border-box;font-family:Tahoma,Arial,sans-serif}
.wz-dialog{width:min(820px,94vw);max-height:90vh;display:flex;flex-direction:column;background:#fff;border:1px solid #d5e7f2;border-radius:20px;box-shadow:0 28px 90px rgba(22,27,38,.34);overflow:hidden;color:#24475f}
.wz-head{padding:18px 22px 14px;border-bottom:1px solid #e5e7ef;flex:0 0 auto}
.wz-head-top{display:flex;align-items:center;justify-content:space-between;gap:14px}
.wz-title{font-size:18px;font-weight:900;color:#204969}
.wz-close{width:36px;height:36px;border:0;border-radius:10px;background:#f2f4f8;color:#6d91ab;font:700 21px/36px Tahoma;cursor:pointer}
.wz-close:hover{background:#e5f0f9;color:#277eaf}
.wz-steps{margin-top:14px;display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:8px}
.wz-step{min-height:40px;padding:7px 9px;display:flex;align-items:center;justify-content:center;gap:7px;border:1px solid #e2e6ee;border-radius:10px;background:#f5f9fd;color:#91aabd;font-size:11px;font-weight:800}
.wz-step b{width:22px;height:22px;display:inline-flex;align-items:center;justify-content:center;border-radius:50%;background:#e3eff8;color:#6d91ab;font-size:10px}
.wz-step.active{border-color:#3997c8;background:#3997c8;color:#fff}
.wz-step.active span{color:#fff}
.wz-step.active b{background:#3997c8;color:#fff}
.wz-step.done{background:#edf6fc;color:#4f86aa}
.wz-body{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;padding:20px 22px 14px}
.wz-label{margin:0 2px 8px;font-size:12px;font-weight:900;color:#355e79}
.wz-selected{margin:0 0 10px;padding:9px 12px;border:1px dashed #cce2f0;border-radius:10px;background:#f5f9fd;color:#819eaf;font-size:12px;font-weight:800}
.wz-selected.has{border-style:solid;color:#2b5672;background:#e7f2fb}
.wz-picker{border:1px solid #cce2f0;border-radius:12px;overflow:hidden;background:#fff}
.wz-search{display:block;width:100%;height:42px;padding:0 13px;border:0;border-bottom:1px solid #e4e7e9;background:#f1f8fd;font-size:12px;color:#2b5672;outline:none;direction:rtl}
.wz-list{max-height:230px;overflow-y:auto;padding:6px}
.wz-item{display:block;width:100%;min-height:38px;padding:8px 11px;border:0;border-radius:8px;background:#fff;color:#315873;text-align:right;font-size:12px;font-weight:700;cursor:pointer}
.wz-item:hover{background:#e5f0f9}
.wz-item.sel{background:#3997c8;color:#fff}
.wz-empty,.wz-loading{padding:18px 12px;color:#7e9bae;text-align:center;font-size:12px;font-weight:700}
.wz-link{margin-top:12px;min-height:38px;padding:0 14px;border:1px solid #cce2f0;border-radius:10px;background:#fff;color:#277eaf;font-size:12px;font-weight:900;cursor:pointer}
.wz-link:hover{background:#e9f4fc}
.wz-create{margin-top:14px;padding:14px;border:1px solid #d5e7f2;border-radius:14px;background:#f5f9fd}
.wz-create[hidden]{display:none}
.wz-create>strong{display:block;margin-bottom:12px;font-size:13px;color:#2b506b}
.wz-grid{display:grid;grid-template-columns:1fr 1fr;gap:0 12px}
.wz-field{margin:0 0 12px;min-width:0}
.wz-field label{display:block;margin:0 0 6px;font-size:12px;font-weight:800;color:#2b506b}
.wz-field input,.wz-field select{display:block;width:100%;min-height:42px;padding:0 12px;border:1px solid #d2e5f1;border-radius:11px;background:#fff;color:#24475f;font-size:12px;direction:rtl;outline:none}
.wz-field input:focus,.wz-field select:focus{border-color:#409fd1;box-shadow:0 0 0 3px rgba(64,159,209,.12)}
.wz-inline{display:flex;gap:8px;align-items:center}
.wz-inline select{flex:1 1 auto}
.wz-plus{flex:0 0 42px;width:42px;height:42px;border:1px solid #b3d5e9;border-radius:11px;background:#eaf4fb;color:#326588;font:900 22px/40px Tahoma;cursor:pointer}
.wz-plus:hover{background:#3997c8;border-color:#3997c8;color:#fff}
.wz-mini{display:flex;gap:8px;margin:0 0 12px}
.wz-mini[hidden]{display:none}
.wz-mini input{flex:1 1 auto;min-height:40px;padding:0 12px;border:1px solid #d2e5f1;border-radius:10px;font-size:12px;direction:rtl}
.wz-static{margin:0 0 14px;padding:10px 12px;border:1px solid #d5e7f2;border-radius:10px;background:#f5f9fd;color:#487391;font-size:12px;font-weight:800}
.wz-msg{min-height:20px;padding:0 22px 6px;font-size:11px;font-weight:800;color:#6d91ab}
.wz-msg.err{color:#a33d3d}
.wz-foot{flex:0 0 auto;display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 22px 16px;border-top:1px solid #e2e6e9;background:#fff}
.wz-foot-r,.wz-foot-l{display:flex;gap:9px}
.wz-btn{min-height:42px;padding:0 20px;border-radius:10px;border:1px solid #d8dde7;background:#fff;color:#487391;font-size:12px;font-weight:900;cursor:pointer}
.wz-btn.primary,.wz-primary{border:1px solid #277eaf;background:linear-gradient(135deg,#3997c8,#277eaf);color:#fff;box-shadow:0 8px 18px rgba(39,126,175,.18);border-radius:10px;min-height:42px;padding:0 18px;font-size:12px;font-weight:900;cursor:pointer}
.wz-btn:disabled,.wz-primary:disabled,.wz-link:disabled{opacity:.55;cursor:not-allowed}
.wz-btn:focus-visible,.wz-primary:focus-visible,.wz-item:focus-visible,.wz-plus:focus-visible,.wz-link:focus-visible{outline:2px solid #409fd1;outline-offset:2px}
#mqDetail .wz-dialog{width:min(620px,94vw)}
.dt-row{display:flex;justify-content:space-between;gap:14px;padding:11px 2px;border-bottom:1px solid #e7f2fb;font-size:12px}
.dt-row span:first-child{color:#7e9bae;font-weight:800}
.dt-row span:last-child{color:#2b5672;font-weight:800;text-align:left}
.mq-tbl{width:100%;border-collapse:collapse;direction:rtl;background:#fff}
.mq-tbl th,.mq-tbl td{padding:12px 14px;text-align:right;font-size:12px;border-bottom:1px solid #e5f0f9;color:#294e68;font-weight:700}
.mq-tbl th{background:#ecf5fc;color:#47677d;font-weight:900}
.mq-tbl-wrap{border:1px solid #d7dde2;border-radius:14px;overflow:auto;background:#fff}
@media(max-width:760px){.wz-steps{grid-template-columns:repeat(2,minmax(0,1fr))}.wz-grid{grid-template-columns:1fr}}
/* MediQ hospital-blue palette. */
#mediq-dashboard .mq-welcome-dot{background:#409fd1!important;box-shadow:0 0 0 4px rgba(64,159,209,.12)!important}
.wz-btn.primary,.wz-primary{background:linear-gradient(135deg,#4ca9d8,#328fc1);border-color:#328fc1;box-shadow:0 8px 18px rgba(64,159,209,.2)}
.wz-step.active{background:#368fbe;border-color:#368fbe;color:white}
.wz-step.active b{background:rgba(255,255,255,.18);color:white}
.wz-step.active span{color:white}
.wz-item.sel{background:#368fbe;color:white}
/* Large minimal duotone illustrations and structured wizard. */
#mediq-dashboard .mq-module-icon{width:110px;height:110px;border-radius:24px;background:#f2f6f8;color:#4e6979;margin-bottom:16px}
#mediq-dashboard .mq-module-icon svg{width:72px;height:72px;stroke-width:1.25}
#mediq-dashboard .mq-action-icon{width:108px;height:108px;border-radius:22px;background:#f2f6f8;color:#4e6979}
#mediq-dashboard .mq-action-icon svg{width:75px;height:75px;stroke-width:1.25}
#mediq-dashboard .mq-module-card{min-height:216px}
#mediq-dashboard .mq-action-card{min-height:148px}
.wz-step{flex-direction:column;gap:4px;min-height:65px}
.wz-step .wz-step-heading{display:flex;align-items:center;justify-content:center;gap:6px}
.wz-step .wz-step-value{display:block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:10px;font-weight:600;color:inherit}
.wz-group-tree,.wz-group-tree ul{list-style:none;margin:0;padding:0 18px 0 0;position:relative}
.wz-group-tree{padding:4px 0}
.wz-group-tree ul{margin-right:15px;border-right:1px solid #bacbd5}
.wz-group-tree li{position:relative;margin:3px 0}
.wz-group-tree ul>li:before{content:"";position:absolute;right:-18px;top:19px;width:18px;border-top:1px solid #bacbd5}
.wz-tree-line{display:flex;align-items:center;gap:4px}
.wz-tree-line .wz-item{width:auto;flex:1;min-width:0;white-space:normal}
.wz-tree-toggle,.wz-tree-spacer{width:26px;flex:0 0 26px;height:30px}
.wz-tree-toggle{border:0;border-radius:6px;background:#edf2f5;color:#435c6d;cursor:pointer;font:700 17px Tahoma}
.wz-tree-toggle:focus-visible{outline:2px solid #69737d}
.wz-segment{padding:14px;margin:0 0 13px;border:1px solid #dce5eb;border-radius:13px;background:#fff;min-inline-size:0}
.wz-segment legend{padding:0 8px;color:#394e5e;font-size:12px;font-weight:900}
.wz-segment .wz-field:last-child{margin-bottom:0}
.wz-context{font-size:11px;font-weight:600;line-height:1.8;color:#6c8190;margin-top:8px}
@media(max-width:760px){#mediq-dashboard .mq-card-grid{grid-template-columns:repeat(2,minmax(0,1fr))}#mediq-dashboard .mq-action-grid{grid-template-columns:1fr}.wz-step{padding:5px}.wz-step .wz-step-value{font-size:9px}}
.wz-segment-tabs{display:flex;gap:6px;flex-wrap:wrap;margin:0 0 15px;padding-bottom:10px;border-bottom:1px solid #e2e7eb}
.wz-segment-tabs button{padding:9px 12px;border:1px solid #d4dfe6;border-radius:9px;background:#f5f8fa;color:#526777;font:700 11px Tahoma;cursor:pointer}
.wz-segment-tabs button.active{background:#69737d;color:white;border-color:#69737d}
.wz-segment[hidden]{display:none!important}
/* Float above the form without occupying a grid row or being clipped by form scroll. */
#mqWz .mq-jcalendar.mq-date-floating{position:fixed!important;z-index:50;margin:0!important;max-width:calc(100vw - 20px);padding:12px;background:#fff;border:1px solid #cce2f0;border-radius:12px;box-shadow:0 16px 48px rgba(23,65,86,.24);overflow:auto;direction:rtl}
:is(#mqWz,#vDialog) .mq-date-floating[hidden]{display:none!important}
:is(#mqWz,#vDialog) .mq-date-floating .mq-jcal-head{display:flex;align-items:center;justify-content:space-between;gap:8px}
:is(#mqWz,#vDialog) .mq-date-floating .mq-jcal-grid{display:grid;grid-template-columns:repeat(7,minmax(0,1fr));gap:4px;text-align:center;margin:10px 0}
:is(#mqWz,#vDialog) .mq-date-floating button{border:1px solid #d5e7f2;border-radius:6px;padding:5px;background:#f1f8fd;color:#315873;cursor:pointer;font:inherit}
:is(#mqWz,#vDialog) .mq-date-floating button:hover{background:#e0f0fa}
/* V11 layout and accessible operation dialog */
#mediq-dashboard .mq-logo img{width:121.8px!important}
#mediq-dashboard .mq-list-layout{grid-template-columns:297px minmax(0,1fr)}
#mediq-dashboard .v-five{grid-template-columns:repeat(5,minmax(0,1fr))}
#mediq-dashboard button.mq-module-card{font:inherit;text-align:right;cursor:pointer;display:flex;flex-direction:column;align-items:flex-start}
#mediq-dashboard .v-tag{display:inline-block;border-radius:8px;padding:5px 8px;font-size:11px;line-height:1.8}
#mediq-dashboard .v-tag.green{color:#17633d;background:#e5f5eb}
#mediq-dashboard .v-tag.orange{color:#8c4808;background:#fff0df}
#mediq-dashboard .v-active{display:block;color:#ab590c;font-size:10px}
#mediq-dashboard .v-summary-row{display:flex;flex-direction:column;gap:8px;padding:14px 0;border-bottom:1px solid #dce8ee;font-size:12px}
#mediq-dashboard .v-summary-row span{color:#6c8190}
#mediq-dashboard .v-summary-row b{line-height:1.8}
#mediq-dashboard .v-steps{display:flex;flex-direction:column;gap:8px}
#mediq-dashboard .v-steps>div{border-right:4px solid #dce8ee;padding:10px;background:#f4f8fb;border-radius:7px;font-size:11px}
#mediq-dashboard .v-steps>.current{background:#44525f;color:white;border-color:#44525f}
#mediq-dashboard .v-steps>.passed{background:#e5f5eb;border-color:#58a97a}
#mediq-dashboard .v-search{display:flex;gap:7px;flex-wrap:wrap}
#mediq-dashboard .v-search input{min-width:180px;border:1px solid #cbdfea;border-radius:8px;padding:10px;font:inherit}
#mediq-dashboard #vService{color:#9a5b10;font-size:11px}
#mediq-dashboard .v-overlay{position:fixed;inset:0;background:#122f4590;z-index:100100;display:flex;align-items:center;justify-content:center;padding:18px;direction:rtl}
#mediq-dashboard .v-overlay[hidden]{display:none}
#mediq-dashboard .v-dialog{width:min(920px,96vw);max-height:92vh;display:flex;flex-direction:column;background:#fff;border:1px solid #cbdfea;border-radius:18px;box-shadow:0 20px 80px #163d4950;overflow:hidden}
#mediq-dashboard .v-dialog header{display:flex;justify-content:space-between;align-items:center;padding:12px 20px;border-bottom:1px solid #dce8ee}
#mediq-dashboard .v-dialog header button{border:0;background:#edf5fa;border-radius:8px;width:35px;height:35px;font-size:24px;cursor:pointer}
#mediq-dashboard .v-dialog-body{overflow:auto;padding:20px;min-height:0}
#mediq-dashboard #vMessage{margin:0;padding:12px 20px;background:#f2f8fc;white-space:pre-wrap;line-height:1.8;font-size:12px}
#mediq-dashboard .v-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14px;margin:16px 0}
#mediq-dashboard .v-fields label{display:flex;flex-direction:column;gap:8px;font-size:12px}
#mediq-dashboard .v-fields input,#mediq-dashboard .v-fields select,#mediq-dashboard .v-fields textarea,#mediq-dashboard #vProcessSearch{font:inherit;padding:10px;border:1px solid #cbdfea;border-radius:8px;background:white;width:100%;box-sizing:border-box}
#mediq-dashboard .v-choice{display:flex;align-items:center;gap:10px;padding:12px;border-bottom:1px solid #e7edf1;font-size:12px;cursor:pointer}
#mediq-dashboard .v-choice small{margin-right:auto;color:#789}
#mediq-dashboard .v-operation-choices{display:flex;flex-wrap:wrap;gap:8px}
#mediq-dashboard .v-stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:20px}
#mediq-dashboard .v-stats>div{background:white;border:1px solid #cbdfea;padding:30px;display:flex;flex-direction:column;gap:12px;border-radius:16px}
#mediq-dashboard .v-stats strong{font-size:30px;color:#318fbd}
@media(max-width:1100px){#mediq-dashboard .v-five{grid-template-columns:repeat(3,minmax(0,1fr))}#mediq-dashboard .mq-list-layout{grid-template-columns:230px minmax(0,1fr)}}
@media(max-width:760px){#mediq-dashboard .v-five{grid-template-columns:repeat(2,minmax(0,1fr))}#mediq-dashboard .mq-list-layout{grid-template-columns:1fr}#mediq-dashboard .v-fields{grid-template-columns:1fr}#mediq-dashboard .v-choice{flex-wrap:wrap}}
#mediq-dashboard .v-attribute-list{max-height:220px;overflow:auto;border:1px solid #cbdfea;border-radius:8px;margin:12px 0;padding:12px;display:flex;flex-direction:column;gap:12px}#mediq-dashboard .v-attribute-list label[hidden]{display:none}
#mediq-dashboard .v-editor-tabs{display:flex;gap:6px;flex-wrap:wrap;position:sticky;top:-20px;z-index:2;background:white;padding:12px 0;border-bottom:1px solid #d4e5ee}
#mediq-dashboard .v-editor-tabs button{font:inherit;font-size:12px;cursor:pointer;border:1px solid #cbdfea;border-radius:9px;padding:10px;background:#f2f8fc;color:#385d73}
#mediq-dashboard .v-editor-tabs button.active{background:#485762;border-color:#485762;color:white}
#mediq-dashboard [data-edit-panel][hidden]{display:none}
#mediq-dashboard .v-editor-footer{display:flex;justify-content:space-between;align-items:center;gap:12px;position:sticky;bottom:-20px;background:#fff;padding:14px 0;border-top:1px solid #d4e5ee;font-size:11px;z-index:2}
#mediq-dashboard .v-fields textarea{min-height:90px}
#mediq-dashboard .v-fields small{color:#7b8c98}
#mediq-dashboard #vDialog .mq-date-floating{position:fixed;z-index:100120;display:block;overflow:auto;background:white;border:1px solid #c3d9e5;border-radius:12px;padding:12px;box-shadow:0 14px 40px #203d5b30;box-sizing:border-box}
#mediq-dashboard #vDialog .mq-date-floating[hidden]{display:none}
#mediq-dashboard .v-live-timeline{direction:rtl;background:white;border:1px solid #d0e2ec;border-radius:14px;padding:18px 20px;margin:0 0 20px;min-width:0}
#mediq-dashboard .v-live-timeline header{display:flex;justify-content:space-between;align-items:flex-start;gap:16px;margin-bottom:24px}
#mediq-dashboard .v-live-timeline header>div{display:flex;flex-direction:column;gap:7px;min-width:0}
#mediq-dashboard .v-live-timeline header span{font-size:11px;color:#6d8795;overflow-wrap:anywhere}
#mediq-dashboard .v-live-timeline header>small{font-size:10px;color:#698b8b;display:flex;align-items:center;gap:5px;white-space:nowrap}
#mediq-dashboard .v-live-timeline header>small>i{width:6px;height:6px;border-radius:50%;background:#16b66a;display:block}
#mediq-dashboard .v-live-timeline header>small.stale{color:#a46515}
#mediq-dashboard .v-live-timeline header>small.stale>i{background:#d58c30}
#mediq-dashboard .v-circle-track{list-style:none;margin:0;padding:0;display:flex;direction:rtl;align-items:flex-start}
#mediq-dashboard .v-circle-step{flex:1;min-width:0;text-align:center;position:relative;padding:0 6px;line-height:1.7}
#mediq-dashboard .v-circle-rail{position:relative;height:30px;margin-bottom:8px}
#mediq-dashboard .v-circle-node{position:relative;z-index:1;display:flex;align-items:center;justify-content:center;width:24px;height:24px;margin:0 auto;border-radius:50%;border:2px solid #cadce5;background:#e0eaf0;box-shadow:0 0 0 4px white;box-sizing:border-box;color:white;font-size:15px;font-weight:bold}
#mediq-dashboard .v-circle-line{position:absolute;top:11px;right:50%;width:calc(100% + 12px);height:3px;background:#d9e5ec}
#mediq-dashboard .v-circle-step:last-child .v-circle-line{display:none}
#mediq-dashboard .v-circle-step.done .v-circle-node{background:#15b464;border-color:#15b464}
#mediq-dashboard .v-circle-line.done{background:#15b464}
#mediq-dashboard .v-circle-step.current .v-circle-node{border-color:#087eaa;background:white}
#mediq-dashboard .v-circle-step.current .v-circle-node>i{display:block;width:8px;height:8px;border-radius:50%;background:#087eaa;animation:v13-pulse 1.6s ease-in-out infinite}
#mediq-dashboard .v-circle-step strong{display:block;font-size:11px;color:#335e76;overflow-wrap:anywhere}
#mediq-dashboard .v-circle-step.current strong{color:#087eaa}
#mediq-dashboard .v-circle-step small,#mediq-dashboard .v-circle-step time{display:block;font-size:10px;color:#8ba0ae}
#mediq-dashboard .v-circle-step.current small{color:#087eaa;font-weight:bold}
#mediq-dashboard .v-live-timeline footer{display:flex;justify-content:space-between;gap:14px;border-top:1px solid #edf3f7;margin-top:20px;padding-top:12px;font-size:11px}
#mediq-dashboard .v-timeline-warning{font-size:11px;color:#a46515}
@keyframes v13-pulse{0%,100%{box-shadow:0 0 0 0 #087eaa40}50%{box-shadow:0 0 0 6px #087eaa10}}
@media(prefers-reduced-motion:reduce){#mediq-dashboard .v-circle-step.current .v-circle-node>i{animation:none}}
@media(max-width:760px){#mediq-dashboard .v-live-timeline header{flex-direction:column}#mediq-dashboard .v-circle-track{flex-direction:column;gap:0}#mediq-dashboard .v-circle-step{width:100%;text-align:right;padding:0 40px 22px 0;box-sizing:border-box}#mediq-dashboard .v-circle-rail{position:absolute;right:0;top:0;width:24px;height:100%;margin:0}#mediq-dashboard .v-circle-line{top:24px;right:11px;height:calc(100% - 12px);width:3px}#mediq-dashboard .v-circle-step:last-child{padding-bottom:0}}
/* Keep row actions together; status dashboard and restrained hospital-blue styling. */
#mediq-dashboard #vAssetDashboard{margin-bottom:20px;direction:rtl}
#mediq-dashboard .v-dashboard-heading{display:flex;align-items:center;justify-content:space-between;gap:16px;margin:0 2px 12px}
#mediq-dashboard .v-dashboard-heading>div{display:flex;flex-direction:column;gap:6px}
#mediq-dashboard .v-dashboard-heading strong{font-size:16px;color:#245574}
#mediq-dashboard .v-dashboard-heading span,#mediq-dashboard .v-dashboard-heading small{font-size:11px;color:#7893a5}
#mediq-dashboard .v-status-cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:14px}
#mediq-dashboard .v-stat-card{--stat-color:#318ebe;--stat-tint:#edf7fd;position:relative;overflow:hidden;text-align:right;font:inherit;cursor:pointer;border:1px solid #d5e6ef;border-radius:17px;padding:18px 20px 16px;background:#fff;color:#345e78;display:grid;grid-template-columns:1fr 48px;gap:8px 12px;box-shadow:0 6px 22px #396a8a06;transition:border-color .16s,box-shadow .16s,transform .16s;min-width:0}
#mediq-dashboard .v-stat-card.active{--stat-color:#20996a;--stat-tint:#edf9f3}
#mediq-dashboard .v-stat-card.inactive{--stat-color:#d58a34;--stat-tint:#fff6e9}
#mediq-dashboard .v-stat-card.other{--stat-color:#7a88a3;--stat-tint:#f0f3f8}
#mediq-dashboard .v-stat-card:hover{transform:translateY(-2px);border-color:var(--stat-color);box-shadow:0 8px 26px #316b8a12}
#mediq-dashboard .v-stat-card.selected{border-color:var(--stat-color);box-shadow:inset 0 0 0 1px var(--stat-color),0 6px 22px #396a8a08}
#mediq-dashboard .v-stat-card:focus-visible{outline:3px solid #8dcced;outline-offset:3px}
#mediq-dashboard .v-stat-icon{grid-column:2;grid-row:1/span 2;width:46px;height:46px;display:flex;align-items:center;justify-content:center;border-radius:14px;background:var(--stat-tint);color:var(--stat-color)}
#mediq-dashboard .v-stat-icon svg{width:27px;height:27px}
#mediq-dashboard .v-stat-label{grid-column:1;grid-row:1;font-size:12px;color:#597b91;align-self:center}
#mediq-dashboard .v-stat-card>strong{grid-column:1;grid-row:2;font-size:28px;line-height:1.3;color:#244e68}
#mediq-dashboard .v-stat-bottom{grid-column:1/-1;font-size:10px;color:#8ba2b1;margin-top:5px}
#mediq-dashboard .v-stat-meter{grid-column:1/-1;height:4px;border-radius:5px;background:var(--stat-tint);overflow:hidden;margin-top:2px}
#mediq-dashboard .v-stat-meter>i{display:block;height:100%;background:var(--stat-color);border-radius:5px}
#mediq-dashboard #mqAssetsHost .mq-tbl{table-layout:auto!important;width:100%;border-collapse:separate;border-spacing:0}
#mediq-dashboard #mqAssetsHost .mq-tbl th{padding:14px 10px;background:#edf6fc;font-size:11px;line-height:1.7;color:#50738a;vertical-align:middle}
#mediq-dashboard #mqAssetsHost .mq-tbl td{padding:15px 10px;vertical-align:middle;border-bottom:1px solid #e8f0f5;font-size:11px;line-height:1.85}
#mediq-dashboard #mqAssetsHost .mq-tbl tr:last-child td{border-bottom:0}
#mediq-dashboard #mqAssetsHost .mq-tbl tbody tr{transition:background .15s;cursor:pointer}
#mediq-dashboard #mqAssetsHost .mq-tbl tbody tr:hover{background:#f6fbfe}
#mediq-dashboard #mqAssetsHost .mq-tbl th:last-child,#mediq-dashboard #mqAssetsHost .mq-tbl td:last-child{width:156px;min-width:156px;white-space:nowrap}
#mediq-dashboard .v-row-actions{display:inline-flex!important;flex-direction:row!important;flex-wrap:nowrap!important;align-items:center;justify-content:center;gap:6px;white-space:nowrap}
#mediq-dashboard .v-row-actions .mq-assets-btn{display:inline-flex!important;align-items:center;justify-content:center;gap:5px;min-width:66px;margin:0!important;padding:7px 9px!important;border-radius:9px;font-size:10px!important;white-space:nowrap;min-height:34px}
#mediq-dashboard .v-row-actions .mq-assets-btn svg{width:14px;height:14px;flex:0 0 14px;fill:none;stroke:currentColor;stroke-width:1.6;stroke-linecap:round;stroke-linejoin:round}
#mediq-dashboard .v-row-actions [data-detail]{background:#f1f8fd;border-color:#d5e6ef;color:#377caa}
#mediq-dashboard .v-row-actions [data-vedit]{background:#fff;border-color:#bdd8e8;color:#377caa}
#mediq-dashboard .v-row-actions button:disabled{opacity:.45;cursor:not-allowed}
#mediq-dashboard .v-status-pill{display:inline-flex;align-items:center;gap:5px;border-radius:8px;background:#f0f3f8;color:#65758f;padding:4px 8px;font-size:10px;white-space:nowrap}
#mediq-dashboard .v-status-pill:before{content:'';width:5px;height:5px;border-radius:50%;background:currentColor}
#mediq-dashboard .v-status-pill.active{background:#ecf8f0;color:#27875b}
#mediq-dashboard .v-status-pill.inactive{background:#fff5e8;color:#a57532}
#mediq-dashboard .v-tag{max-width:210px;overflow-wrap:anywhere;line-height:1.8;padding:5px 9px;border:1px solid transparent}
#mediq-dashboard .v-tag.green{background:#edf8f1;color:#3b8060;border-color:#e2f0e7}
#mediq-dashboard .v-tag.orange{background:#fff4e8;color:#a57532;border-color:#faecd9}
#mediq-dashboard .mq-list-menu{border-color:#d5e6ef;box-shadow:0 6px 24px #396a8a05}
#mediq-dashboard .v-summary-row{padding:13px 0}
@media(max-width:1150px){#mediq-dashboard .v-status-cards{grid-template-columns:repeat(2,minmax(0,1fr))}#mediq-dashboard .mq-list-layout{grid-template-columns:240px minmax(0,1fr)}}
@media(max-width:900px){#mediq-dashboard .mq-list-layout{grid-template-columns:1fr}#mediq-dashboard #mqAssetsHost .mq-tbl th:last-child,#mediq-dashboard #mqAssetsHost .mq-tbl td:last-child{min-width:146px;width:146px}}
@media(max-width:600px){#mediq-dashboard .v-dashboard-heading{align-items:flex-start;flex-direction:column;gap:7px}#mediq-dashboard .v-stat-card{padding:14px;grid-template-columns:1fr 32px}#mediq-dashboard .v-stat-icon{width:32px;height:32px;border-radius:10px}#mediq-dashboard .v-stat-icon svg{width:21px;height:21px}#mediq-dashboard .v-stat-label{font-size:10px}#mediq-dashboard .v-stat-card>strong{font-size:24px}}
/* V15: dependent attribute values and compact vertical process under sidebar details. */
#mediq-dashboard .v-smart-filter{display:flex;flex-direction:column;gap:9px;direction:rtl}
#mediq-dashboard .v-smart-filter label{font-size:12px;font-weight:900;color:#315873}
#mediq-dashboard .v-smart-filter select,#mediq-dashboard .v-smart-filter input{width:100%;max-width:100%;min-height:39px;border:1px solid #cbdfea;border-radius:9px;padding:8px 11px;background:white;color:#315873;outline:none;font:12px Tahoma,Arial;box-sizing:border-box}
#mediq-dashboard .v-smart-filter select:focus,#mediq-dashboard .v-smart-filter input:focus{border-color:#3997c8;box-shadow:0 0 0 3px #3997c822}
#mediq-dashboard .v-smart-filter #vFilterDetails{display:flex;flex-direction:column;gap:9px;margin-top:8px}
#mediq-dashboard .v-smart-filter #vFilterDetails[hidden]{display:none!important}
#mediq-dashboard .v-smart-filter #vFilterValue{height:178px;overflow:auto}
#mediq-dashboard .v-smart-filter #vFilterValue option{padding:8px;white-space:normal}
#mediq-dashboard .v-smart-filter small,#mediq-dashboard .v-filter-hint{font-size:11px;color:#7995a7}
#mediq-dashboard .v-filter-actions{display:flex;justify-content:flex-start;margin-top:4px}
#mediq-dashboard .v-filter-chip{display:flex;align-items:center;justify-content:space-between;gap:8px;margin:7px 0;padding:9px 11px;border:1px solid #d4e6f0;background:#f1f8fd;border-radius:9px;font-size:11px;color:#305b78;font-weight:700}
#mediq-dashboard .v-filter-chip button{border:0;background:#e5f6ee;color:#15986b;font-size:17px;font-weight:900;border-radius:6px;cursor:pointer;min-width:27px;min-height:27px}
#mediq-dashboard #vFilterList h4{font-size:12px;margin:15px 0 5px}
#mediq-dashboard .mq-list-menu #vLiveTimeline{margin:18px 0 0;padding:15px 5px 5px;border:0;border-top:1px solid #dce9f1;border-radius:0;box-shadow:none;background:transparent}
#mediq-dashboard .mq-list-menu #vLiveTimeline header{margin-bottom:17px}
#mediq-dashboard .mq-list-menu #vLiveTimeline header strong{font-size:13px;color:#245574}
#mediq-dashboard .mq-list-menu #vLiveTimeline .v-circle-track{display:flex;flex-direction:column;align-items:stretch;gap:0}
#mediq-dashboard .mq-list-menu #vLiveTimeline .v-circle-step{width:100%;min-height:69px;flex:none;text-align:right;padding:0 38px 18px 0}
#mediq-dashboard .mq-list-menu #vLiveTimeline .v-circle-rail{position:absolute;right:0;top:0;width:27px;height:100%;margin:0}
#mediq-dashboard .mq-list-menu #vLiveTimeline .v-circle-node{margin:0;width:24px;height:24px}
#mediq-dashboard .mq-list-menu #vLiveTimeline .v-circle-line{position:absolute;top:24px;right:11px;width:3px;height:calc(100% - 20px)}
#mediq-dashboard .mq-list-menu #vLiveTimeline .v-circle-step strong{font-size:11px}
#mediq-dashboard .mq-list-menu #vLiveTimeline .v-circle-step small{font-size:10px}
/* Inline Jira Assets-style attribute filtering; never uses the dialog overlay. */
#mediq-dashboard .v-filter-anchor{position:relative;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
#mediq-dashboard .v-inline-filters{position:absolute;top:calc(100% + 8px);right:0;z-index:80;width:min(610px,calc(100vw - 70px));max-height:min(560px,75vh);overflow:auto;direction:rtl;background:#fff;border:1px solid #cbd9e4;border-radius:8px;box-shadow:0 14px 40px rgba(21,55,75,.18);padding:12px;text-align:right}
#mediq-dashboard .v-filter-top{display:flex;align-items:center;justify-content:space-between;padding:3px 5px 12px;border-bottom:1px solid #e4edf3;font-size:13px;color:#245574}
#mediq-dashboard .v-filter-top button{border:0;background:transparent;font-size:23px;cursor:pointer;color:#55748a}
#mediq-dashboard .v-filter-columns{display:grid;grid-template-columns:minmax(160px,1fr) minmax(200px,1.2fr);gap:12px;padding-top:12px}
#mediq-dashboard .v-filter-attributes{border-left:1px solid #e4edf3;padding-left:10px;min-width:0}
#mediq-dashboard .v-filter-attributes input,#mediq-dashboard .v-filter-values input,#mediq-dashboard .v-filter-values select{width:100%;min-height:34px;max-width:100%;padding:7px 9px;border:1px solid #ccdce7;border-radius:5px;background:#fff;color:#315873;box-sizing:border-box;font:12px Tahoma}
#mediq-dashboard .v-attribute-list{max-height:290px;overflow-y:auto;margin-top:8px}
#mediq-dashboard .v-attribute-choice{display:flex;align-items:center;gap:9px;width:100%;min-height:34px;border:0;background:#fff;color:#315873;text-align:right;padding:6px;cursor:pointer;font:12px Tahoma}
#mediq-dashboard .v-attribute-choice:hover{background:#ecf5fc}
#mediq-dashboard .v-checkmark{display:inline-flex;justify-content:center;align-items:center;width:15px;height:15px;border:1px solid #a7b7c4;border-radius:2px;color:#247eaf;font-weight:bold;flex:none}
#mediq-dashboard .v-filter-values{min-width:0}
#mediq-dashboard .v-filter-values #vFilterDetails{display:flex;flex-direction:column;gap:8px}
#mediq-dashboard .v-filter-values #vFilterDetails[hidden],#mediq-dashboard .v-filter-values #vFilterPickHint[hidden]{display:none!important}
#mediq-dashboard .v-filter-values label{font-size:12px;font-weight:700;color:#345c74}
#mediq-dashboard .v-filter-values #vFilterValue{height:166px;overflow:auto}
#mediq-dashboard .v-filter-values #vFilterValue option{padding:7px}
#mediq-dashboard .v-filter-values small,#mediq-dashboard .v-filter-values p{font-size:11px;color:#7893a5}
#mediq-dashboard .v-inline-filters #vFilterList{border-top:1px solid #e5edf3;margin-top:10px;padding-top:6px}
@media(max-width:650px){#mediq-dashboard .v-filter-columns{grid-template-columns:1fr}#mediq-dashboard .v-filter-attributes{border-left:0;border-bottom:1px solid #e4edf3;padding-bottom:9px}#mediq-dashboard .v-attribute-list{max-height:155px}}
/* V18 - Inline checkbox selection, no separate active filter section */
#mediq-dashboard .v-filter-checklist{height:166px;overflow-y:auto;border:1px solid #ccdce7;border-radius:5px;background:white;padding:4px!important}
#mediq-dashboard .v-filter-check-option{display:flex!important;flex-direction:row!important;align-items:center;gap:9px;min-height:33px;margin:0!important;padding:5px 8px;cursor:pointer;color:#315873;font-size:12px;font-weight:600}
#mediq-dashboard .v-filter-check-option:hover{background:#eef7fc}
#mediq-dashboard .v-filter-check-option:has(input:checked){background:#e5f3fc;color:#20577b}
#mediq-dashboard .v-filter-check-option input[type=checkbox]{width:16px!important;height:16px!important;min-height:0!important;flex:0 0 16px;margin:0!important;accent-color:#3997c8;cursor:pointer}
#mediq-dashboard .v-filter-check-option span{flex:1;min-width:0}
#mediq-dashboard .v-filter-empty{margin:10px!important;text-align:center}
/* V19: simultaneous attribute filters and right-aligned checkboxes */
#mediq-dashboard .v-attribute-choice,
#mediq-dashboard .v-filter-check-option {
direction:rtl !important;
text-align:right !important;
justify-content:flex-start !important;
flex-direction:row !important;
}
#mediq-dashboard .v-attribute-choice { gap:9px !important; }
#mediq-dashboard .v-attribute-choice .v-attribute-tick {
display:inline-flex;align-items:center;justify-content:center;
width:16px;height:16px;min-width:16px;flex:0 0 16px;
border:1px solid #9bbad0;border-radius:3px;
background:#fff;color:#fff;font-size:12px;font-weight:900;
}
#mediq-dashboard .v-attribute-choice[aria-pressed="true"] .v-attribute-tick {
background:#3997c8;border-color:#3997c8;color:#fff;
}
#mediq-dashboard .v-attribute-current{background:#eaf4fc!important;}
#mediq-dashboard .v-filter-check-option input[type="checkbox"]{
order:0!important;margin:0!important;float:none!important;
position:static!important;inset:auto!important;
flex:0 0 16px!important;align-self:center!important;
}
#mediq-dashboard .v-filter-check-option span{order:1!important;flex:1 1 auto!important;text-align:right!important;}
/* ===== V26: scoped table alignment, purple department, hierarchy arrow ===== */
#mediq-dashboard .v-tag.purple{background:#f1e8ff!important;color:#773ab6!important;border:1px solid #e0c9ff!important}
#mediq-dashboard #mqAssetsHost .mq-tbl th:nth-child(n+4),
#mediq-dashboard #mqAssetsHost .mq-tbl td:nth-child(n+4){text-align:center!important;vertical-align:middle!important}
#mediq-dashboard #mqAssetsHost .mq-tbl td:nth-child(4) .v-tag,
#mediq-dashboard #mqAssetsHost .mq-tbl td:nth-child(5) .v-tag{margin:0 auto!important}
#mediq-dashboard .mq-module-card.mq-has-children{position:relative!important;padding-bottom:40px!important}
#mediq-dashboard .mq-module-card.mq-has-children .mq-hierarchy-arrow{position:absolute;bottom:12px;left:13px;width:25px;height:25px;display:flex;align-items:center;justify-content:center;border:1px solid #d6e4ed;border-radius:8px;background:#f1f7fb;color:#4484af;font:900 20px/1 Tahoma;pointer-events:none}
/* V27 — compact RTL filters and animated live workflow step */
#mediq-dashboard .v-inline-filters{
width:min(510px,calc(100vw - 36px)) !important;
max-height:min(500px,78vh) !important;
padding:10px !important;
direction:rtl !important;
text-align:right !important;
}
#mediq-dashboard .v-filter-columns{
grid-template-columns:minmax(0,1fr) minmax(0,1.04fr) !important;
gap:9px !important;
direction:rtl !important;
}
#mediq-dashboard .v-filter-attributes{
min-width:0 !important;padding-left:8px !important;
}
#mediq-dashboard .v-filter-values,#mediq-dashboard .v-filter-values #vFilterDetails{
direction:rtl !important;text-align:right !important;min-width:0 !important;
}
#mediq-dashboard .v-attribute-choice,
#mediq-dashboard .v-filter-check-option{
display:grid !important;
grid-template-columns:16px minmax(0,1fr) !important;
column-gap:7px !important;
justify-content:initial !important;
align-items:center !important;
direction:rtl !important;
text-align:right !important;
width:100% !important;
padding:5px 4px !important;
box-sizing:border-box !important;
}
#mediq-dashboard .v-attribute-choice .v-attribute-tick,
#mediq-dashboard .v-filter-check-option input[type="checkbox"]{
grid-column:1 !important;
grid-row:1 !important;
justify-self:start !important;
margin:0 !important;
order:initial !important;
}
#mediq-dashboard .v-attribute-choice>span:last-child,
#mediq-dashboard .v-filter-check-option>span{
grid-column:2 !important;grid-row:1 !important;
text-align:right !important;min-width:0 !important;
order:initial !important;flex:initial !important;
line-height:1.8 !important;
}
#mediq-dashboard .v-filter-checklist{padding:4px !important;}
#mediq-dashboard .v-filter-values label,
#mediq-dashboard .v-filter-values input,
#mediq-dashboard .v-filter-values select{
direction:rtl !important;text-align:right !important;
}
#mediq-dashboard .v-circle-step.current .v-circle-node{
animation:mq-live-circle 1.65s ease-in-out infinite !important;
}
#mediq-dashboard .v-circle-step.current .v-circle-node>i{
animation:mq-live-dot 1.65s ease-in-out infinite !important;
}
@keyframes mq-live-circle{
0%,100%{box-shadow:0 0 0 3px #ffffff,0 0 0 4px rgba(8,126,170,.12);border-color:#087eaa}
50%{box-shadow:0 0 0 4px #ffffff,0 0 0 10px rgba(8,126,170,.20);border-color:#0c9ac8}
}
@keyframes mq-live-dot{
0%,100%{opacity:1;transform:scale(1)}
50%{opacity:.32;transform:scale(.55)}
}
@media(max-width:540px){
#mediq-dashboard .v-filter-columns{grid-template-columns:1fr !important}
#mediq-dashboard .v-filter-attributes{border-left:0 !important;border-bottom:1px solid #e4edf3 !important;padding-bottom:8px !important}
}
/* V28 — visible live step + hierarchy corner indicator */
#mediq-dashboard .mq-card-grid.v-five .mq-module-card.mq-has-children{
position:relative!important;padding-bottom:40px!important;
}
#mediq-dashboard .mq-card-grid.v-five .mq-hierarchy-arrow{
position:absolute!important;left:13px!important;bottom:12px!important;
display:flex!important;visibility:visible!important;opacity:1!important;
width:27px!important;height:27px!important;align-items:center!important;justify-content:center!important;
border:1px solid #bfd8e9!important;border-radius:8px!important;
background:#eaf5fc!important;color:#257eaf!important;
font:900 19px/1 Tahoma,Arial,sans-serif!important;
pointer-events:none!important;z-index:3!important;
}
#mediq-dashboard .v-circle-step.current .v-circle-node{
animation:mediq-v28-live 1.15s ease-in-out infinite!important;
will-change:box-shadow,background-color,transform;
}
#mediq-dashboard .v-circle-step.current .v-circle-node>i{
animation:mediq-v28-dot 1.15s ease-in-out infinite!important;
}
@keyframes mediq-v28-live{
0%,100%{background:#fff;border-color:#087eaa;box-shadow:0 0 0 3px #fff,0 0 0 4px rgba(0,139,207,.15);transform:scale(1)}
50%{background:#d8f1ff;border-color:#0077b6;box-shadow:0 0 0 4px #fff,0 0 0 10px rgba(0,139,207,.36);transform:scale(1.12)}
}
@keyframes mediq-v28-dot{
0%,100%{opacity:1;transform:scale(1)}
50%{opacity:.18;transform:scale(.4)}
}
/* V29 — strong, clearly visible active-workflow blink. */
#mediq-dashboard .mq-list-menu #vLiveTimeline .v-circle-step.current .v-circle-node,
#mediq-dashboard #vLiveTimeline .v-circle-step.current .v-circle-node {
animation: mediq-v29-blink 1s steps(1,end) infinite !important;
transform:none !important;
will-change:background-color,box-shadow !important;
}
#mediq-dashboard .mq-list-menu #vLiveTimeline .v-circle-step.current .v-circle-node>i,
#mediq-dashboard #vLiveTimeline .v-circle-step.current .v-circle-node>i {
animation: mediq-v29-dot 1s steps(1,end) infinite !important;
}
@keyframes mediq-v29-blink {
0%, 100% { background:#fff; border-color:#087eaa; box-shadow:0 0 0 4px #fff,0 0 0 5px rgba(0,125,190,.18); }
50% { background:#087eaa; border-color:#087eaa; box-shadow:0 0 0 4px #fff,0 0 0 11px rgba(0,125,190,.40); }
}
@keyframes mediq-v29-dot {
0%,100% { background:#087eaa; opacity:1; }
50% { background:#fff; opacity:1; }
}
/* V30 - focused UI refinements */
#mediq-dashboard .mq-header{display:none!important}
#mediq-dashboard .mq-hero{margin-top:18px!important;min-height:110px!important;overflow:visible!important}
#mediq-dashboard .mq-hero .mq-header-left{position:relative;z-index:3;display:flex!important;flex-wrap:wrap!important;margin:0!important}
#mediq-dashboard .mq-hero .mq-header-welcome{color:#37617c!important}
#mediq-dashboard .mq-breadcrumb{margin-top:14px!important;min-height:48px!important}
#mediq-dashboard .mq-tree-title{margin-top:8px!important}
#mediq-dashboard .mq-assets-actions{order:-1}
#mediq-dashboard .mq-assets-btn.primary,#mediq-dashboard #vProcess,#mediq-dashboard #mqAssetsNew,#mediq-dashboard #vReview,#mediq-dashboard #vCommit{background:#179967!important;border-color:#179967!important;color:#fff!important}
#mediq-dashboard .mq-assets-btn.primary:hover,#mediq-dashboard #vProcess:hover{background:#0c7c51!important}
#mediq-dashboard .v-process-controls{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin:12px 0}
#mediq-dashboard .v-process-controls label{font-size:12px;font-weight:700;color:#315873;display:flex;flex-direction:column;gap:7px}
#mediq-dashboard .v-process-controls select{width:100%;padding:9px;border:1px solid #cbdfea;border-radius:8px;background:#fff}
#mediq-dashboard .v-process-table{width:100%;border-collapse:collapse;margin-top:12px;font-size:11px}
#mediq-dashboard .v-process-table th,#mediq-dashboard .v-process-table td{padding:10px 7px;border-bottom:1px solid #deebf3;text-align:center;vertical-align:middle}
#mediq-dashboard .v-process-table th{background:#edf6fc;color:#315873}
#mediq-dashboard .v-active-flag{display:inline-block;width:8px;height:8px;border-radius:50%;margin-left:5px;background:#16a46b}
#mediq-dashboard .v-active-flag.inactive{background:#e08c44}
#mediq-dashboard .v-process-searchline{margin-top:15px}
@media(max-width:750px){#mediq-dashboard .v-process-controls{grid-template-columns:1fr}#mediq-dashboard .mq-hero{flex-wrap:wrap;gap:10px}}
#mediq-dashboard .mq-tree-row.level-2,#mediq-dashboard .mq-tree-row.level-3,#mediq-dashboard .mq-tree-row.level-4,#mediq-dashboard .mq-tree-children,#mediq-dashboard .mq-tree-separator{display:none!important}
#mediq-dashboard .mq-tree-row.level-1{min-height:48px!important}
#mediq-dashboard .mq-tree-title{font-size:12px!important}
/* V31: five-item primary tree, no former cycle navigation */
#mediq-dashboard .mq-tree-v31{margin-top:18px;gap:8px;overflow-y:auto;}
#mediq-dashboard .mq-tree-v31 .mq-tree-row{min-height:48px;padding:0 13px;font-size:13px;white-space:normal;line-height:1.8;}
#mediq-dashboard .mq-tree-v31 .mq-tree-dot{flex:0 0 6px;}
#mediq-dashboard .mq-tree-v31 .mq-tree-row.active{background:linear-gradient(90deg,#3997c8,#277eaf);}
#mediq-dashboard .v32-review-top{display:inline-flex!important;margin:10px 0 14px!important;align-items:center;justify-content:center}
/* V32 - keep main navigation blue; only operational submit buttons soft green */
#mediq-dashboard .mq-assets-btn.primary,#mediq-dashboard #mqAssetsNew,#mediq-dashboard #vProcess{background:linear-gradient(135deg,#429ed0,#2c88bb)!important;border-color:#328fbe!important;color:#fff!important}
#mediq-dashboard #vReview,#mediq-dashboard #vCommit,#mediq-dashboard .v-dialog .mq-assets-btn.primary{background:#43a981!important;border-color:#43a981!important;color:#fff!important}
#mediq-dashboard #vReview:hover,#mediq-dashboard #vCommit:hover{background:#339671!important}
/* Real back button sits at the left edge of the hero, never in its center */
#mediq-dashboard .mq-hero{position:relative!important;padding-left:122px!important}
#mediq-dashboard #mqBack{position:absolute!important;left:20px!important;top:50%!important;transform:translateY(-50%)!important;margin:0!important;right:auto!important}
/* Hierarchy is revealed only for the currently selected branch */
#mediq-dashboard .mq-tree-v31 .v32-tree-children{display:none!important;margin:0 0 7px!important;padding-right:12px!important}
#mediq-dashboard .mq-tree-v31 .v32-tree-children.open{display:block!important}
#mediq-dashboard .mq-tree-v31 .v32-tree-children .mq-tree-row.level-2{display:flex!important;min-height:35px!important;font-size:11px!important;color:rgba(255,255,255,.85)}
#mediq-dashboard .mq-tree-v31 .v32-tree-children .mq-tree-row.level-2.active{background:#2b83b7!important;color:white!important}
#mediq-dashboard .mq-tree-v31 .mq-tree-row.level-1[data-tree-key="logistics"]:after,
#mediq-dashboard .mq-tree-v31 .mq-tree-row.level-1[data-tree-key="property"]:after{content:'⌄';margin-right:auto;color:#eaf4fa;font-size:16px}
/* Compact right-to-left feature picker: no horizontal scrollbar or overflowing labels */
#mediq-dashboard .v-inline-filters{width:min(485px,calc(100vw - 35px))!important;max-height:min(490px,75vh)!important;overflow-y:auto!important;overflow-x:hidden!important;text-align:right!important;direction:rtl!important}
#mediq-dashboard .v-filter-columns{grid-template-columns:minmax(0,1fr) minmax(0,1fr)!important;gap:8px!important}
#mediq-dashboard .v-filter-attributes,#mediq-dashboard .v-filter-values{min-width:0!important;overflow:hidden!important}
#mediq-dashboard .v-attribute-list,#mediq-dashboard .v-filter-checklist{overflow-x:hidden!important;max-width:100%!important}
#mediq-dashboard .v-filter-check-option{display:flex!important;direction:rtl!important;flex-direction:row!important;justify-content:flex-start!important;align-items:center!important;gap:6px!important;text-align:right!important;padding:6px!important;min-width:0!important}
#mediq-dashboard .v-filter-check-option input[type=checkbox]{order:0!important;position:static!important;flex:0 0 15px!important;width:15px!important;height:15px!important;margin:0!important}
#mediq-dashboard .v-filter-check-option>span{order:1!important;flex:1 1 0!important;min-width:0!important;max-width:100%!important;overflow-wrap:anywhere!important;word-break:break-word!important;white-space:normal!important;text-align:right!important;line-height:1.7!important}
#mediq-dashboard .v-attribute-choice{white-space:normal!important;overflow-wrap:anywhere!important}
#mediq-dashboard #vFilterFind,#mediq-dashboard #vAttributeSearch{width:100%!important;min-width:0!important}
@media(max-width:520px){#mediq-dashboard .v-filter-columns{grid-template-columns:1fr!important}#mediq-dashboard .v-inline-filters{width:min(360px,calc(100vw - 20px))!important}}
</style>
<div class="mq-app">
<!-- =====================================================
MAIN
===================================================== -->
<main class="mq-main">
<!-- HEADER -->
<header class="mq-header">
<div class="mq-header-right">
<div
id="mqPageTitle"
class="mq-page-title"
>
تأمین
</div>
<div
id="mqPageDesc"
class="mq-page-description"
>
مدیریت فرآیند تأمین تجهیزات پزشکی
</div>
</div>
<div class="mq-header-left">
<a
id="mqEditPageBtn"
class="mq-edit-page-btn"
href="/pages/editpage.action?pageId=177807112"
title="ویرایش صفحه داشبورد"
>
<svg viewBox="0 0 24 24" aria-hidden="true">
<path d="M12 20h9"></path>
<path d="M16.5 3.5a2.1 2.1 0 0 1 3 3L8 18l-4 1 1-4Z"></path>
</svg>
<span>ویرایش صفحه</span>
</a>
<div class="mq-header-welcome">
<span class="mq-welcome-dot"></span>
<strong id="mqWelcomeUser">کاربر مدیکیو</strong>
<span>خوش آمدید</span>
</div>
</div>
</header>
<!-- HERO -->
<section class="mq-hero">
<div>
<div
id="mqHeroTitle"
class="mq-hero-title"
>
مدیریت تجهیزات
</div>
<div
id="mqHeroDesc"
class="mq-hero-desc"
>
بخش موردنظر خود را انتخاب کنید.
</div>
</div>
<button
id="mqBack"
class="mq-back-btn"
type="button"
>
بازگشت
</button>
</section>
<!-- BREADCRUMB -->
<div
id="mqBreadcrumb"
class="mq-breadcrumb"
></div>
<!-- DYNAMIC VIEW -->
<div
id="mqView"
class="mq-view"
>
<div class="mq-section-head">
<div>
<div class="mq-section-title">مدیریت تجهیزات</div>
<div class="mq-section-desc">یکی از حوزههای مدیریت تجهیزات را انتخاب کنید.</div>
</div>
</div>
<div class="mq-card-grid">
<div class="mq-module-card">
<div class="mq-module-icon">
<svg viewBox="0 0 24 24"><path d="M12 3l7 4-7 4-7-4 7-4z"></path><path d="M5 7v9l7 4 7-4V7"></path><path d="M12 11v9"></path></svg>
</div>
<div class="mq-module-name">مدیریت اموال</div>
</div>
<div class="mq-module-card">
<div class="mq-module-icon">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="3"></circle><path d="M12 2v3"></path><path d="M12 19v3"></path><path d="M2 12h3"></path><path d="M19 12h3"></path></svg>
</div>
<div class="mq-module-name">مدیریت تعمیر و نگهداری</div>
</div>
<div class="mq-module-card">
<div class="mq-module-icon">
<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9"></circle><path d="M8 12h8"></path><path d="M12 8v8"></path></svg>
</div>
<div class="mq-module-name">مدیریت مالی و بهرهوری</div>
</div>
<div class="mq-module-card" data-action="logistics">
<div class="mq-module-icon">
<svg viewBox="0 0 24 24"><path d="M4 7h16"></path><path d="M6 7l1 13h10l1-13"></path><path d="M9 4h6"></path></svg>
</div>
<div class="mq-module-name">مدیریت تأمین و لجستیک</div>
<div class="mq-module-arrow">‹</div>
</div>
</div>
</div>
</main>
<!-- =====================================================
SIDEBAR
===================================================== -->
<aside class="mq-sidebar">
<div class="mq-logo">
<img
src="/download/attachments/174855060/MediQ%20Heart%20Medical%20Logo.png"
alt="MediQ"
>
</div>
<div class="mq-life-title">
چرخه عمر تجهیزات
</div>
<div class="mq-life">
<div
class="mq-life-item active"
data-cycle="supply"
>
<div class="mq-life-icon">
<svg viewBox="0 0 24 24">
<path d="M4 7h16"></path>
<path d="M6 7l1 13h10l1-13"></path>
<path d="M9 4h6"></path>
</svg>
</div>
تأمین
</div>
<div
class="mq-life-item"
data-cycle="operation"
>
<div class="mq-life-icon">
<svg viewBox="0 0 24 24">
<circle
cx="12"
cy="12"
r="3"
></circle>
<path d="M12 3v3"></path>
<path d="M12 18v3"></path>
<path d="M3 12h3"></path>
<path d="M18 12h3"></path>
</svg>
</div>
بهرهبرداری
</div>
<div
class="mq-life-item"
data-cycle="replacement"
>
<div class="mq-life-icon">
<svg viewBox="0 0 24 24">
<path d="M4 7h11"></path>
<path d="M12 4l3 3-3 3"></path>
<path d="M20 17H9"></path>
<path d="M12 14l-3 3 3 3"></path>
</svg>
</div>
جایگزینی
</div>
<div
class="mq-life-item"
data-cycle="maintenance"
>
<div class="mq-life-icon">
<svg viewBox="0 0 24 24">
<path
d="M14 6a4 4 0 0 0 4 4l-8 8-4-4 8-8z"
></path>
</svg>
</div>
نگهداری
</div>
</div>
<!-- MEDIQ V31 - FIVE PRIMARY NAVIGATION SECTIONS -->
<nav class="mq-tree mq-tree-v31" id="mqTree" aria-label="منوی اصلی مدیکیو">
<div class="mq-tree-row level-1" data-tree-action="equipmentMaintenance" data-tree-key="equipmentMaintenance"><span class="mq-tree-dot"></span><span>مدیریت تعمیر و نگهداری</span></div>
<div class="mq-tree-row level-1" data-tree-action="logistics" data-tree-key="logistics"><span class="mq-tree-dot"></span><span>مدیریت تأمین و لجستیک</span></div>
<div class="mq-tree-children v32-tree-children" data-tree-group="logistics">
<div class="mq-tree-row level-2" data-v32-nav="consumable"><span class="mq-tree-dot"></span><span>کالاهای مصرفی</span></div>
<div class="mq-tree-row level-2" data-v32-nav="fixed"><span class="mq-tree-dot"></span><span>داراییهای ثابت</span></div>
<div class="mq-tree-row level-2" data-v32-nav="suppliers"><span class="mq-tree-dot"></span><span>تأمینکنندهها</span></div>
</div>
<div class="mq-tree-row level-1" data-tree-action="property" data-tree-key="property"><span class="mq-tree-dot"></span><span>مدیریت اموال و داراییها</span></div>
<div class="mq-tree-children v32-tree-children" data-tree-group="property">
<div class="mq-tree-row level-2" data-v32-nav="assets"><span class="mq-tree-dot"></span><span>لیست داراییها</span></div>
<div class="mq-tree-row level-2" data-v32-nav="handover"><span class="mq-tree-dot"></span><span>تحویل و تحول دارایی</span></div>
</div>
<div class="mq-tree-row level-1" data-tree-action="finance" data-tree-key="finance"><span class="mq-tree-dot"></span><span>مدیریت مالی و بهرهوری</span></div>
<div class="mq-tree-row level-1" data-tree-action="analysis" data-tree-key="analysis"><span class="mq-tree-dot"></span><span>تحلیل و آنالیز</span></div>
</nav>
<div class="mq-sidebar-bottom">
<div
id="mqLogout"
class="mq-logout"
>
خروج از حساب کاربری
</div>
</div>
</aside>
</div>
<div id="mqWz" aria-hidden="true">
<div class="wz-dialog" role="dialog" aria-modal="true" aria-labelledby="wzTitle">
<div class="wz-head">
<div class="wz-head-top"><div class="wz-title" id="wzTitle">انتخاب گروه</div><button type="button" class="wz-close" id="wzClose" aria-label="بستن">×</button></div>
<div class="wz-steps" id="wzSteps"></div>
</div>
<div class="wz-body" id="wzBody"></div>
<div class="wz-msg" id="wzMsg" role="status"></div>
<div class="wz-foot">
<div class="wz-foot-r"><button type="button" class="wz-btn" id="wzPrev">مرحله قبل</button></div>
<div class="wz-foot-l"><button type="button" class="wz-btn primary" id="wzNext">مرحله بعد</button></div>
</div>
</div>
</div>
<div id="mqDetail" aria-hidden="true">
<div class="wz-dialog" role="dialog" aria-modal="true" aria-labelledby="mqDetailTitle">
<div class="wz-head"><div class="wz-head-top"><div class="wz-title" id="mqDetailTitle">جزئیات دارایی</div><button type="button" class="wz-close" id="mqDetailClose" aria-label="بستن">×</button></div></div>
<div class="wz-body" id="mqDetailBody"></div>
</div>
</div>
<div id="mqToast" class="mq-toast"></div>
<script>
(function () {
"use strict";
function mqShowFatal(msg){
try{
var d=document.getElementById("mqHeroDesc");
if(d){d.textContent="خطای اسکریپت: "+msg;d.style.color="#ffb4b4";d.style.direction="ltr";d.style.textAlign="right";}
}catch(e){}
}
/* ============================================================
STATE
============================================================ */
var state = {
cycle:
"supply",
screen:
"equipment",
selectedAssetSection:
"purchased"
};
/* ============================================================
ELEMENTS
============================================================ */
var view =
document.getElementById(
"mqView"
);
var breadcrumb =
document.getElementById(
"mqBreadcrumb"
);
var heroTitle =
document.getElementById(
"mqHeroTitle"
);
var heroDesc =
document.getElementById(
"mqHeroDesc"
);
var backButton =
document.getElementById(
"mqBack"
);
var pageTitle =
document.getElementById(
"mqPageTitle"
);
var pageDesc =
document.getElementById(
"mqPageDesc"
);
var toast =
document.getElementById(
"mqToast"
);
/* ============================================================
ICONS
============================================================ */
var ICONS = {
"supply": "<path fill=\"#e5edf1\" stroke=\"none\" d=\"M3 8h12v10H3z\"/><path d=\"M3 8h12v10H3zM15 11h4l3 4v3h-7M19 11v4h3M7 8V4h7v4M10.5 4v4\"/><circle cx=\"7\" cy=\"19\" r=\"2\" fill=\"#fff\"/><circle cx=\"18\" cy=\"19\" r=\"2\" fill=\"#fff\"/><path d=\"M6 12h6m-3-2v4\"/>",
"maintenance": "<rect x=\"2\" y=\"3\" width=\"16\" height=\"12\" rx=\"2\" fill=\"#e5edf1\"/><path d=\"M4 10h3l2-4 3 7 2-3h2M8 15v4m-4 1h9\"/><path d=\"M21 11a4 4 0 0 1-4 5l-4 5-2-2 5-5a4 4 0 0 1 5-3z\" fill=\"#fff\"/>",
"property": "<rect x=\"3\" y=\"4\" width=\"14\" height=\"17\" rx=\"2\" fill=\"#e5edf1\"/><rect x=\"7\" y=\"2\" width=\"6\" height=\"4\" rx=\"1\" fill=\"#fff\"/><path d=\"M6 9h8M6 12h4M6 16h3M6 18h3\"/><path d=\"M14 11h5l3 3-7 7-5-5z\" fill=\"#fff\"/><circle cx=\"17\" cy=\"14\" r=\".8\"/>",
"finance": "<path fill=\"#e5edf1\" d=\"M3 3h13v16H3z\"/><path d=\"M6 15v-4m4 4V8m4 4V5M5 7l4-3 4 1 4-3\"/><ellipse cx=\"18\" cy=\"16\" rx=\"4\" ry=\"2\" fill=\"#fff\"/><path d=\"M14 16v4c0 3 8 3 8 0v-4M14 18c0 3 8 3 8 0\"/>",
"purchase": "<path d=\"M3 4h3l2 12h11l3-9H7\" fill=\"#e5edf1\"/><circle cx=\"10\" cy=\"20\" r=\"1.5\" fill=\"#fff\"/><circle cx=\"18\" cy=\"20\" r=\"1.5\" fill=\"#fff\"/><path d=\"M10 10h8m-4-3v6M3 9H1M4 12H2\"/>",
"newAsset": "<path d=\"M3 8l8-4 8 4-8 4z\" fill=\"#e5edf1\"/><path d=\"M3 8v11l8 4 8-4V8M11 12v11M7 6l8 4\"/><circle cx=\"19\" cy=\"5\" r=\"4\" fill=\"#fff\"/><path d=\"M19 3v4m-2-2h4\"/>",
"edit": "<rect x=\"3\" y=\"3\" width=\"13\" height=\"18\" rx=\"2\" fill=\"#e5edf1\"/><path d=\"M6 7h7M6 11h4M6 15h2\"/><path d=\"M10 18l1-4L20 5l3 3-9 9z\" fill=\"#fff\"/><path d=\"M18 7l3 3M10 18l4-1\"/>",
"consumable": "<path d=\"M3 11h18v11H3z\" fill=\"#e5edf1\"/><path d=\"M8 11V4h5v7M7 4h7M8 7h5M16 11V2h4v9M16 5h4M3 15h18\"/><path d=\"M10 17h4m-2-2v6\"/>"
};
/* ============================================================
TOAST
============================================================ */
var toastTimer = null;
function showToast(message) {
if (!toast) {
return;
}
toast.textContent =
publicMessage(message);
toast.classList.add(
"show"
);
window.clearTimeout(
toastTimer
);
toastTimer =
window.setTimeout(
function () {
toast.classList.remove(
"show"
);
},
2200
);
}
/* ============================================================
BREADCRUMB
============================================================ */
function buildBreadcrumb(items) {
if (!breadcrumb) {
return;
}
var html = "";
items.forEach(function (item, index) {
var isLast = index === items.length - 1;
html +=
'<span class="' +
(isLast ? 'mq-bread-item mq-bread-current' : 'mq-bread-item mq-bread-link') +
'" data-bread-label="' + item + '">' +
item +
'</span>';
if (!isLast) {
html += '<span class="mq-bread-separator">/</span>';
}
});
breadcrumb.innerHTML = html;
var links = breadcrumb.querySelectorAll('.mq-bread-link');
for (var i = 0; i < links.length; i++) {
links[i].onclick = function () {
var label = this.getAttribute('data-bread-label');
if (label === 'تأمین' || label === 'مدیریت تجهیزات') {
renderEquipment();
}
else if (label === 'مدیریت تأمین و لجستیک') {
renderLogistics();
}
else if (label === 'ورود دارایی جدید') {
state.selectedAssetSection = 'purchased';
renderAssetSections('newAsset');
}
else if (label === 'ویرایش دارایی') {
renderEditAssetWorkspace();
}
};
}
}
/* ============================================================
CARD
============================================================ */
function moduleCard(
title,
icon,
action,
clickable
) {
return (
'<div class="mq-module-card" ' +
(
clickable
? 'data-action="' +
action +
'"'
: ''
) +
'>' +
'<div class="mq-module-icon">' +
'<svg viewBox="0 0 24 24">' +
icon +
'</svg>' +
'</div>' +
'<div class="mq-module-name">' +
title +
'</div>' +
(
clickable
? '<div class="mq-module-arrow">‹</div>'
: ''
) +
'</div>'
);
}
/* ============================================================
SCREEN : EQUIPMENT
============================================================ */
function renderEquipment() {
state.screen =
"equipment";
pageTitle.textContent =
"تأمین";
pageDesc.textContent =
"مدیریت فرآیند تأمین تجهیزات پزشکی";
heroTitle.textContent =
"مدیریت تجهیزات";
heroDesc.textContent =
"حوزه موردنظر را انتخاب کنید.";
backButton.style.display =
"none";
buildBreadcrumb(
[
"تأمین",
"مدیریت تجهیزات"
]
);
view.innerHTML =
'<div class="mq-section-head">' +
'<div>' +
'<div class="mq-section-title">' +
'مدیریت تجهیزات' +
'</div>' +
'<div class="mq-section-desc">' +
'یکی از حوزههای مدیریت تجهیزات را انتخاب کنید.' +
'</div>' +
'</div>' +
'</div>' +
'<div class="mq-card-grid">' +
moduleCard(
"مدیریت تأمین و لجستیک",
ICONS.supply,
"logistics",
true
) +
moduleCard(
"مدیریت تعمیر و نگهداری",
ICONS.maintenance,
"",
false
) +
moduleCard(
"مدیریت اموال و داراییها",
ICONS.property,
"",
false
) +
moduleCard(
"مدیریت مالی و بهرهوری",
ICONS.finance,
"",
false
) +
'</div>';
bindActions();
mqTreeActivate("equipment");
}
/* ============================================================
SCREEN : LOGISTICS
============================================================ */
function renderLogistics() {
state.screen =
"logistics";
heroTitle.textContent =
"مدیریت تأمین و لجستیک";
heroDesc.textContent =
"عملیات موردنظر را انتخاب کنید.";
backButton.style.display =
"inline-block";
buildBreadcrumb(
[
"تأمین",
"مدیریت تجهیزات",
"مدیریت تأمین و لجستیک"
]
);
view.innerHTML =
'<div class="mq-section-head">' +
'<div>' +
'<div class="mq-section-title">' +
'مدیریت تأمین و لجستیک' +
'</div>' +
'<div class="mq-section-desc">' +
'عملیات مرتبط با تأمین و لجستیک تجهیزات' +
'</div>' +
'</div>' +
'</div>' +
'<div class="mq-action-grid">' +
actionCard(
"خرید دارایی",
"فرآیند خرید دارایی",
ICONS.purchase,
"purchase"
) +
actionCard(
"ورود دارایی جدید",
"ثبت و تکمیل اطلاعات دارایی جدید",
ICONS.newAsset,
"newAsset"
) +
actionCard(
"ویرایش دارایی",
"مشاهده و ویرایش اطلاعات دارایی موجود",
ICONS.edit,
"editAsset"
) +
actionCard(
"کالاهای مصرفی",
"مدیریت کالاهای مصرفی",
ICONS.consumable,
"consumable"
) +
'</div>';
bindActions();
mqTreeActivate("logistics");
}
function actionCard(
title,
subtitle,
icon,
action
) {
return (
'<div class="mq-action-card" data-action="' +
action +
'">' +
'<div class="mq-action-icon">' +
'<svg viewBox="0 0 24 24">' +
icon +
'</svg>' +
'</div>' +
'<div>' +
'<div class="mq-action-title">' +
title +
'</div>' +
'<div class="mq-action-sub">' +
subtitle +
'</div>' +
'</div>' +
'</div>'
);
}
/* ============================================================
ASSET SECTION SCREEN
============================================================ */
function renderAssetSections(mode) {
state.screen =
mode;
var isNew =
mode ===
"newAsset";
var title =
isNew
? "ورود دارایی جدید"
: "ویرایش دارایی موجود";
heroTitle.textContent =
title;
heroDesc.textContent =
isNew
? "اطلاعات موردنیاز برای ورود دارایی را انتخاب کنید."
: "بخش موردنظر برای ویرایش دارایی را انتخاب کنید.";
backButton.style.display =
"inline-block";
buildBreadcrumb(
[
"تأمین",
"مدیریت تجهیزات",
"مدیریت تأمین و لجستیک",
title
]
);
view.innerHTML =
'<div class="mq-list-layout">' +
'<div class="mq-list-menu">' +
listOption(
"purchased",
"لیست داراییها"
) +
listOption(
"technical",
"شناسنامه فنی"
) +
listOption(
"financial",
"شناسنامه مالی"
) +
listOption(
"maintenance",
"شناسنامه نگهداری و تعمیر"
) +
listOption(
"commercial",
"شناسنامه بازرگانی"
) +
'</div>' +
'<div class="mq-preview">' +
'<div id="mqPreviewContent"></div>' +
'</div>' +
'</div>';
bindSectionOptions();
renderPreview(
state.selectedAssetSection
);
mqTreeActivate(mode + "-" + state.selectedAssetSection);
}
function listOption(
key,
title
) {
return (
'<div ' +
'class="mq-list-option" ' +
'data-section="' +
key +
'">' +
'<span>' +
title +
'</span>' +
'<span class="mq-option-badge">' +
'‹' +
'</span>' +
'</div>'
);
}
/* ============================================================
PREVIEW CONTENT
============================================================ */
var SECTION_NAMES = {
purchased:
"لیست داراییها",
technical:
"شناسنامه فنی",
financial:
"شناسنامه مالی",
maintenance:
"شناسنامه نگهداری و تعمیر",
commercial:
"شناسنامه بازرگانی"
};
/* ============================================================
SIMPLE PRESENTATION PAGES
============================================================ */
function renderSimplePage(
title
) {
heroTitle.textContent =
title;
heroDesc.textContent =
"نمای پرزنت این بخش";
backButton.style.display =
"inline-block";
buildBreadcrumb(
[
"تأمین",
"مدیریت تجهیزات",
"مدیریت تأمین و لجستیک",
title
]
);
view.innerHTML =
'<div class="mq-empty-cycle">' +
'<strong>' +
title +
'</strong>' +
'<span>' +
'این بخش در ادامه فرآیند طراحی تکمیل میشود.' +
'</span>' +
'</div>';
}
/* ============================================================
OTHER LIFE CYCLE TABS
============================================================ */
function renderOtherCycle(
key,
title
) {
state.cycle =
key;
pageTitle.textContent =
title;
pageDesc.textContent =
"چرخه عمر تجهیزات پزشکی";
heroTitle.textContent =
title;
heroDesc.textContent =
"نمای ساختار این بخش";
backButton.style.display =
"none";
buildBreadcrumb(
[
title
]
);
view.innerHTML =
'<div class="mq-empty-cycle">' +
'<strong>' +
title +
'</strong>' +
'<span>' +
'ساختار این بخش در مرحله بعد طراحی میشود.' +
'</span>' +
'</div>';
}
/* ============================================================
BIND MODULE ACTIONS
============================================================ */
function bindActions() {
var elements =
document.querySelectorAll(
"#mediq-dashboard [data-action]"
);
for (
var i = 0;
i < elements.length;
i++
) {
elements[i].onclick =
function () {
var action =
this.getAttribute(
"data-action"
);
if (
action ===
"logistics"
) {
renderLogistics();
}
else if (
action ===
"newAsset"
) {
renderAssetSections(
"newAsset"
);
}
else if (
action ===
"editAsset"
) {
renderEditAssetWorkspace();
}
else if (
action ===
"purchase"
) {
renderSimplePage(
"خرید دارایی"
);
}
else if (
action ===
"consumable"
) {
renderSimplePage(
"کالاهای مصرفی"
);
}
};
}
}
/* ============================================================
SECTION OPTIONS
============================================================ */
function bindSectionOptions() {
var options =
document.querySelectorAll(
"#mediq-dashboard .mq-list-option"
);
for (
var i = 0;
i < options.length;
i++
) {
options[i].onclick =
function () {
renderPreview(
this.getAttribute(
"data-section"
)
);
};
}
}
/* ============================================================
BACK
============================================================ */
if (backButton) {
backButton.onclick =
function () {
if (
state.screen ===
"logistics"
) {
renderEquipment();
}
else if (
state.screen ===
"newAsset" ||
state.screen ===
"editAsset"
) {
renderLogistics();
}
else if (
state.screen === "property" ||
state.screen === "equipmentMaintenance" ||
state.screen === "finance"
) {
renderEquipment();
}
else if (
state.screen === "purchase" ||
state.screen === "consumable"
) {
renderLogistics();
}
else {
renderLogistics();
}
};
}
/* ============================================================
LIFE CYCLE BUTTONS
============================================================ */
var lifeItems =
document.querySelectorAll(
"#mediq-dashboard .mq-life-item"
);
for (
var i = 0;
i < lifeItems.length;
i++
) {
lifeItems[i].onclick =
function () {
var cycle =
this.getAttribute(
"data-cycle"
);
for (
var x = 0;
x < lifeItems.length;
x++
) {
lifeItems[x]
.classList
.remove(
"active"
);
}
this.classList.add(
"active"
);
if (
cycle ===
"supply"
) {
state.cycle =
"supply";
renderEquipment();
}
else if (
cycle ===
"operation"
) {
renderOtherCycle(
"operation",
"بهرهبرداری"
);
}
else if (
cycle ===
"replacement"
) {
renderOtherCycle(
"replacement",
"جایگزینی"
);
}
else if (
cycle ===
"maintenance"
) {
renderOtherCycle(
"maintenance",
"نگهداری"
);
}
};
}
/* ============================================================
LOGOUT
============================================================ */
var logout =
document.getElementById(
"mqLogout"
);
if (logout) {
logout.onclick =
function () {
window.location.href =
"/logout.action";
};
}
/* ============================================================
CURRENT USER / FULL NAME
============================================================ */
(function loadMediQCurrentUser() {
var fallbackUser = "";
try {
if (window.AJS && AJS.Meta) {
fallbackUser = AJS.Meta.get("remote-user") || "";
}
} catch (e) {}
function setWelcomeName(name) {
var welcomeUser = document.getElementById("mqWelcomeUser");
if (welcomeUser && name) {
welcomeUser.textContent = name;
}
/* -------------------------------------------------
Edit page button - use current Confluence page id
------------------------------------------------- */
var editBtn = document.getElementById("mqEditPageBtn");
if (editBtn) {
var currentPageId = "";
try {
if (window.AJS && AJS.Meta) {
currentPageId = AJS.Meta.get("page-id") || "";
}
}
catch (ignorePageMeta) {}
if (!currentPageId) {
try {
currentPageId =
new URL(window.location.href)
.searchParams
.get("pageId") || "";
}
catch (ignorePageUrl) {}
}
if (currentPageId) {
editBtn.href =
"/pages/editpage.action?pageId=" +
encodeURIComponent(currentPageId);
}
}
}
setWelcomeName(fallbackUser || "کاربر مدیکیو");
try {
var xhr = new XMLHttpRequest();
xhr.open("GET", "/rest/api/user/current", true);
xhr.setRequestHeader("Accept", "application/json");
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4 || xhr.status < 200 || xhr.status >= 300) return;
try {
var user = JSON.parse(xhr.responseText || "{}");
setWelcomeName(user.displayName || user.fullName || fallbackUser || "کاربر مدیکیو");
} catch (e) {}
};
xhr.send();
} catch (e) {}
})();
/* ============================================================
SIDEBAR TREE
============================================================ */
function mqTreeOpen(group, open) {
var el = document.querySelector('#mediq-dashboard [data-tree-group="' + group + '"]');
var row = document.querySelector('#mediq-dashboard [data-tree-key="' + group + '"]');
if (el) el.classList.toggle("open", !!open);
if (row) row.classList.toggle("open", !!open);
}
function mqTreeReset() {
var rows = document.querySelectorAll("#mediq-dashboard .mq-tree-row");
for (var i = 0; i < rows.length; i++) {
rows[i].classList.remove("active");
rows[i].classList.remove("parent-active");
}
}
function mqTreeActivate(key) {
mqTreeReset();
var group=key;
if(key==='newAsset'||key==='editAsset'||key==='fixed'||key==='property')group='property';
else if(key==='consumable'||key==='suppliers'||key==='purchase'||key==='logistics')group='logistics';
else if(key==='maintenance'||key==='equipmentMaintenance')group='equipmentMaintenance';
else if(key==='analysis')group='analysis';
var active=document.querySelector('#mediq-dashboard #mqTree [data-tree-key="'+group+'"]');
if(active)active.classList.add('active');
var logisticsOpen=group==='logistics', propertyOpen=group==='property';
var lg=document.querySelector('#mqTree [data-tree-group="logistics"]'),pr=document.querySelector('#mqTree [data-tree-group="property"]');
if(lg)lg.classList.toggle('open',logisticsOpen);
if(pr)pr.classList.toggle('open',propertyOpen);
var sub=key==='suppliers'?'suppliers':key==='consumable'?'consumable':key==='fixed'?'fixed':null;
document.querySelectorAll('#mqTree [data-v32-nav]').forEach(function(el){el.classList.toggle('active',el.getAttribute('data-v32-nav')===sub);});
}
function mqTreeSimpleEquipmentPage(title, key) {
state.screen = key;
pageTitle.textContent = "تأمین";
pageDesc.textContent = "مدیریت فرآیند تأمین تجهیزات پزشکی";
heroTitle.textContent = title;
heroDesc.textContent = "نمای پرزنت این بخش";
backButton.style.display = "inline-block";
buildBreadcrumb(["تأمین", "مدیریت تجهیزات", title]);
view.innerHTML =
'<div class="mq-empty-cycle">' +
'<strong>' + title + '</strong>' +
'<span>این بخش در ادامه فرآیند طراحی تکمیل میشود.</span>' +
'</div>';
mqTreeActivate(key);
}
function bindTree() {
var rows = document.querySelectorAll('#mediq-dashboard #mqTree [data-tree-action]');
rows.forEach(function(row){
row.onclick=function(){
var action=this.getAttribute('data-tree-action');
if(action==='equipmentMaintenance')mqTreeSimpleEquipmentPage('مدیریت تعمیر و نگهداری','equipmentMaintenance');
else if(action==='logistics')renderLogistics();
else if(action==='property')renderAssetSections('newAsset');
else if(action==='finance')mqTreeSimpleEquipmentPage('مدیریت مالی و بهرهوری','finance');
else if(action==='analysis')vAnalysis();
};
});
}
/* ============================================================
MEDIQ CODE-ONLY ENGINE (standalone)
Reads/writes through ScriptRunner REST endpoints only.
============================================================ */
var CTX = "";
try { if (window.AJS && typeof AJS.contextPath === "function") CTX = AJS.contextPath() || ""; } catch (e0) {}
var API = {
read: CTX + "/rest/scriptrunner/latest/custom/mediqGateway",
write: CTX + "/rest/scriptrunner/latest/custom/mediqGatewayWrite",
pages: CTX + "/rest/scriptrunner/latest/custom/mediqEnsureAssetPages"
};
var ATTR = {
groupParent: 6663, titleGroup: 6668, modelTitle: 6626,
manufacturer: 6627, modelType: 6629, modelGroup: 6630,
groupPersian: 6683,
devName: 6265, devId: 6267, assetNo: 6269, purchase: 6271,
supplier: 6272, department: 6277, status: 6279, model: 6644
};
var STATUS_FA = { "active": "فعال", "inactive": "غیرفعال", "entered-in-error": "ثبت اشتباه" };
function $id(id) { return document.getElementById(id); }
function esc(v) {
var amp = String.fromCharCode(38);
return String(v == null ? "" : v).replace(/[&<>"']/g, function (c) {
var entities = {};
entities[String.fromCharCode(38)] = amp + "amp;";
entities[String.fromCharCode(60)] = amp + "lt;";
entities[String.fromCharCode(62)] = amp + "gt;";
entities[String.fromCharCode(34)] = amp + "quot;";
entities[String.fromCharCode(39)] = amp + "#39;";
return entities[c];
});
}
function clean(v) { return String(v == null ? "" : v).trim(); }
function norm(v) { return clean(v).toLowerCase(); }
function jfetch(url, opts) {
opts = opts || {};
opts.credentials = "same-origin";
opts.headers = opts.headers || {};
opts.headers.Accept = "application/json";
return fetch(url, opts).then(function (r) {
return r.text().then(function (raw) {
var data = null;
try { data = raw ? JSON.parse(raw) : {}; }
catch (e) { data = /^\d+$/.test(clean(raw)) ? { ok: true, id: clean(raw) } : { ok: r.ok, raw: raw }; }
if (!r.ok || (data && data.ok === false)) {
var err = new Error((data && data.message) || ("HTTP " + r.status + (raw ? " - " + raw.slice(0, 200) : "")));
err.status = r.status;
throw err;
}
return data || {};
});
});
}
var cache = {};
var mqPendingReads = {};
function apiGet(kind, force) {
if(!force && cache[kind]) return Promise.resolve(cache[kind]);
if(!force && mqPendingReads[kind]) return mqPendingReads[kind];
function batch(offset,items){
return jfetch(API.read+"?kind="+encodeURIComponent(kind)+"&limit=500&offset="+offset,{method:"GET"}).then(function(x){
var next=x.items || [];items=items.concat(next);
if(x.hasMore){
if(!next.length) throw new Error("دریافت فهرست کامل نشد.");
return batch(offset+next.length,items);
}
cache[kind]=items;return items;
});
}
var promise=batch(0,[]);
mqPendingReads[kind]=promise;
var clearPending=function(){if(mqPendingReads[kind]===promise) delete mqPendingReads[kind];};
promise.then(clearPending,clearPending);
return promise;
}
function apiWrite(op, payload) {
return jfetch(API.write + "?operation=" + encodeURIComponent(op), {
method: "POST",
headers: { "Content-Type": "application/json; charset=UTF-8", "X-Atlassian-Token": "no-check" },
body: JSON.stringify(payload || {})
});
}
function apiPages(payload) {
return jfetch(API.pages, {
method: "POST",
headers: { "Content-Type": "application/json; charset=UTF-8", "X-Atlassian-Token": "no-check" },
body: JSON.stringify(payload || {})
});
}
function attrList(row, id) {
if (!row || !row.attributes) return [];
var v = row.attributes[String(id)];
if (v == null) return [];
return Array.isArray(v) ? v.map(String) : [String(v)];
}
function attr(row, id) { var l = attrList(row, id); return l.length ? l[0] : ""; }
function findRow(kind, id) {
var rows = cache[kind] || [];
for (var i = 0; i < rows.length; i++) if (String(rows[i].id) === String(id)) return rows[i];
return null;
}
function labelOf(row) { return row ? (row.label || row.key || row.id) : ""; }
function groupLabel(row) {
var p = attr(row, ATTR.groupPersian);
return p ? (row.key ? row.key + " - " + p : p) : labelOf(row);
}
/* ---------------- Assets list / detail ---------------- */
function statusText(v) {
v = clean(v);
if (!v) return "—";
if (STATUS_FA[norm(v)]) return STATUS_FA[norm(v)];
return /^\d+$/.test(v) ? "—" : v;
}
var ASSET_PAGE = { page:1, size:"10", request:0 };
function filterAssetItems(items,query){
query=searchNorm(query);
return items.filter(function(row){
if(!query) return true;
var values=[row.key,row.label,row.id,statusText(attr(row,ATTR.status))];
Object.keys(row.attributes || {}).forEach(function(k){values=values.concat(attrList(row,k));});
return searchNorm(values.join(" ")).indexOf(query)>=0;
});
}
function searchNorm(value){
return latinDigits(value).replace(/ي/g,"ی").replace(/ك/g,"ک").toLowerCase().replace(/\s+/g," ").trim();
}
function assetPageSlice(items,page,size){
var count=size==="all"?Math.max(items.length,1):Number(size), pages=Math.max(1,Math.ceil(items.length/count));
page=Math.min(Math.max(1,page),pages);
return {items:items.slice((page-1)*count,page*count),page:page,pages:pages,start:items.length?(page-1)*count+1:0,end:Math.min(page*count,items.length)};
}
function loadAssets(hostId, searchId) {
var host=$id(hostId); if(!host) return;
var request=++ASSET_PAGE.request;
host.innerHTML='<div class="wz-loading">در حال دریافت اطلاعات داراییها...</div>';
apiGet("equipment",true).then(function(items){
if(request!==ASSET_PAGE.request || !$id(hostId)) return;
var input=searchId?$id(searchId):null;
function paint(){
host=$id(hostId);if(!host) return;
var filtered=filterAssetItems(items,input?input.value:""), part=assetPageSlice(filtered,ASSET_PAGE.page,ASSET_PAGE.size);
ASSET_PAGE.page=part.page;
host.innerHTML='<div class="mq-tbl-wrap"><table class="mq-tbl"><thead><tr><th>شناسه دستگاه</th><th>نام دستگاه</th><th>شماره اموال</th><th>وضعیت</th><th>عملیات</th></tr></thead><tbody>'+part.items.map(function(o){
return '<tr><td>'+esc(attr(o,ATTR.devId)||o.key||o.id)+'</td><td>'+esc(attr(o,ATTR.devName)||o.label||"—")+'</td><td>'+esc(attr(o,ATTR.assetNo)||"—")+'</td><td>'+esc(statusText(attr(o,ATTR.status)))+'</td><td><button type="button" class="mq-assets-btn" data-detail="'+esc(o.id)+'">مشاهده</button></td></tr>';
}).join("")+(filtered.length?'':'<tr><td colspan="5">موردی یافت نشد.</td></tr>')+'</tbody></table></div>'+
'<div class="mq-list-controls"><label>تعداد نمایش <select id="mqPageSize">'+["10","20","50","all"].map(function(n){return '<option value="'+n+'"'+(n===ASSET_PAGE.size?' selected':'')+'>'+(n==="all"?'همه':n)+'</option>';}).join("")+'</select></label><span>'+part.start+' تا '+part.end+' از '+filtered.length+' نتیجه — کل داراییها: '+items.length+'</span></div>'+
'<div class="mq-list-controls"><button type="button" class="mq-assets-btn" id="mqPagePrev"'+(part.page===1?' disabled':'')+'>قبلی</button><span>صفحه '+part.page+' از '+part.pages+'</span><button type="button" class="mq-assets-btn" id="mqPageNext"'+(part.page===part.pages?' disabled':'')+'>بعدی</button></div>';
$id("mqPageSize").onchange=function(){ASSET_PAGE.size=this.value;ASSET_PAGE.page=1;paint();};
$id("mqPagePrev").onclick=function(){ASSET_PAGE.page--;paint();};
$id("mqPageNext").onclick=function(){ASSET_PAGE.page++;paint();};
}
if(input)input.oninput=function(){ASSET_PAGE.page=1;paint();};
paint();
}).catch(function(e){if(request===ASSET_PAGE.request && $id(hostId))$id(hostId).innerHTML='<div class="mq-assets-message">خطا در دریافت اطلاعات: '+esc(publicMessage(e.message))+'</div>';});
}
function refName(kind, id) {
id = clean(id);
if (!id) return "—";
var r = findRow(kind, id);
return r ? labelOf(r) : id;
}
function openDetail(id) {
var row = findRow("equipment", id);
if (!row) return;
var box = $id("mqDetailBody");
$id("mqDetailTitle").textContent = attr(row, ATTR.devName) || labelOf(row);
box.innerHTML = '<div class="wz-loading">در حال بارگذاری...</div>';
$id("mqDetail").classList.add("open");
Promise.all([
apiGet("supplier").catch(function () { return []; }),
apiGet("department"),
loadExtraEquipment(),
apiGet("models").catch(function () { return []; })
]).then(function () {
var data = [
["شناسه دستگاه", attr(row, ATTR.devId)],
["نام دستگاه", attr(row, ATTR.devName)],
["مدل", refName("models", attr(row, ATTR.model))],
["شماره اموال", attr(row, ATTR.assetNo)],
["تاریخ خرید", displayJalali(attr(row, ATTR.purchase), false)],
["فروشنده", refName("supplier", attr(row, ATTR.supplier))],
["بخش بهرهبردار", refName("department", attr(row, ATTR.department))],
["وضعیت", statusText(attr(row, ATTR.status))],
["کد سامانه", row.key]
];
EQUIPMENT_FIELDS.forEach(function(f){
var values=attrList(row,f[0]);
if(f[3]==="ref") values=values.map(function(x){return refName(f[4],x);});
if(f[3]==="boolean") values=values.map(function(x){return x==="true"?"بله":x==="false"?"خیر":x;});
if(f[3] === "date" || f[3] === "datetime-local") values=values.map(function(v){return displayJalali(v,f[3] === "datetime-local");});
data.push([f[2],values.join("، ")]);
});
box.innerHTML = data.map(function (d) {
return '<div class="dt-row"><span>' + esc(d[0]) + "</span><span>" + esc(d[1] || "—") + "</span></div>";
}).join("");
});
}
function closeDetail() { $id("mqDetail").classList.remove("open"); }
function renderEditAssetWorkspace() {
state.selectedAssetSection = "purchased";
renderAssetSections("editAsset");
}
function renderPreview(section) {
state.selectedAssetSection = section;
if (state.screen === "newAsset" || state.screen === "editAsset") mqTreeActivate(state.screen + "-" + section);
var box = $id("mqPreviewContent");
if (!box) return;
var title = SECTION_NAMES[section] || "شناسنامه";
var isNew = state.screen === "newAsset";
if (section === "purchased") {
box.innerHTML =
'<div class="mq-preview-title">لیست داراییها</div>' +
'<div class="mq-preview-description">داراییهای ثبتشده در سامانه</div>' +
'<div class="mq-assets-head">' +
'<input id="mqAssetSearch" class="mq-edit-search" type="search" placeholder="جستجو در داراییها…" aria-label="جستجو در داراییها">' +
'<div class="mq-assets-actions">' +
'<button type="button" class="mq-assets-btn" id="mqAssetsRefresh">بهروزرسانی لیست</button>' +
(isNew ? '<button type="button" class="mq-assets-btn primary" id="mqAssetsNew">ثبت دارایی جدید</button>' : "") +
"</div></div>" +
'<div id="mqAssetsHost" class="mq-assets-host"></div>';
var nb = $id("mqAssetsNew"); if (nb) nb.onclick = openWizard;
$id("mqAssetsRefresh").onclick = function () { loadAssets("mqAssetsHost", "mqAssetSearch"); };
loadAssets("mqAssetsHost", "mqAssetSearch");
} else {
box.innerHTML =
'<div class="mq-preview-title">' + esc(title) + "</div>" +
'<div class="mq-preview-description">این بخش در حال آمادهسازی است.</div>' +
'<div class="mq-demo-box"><div class="mq-demo-icon">✓</div><div class="mq-demo-text">' + esc(title) + "</div></div>";
}
var opts = document.querySelectorAll("#mediq-dashboard .mq-list-option");
for (var i = 0; i < opts.length; i++) opts[i].classList.toggle("active", opts[i].getAttribute("data-section") === section);
}
/* ---------------- Registration wizard ---------------- */
var W = { open: false, step: 0, busy: false, token: 0, sel: { group: "", title: "", model: "" }, draft: {} };
var STEPS = [
{ key: "group", kind: "groups", noun: "گروه",
filter: function (r) { return true; }, label: groupLabel },
{ key: "title", kind: "titles", noun: "عنوان دستگاه",
filter: function (r) { return !W.sel.group || attrList(r, ATTR.titleGroup).indexOf(String(W.sel.group)) >= 0; }, label: labelOf },
{ key: "model", kind: "models", noun: "مدل",
filter: function (r) { return !W.sel.title || attrList(r, ATTR.modelTitle).indexOf(String(W.sel.title)) >= 0; }, label: labelOf }
];
var STEP_NAMES = ["گروه", "عنوان دستگاه", "مدل", "دستگاه"];
function publicMessage(value){
return String(value == null ? "" : value).replace(/Jira\s*Assets?/gi,"سامانه داراییها").replace(/Confluence/gi,"سامانه مستندات").replace(/ScriptRunner/gi,"سرویس").replace(/\bAssets?\b/gi,"دارایی").replace(/\bJira\b/gi,"سامانه").replace(/جیرا|کانفلوئنس/g,"سامانه").replace(/\bEndpoint\b/gi,"سرویس");
}
function wzMsg(text, isErr) {
var el = $id("wzMsg");
if (!el) return;
el.textContent = publicMessage(text);
el.className = "wz-msg" + (isErr ? " err" : "");
}
function wzBusy(flag) {
W.busy = !!flag;
var b = document.querySelectorAll("#mqWz button:not(.wz-close)");
for (var i = 0; i < b.length; i++) b[i].disabled = !!flag;
if (!flag) wzHeader();
}
function wzHeader() {
$id("wzTitle").textContent = W.step === 3 ? "ثبت دستگاه" : "انتخاب " + STEP_NAMES[W.step];
$id("wzSteps").innerHTML = STEP_NAMES.map(function (n, i) {
var c = i === W.step ? " active" : (i < W.step ? " done" : "");
var chosen = i < 3 ? findRow(STEPS[i].kind,W.sel[STEPS[i].key]) : null;
var chosenLabel = chosen ? STEPS[i].label(chosen) : (i === 3 ? clean(W.draft.deviceId) : "");
return '<div class="wz-step' + c + '"><div class="wz-step-heading"><b>'+(i+1)+'</b><span>'+esc(n)+'</span></div><small class="wz-step-value" title="'+esc(chosenLabel)+'">'+esc(chosenLabel || "—")+'</small></div>';
}).join("");
var prev = $id("wzPrev"), next = $id("wzNext");
prev.style.visibility = W.step === 0 ? "hidden" : "visible";
next.textContent = W.step === 3 ? "ثبت دستگاه" : "مرحله بعد";
}
function openWizard() {
W.open = true; W.step = 0; W.busy = false;
W.sel = { group: "", title: "", model: "" }; W.draft = {}; W.segment=0;
$id("mqWz").classList.add("open");
$id("mqWz").setAttribute("aria-hidden", "false");
wzPaint();
}
function closeWizard() {
mqCloseDatePopover();
W.open = false;
$id("mqWz").classList.remove("open");
$id("mqWz").setAttribute("aria-hidden", "true");
}
var JALALI_FORMAT = new Intl.DateTimeFormat("en-US-u-ca-persian-nu-latn",{year:"numeric",month:"numeric",day:"numeric",timeZone:"UTC"});
var JALALI_MONTHS=["فروردین","اردیبهشت","خرداد","تیر","مرداد","شهریور","مهر","آبان","آذر","دی","بهمن","اسفند"];
function latinDigits(value){return String(value==null?"":value).replace(/[۰-۹]/g,function(c){return String(c.charCodeAt(0)-1776);}).replace(/[٠-٩]/g,function(c){return String(c.charCodeAt(0)-1632);});}
function jalaliToday(){var d=new Date();return persianParts(new Date(Date.UTC(d.getFullYear(),d.getMonth(),d.getDate())));}
function padDate(n){return String(n).padStart(2,"0");}
function persianParts(date){var p={};JALALI_FORMAT.formatToParts(date).forEach(function(x){if(x.type!=="literal")p[x.type]=Number(x.value);});return {y:p.year,m:p.month,d:p.day};}
function jalaliToISO(y,m,d){
if(y<1200 || y>1600 || m<1 || m>12 || d<1 || d>31)throw new Error("تاریخ شمسی معتبر نیست.");
var low=Math.floor(Date.UTC(y+621,0,1)/86400000),high=Math.floor(Date.UTC(y+623,0,1)/86400000),target=y*10000+m*100+d;
while(low<=high){var middle=Math.floor((low+high)/2),date=new Date(middle*86400000),p=persianParts(date),key=p.y*10000+p.m*100+p.d;
if(key===target)return date.toISOString().slice(0,10);
if(key<target)low=middle+1;else high=middle-1;
}
throw new Error("روز انتخابشده در این ماه وجود ندارد.");
}
function parseJalali(value,withTime){
var raw=latinDigits(value).trim();if(!raw)return "";
var match=raw.match(/^(\d{4})[\/\-](\d{1,2})[\/\-](\d{1,2})(?:[ T]+(\d{1,2}):(\d{2})(?::(\d{2}))?)?$/);
if(!match)throw new Error(withTime?"تاریخ و ساعت را مانند ۱۴۰۵/۰۷/۲۸ ۱۴:۳۰ وارد کنید.":"تاریخ را مانند ۱۴۰۵/۰۷/۲۸ وارد کنید.");
var iso=jalaliToISO(Number(match[1]),Number(match[2]),Number(match[3]));
if(withTime){var hh=Number(match[4]||0),mm=Number(match[5]||0),ss=Number(match[6]||0);if(hh>23 || mm>59 || ss>59)throw new Error("ساعت معتبر نیست.");return iso+"T"+padDate(hh)+":"+padDate(mm)+":"+padDate(ss);}
if(match[4]!=null)throw new Error("این فیلد فقط تاریخ میپذیرد.");
return iso;
}
function displayJalali(value,withTime){
var raw=latinDigits(value).trim();if(!raw)return "";
var match=raw.match(/^(\d{4})[-\/](\d{1,2})[-\/](\d{1,2})(?:[ T](\d{2}):(\d{2}))?/);
if(!match)return raw;
if(Number(match[1])<1700)return raw.replace(/-/g,"/");
var date=new Date(Date.UTC(Number(match[1]),Number(match[2])-1,Number(match[3]))),p=persianParts(date);
return p.y+"/"+padDate(p.m)+"/"+padDate(p.d)+(withTime?" "+(match[4]||"00")+":"+(match[5]||"00"):"");
}
function jalaliField(id,label,value,withTime,required){
return '<div class="wz-field mq-jdate"><label for="'+id+'">'+esc(label)+(required?' *':'')+'</label><div class="wz-inline"><input type="text" dir="ltr" id="'+id+'" data-jalali="'+(withTime?'time':'date')+'" value="'+esc(displayJalali(value,withTime))+'" placeholder="'+(withTime?'۱۴۰۵/۰۷/۲۸ ۱۴:۳۰':'۱۴۰۵/۰۷/۲۸')+'" autocomplete="off"><button type="button" class="wz-plus" data-jcalendar="'+id+'" aria-label="انتخاب تاریخ شمسی">▦</button></div><div class="mq-jcalendar" id="'+id+'Calendar" hidden></div></div>';
}
function gregorianInput(id,withTime){var el=$id(id);return el?parseJalali(el.value,withTime):"";}
function validateJalaliInputs(){
var inputs=document.querySelectorAll('#wzBody [data-jalali]');
for(var i=0;i<inputs.length;i++)try{parseJalali(inputs[i].value,inputs[i].dataset.jalali==="time");inputs[i].setCustomValidity("");}catch(e){inputs[i].setCustomValidity(e.message);revealEquipmentField(inputs[i]);inputs[i].focus();wzMsg(e.message,true);return false;}
return true;
}
var MQ_DATE_POPOVER = null;
function mqDatePopoverRect(anchor,width,height,bounds){
var gap=7,pad=10,leftEdge=bounds.left+pad,rightEdge=bounds.right-pad,topEdge=bounds.top+pad,bottomEdge=bounds.bottom-pad;
var available=Math.max(1,bottomEdge-topEdge),shownHeight=Math.min(height,available);
var below=bottomEdge-anchor.bottom-gap,above=anchor.top-gap-topEdge;
var top=anchor.bottom+gap;
if(below<shownHeight && above>=shownHeight)top=anchor.top-gap-shownHeight;
// If neither side fits, overlap the fields while retaining the full calendar height.
top=Math.max(topEdge,Math.min(top,bottomEdge-shownHeight));
return {left:Math.max(leftEdge,Math.min(anchor.right-width,rightEdge-width)),top:top,maxHeight:available};
}
function mqPositionDatePopover(){
var active=MQ_DATE_POPOVER;if(!active)return;
if(!active.anchor.isConnected || !active.box.isConnected){mqCloseDatePopover();return;}
var body=active.anchor.closest("#vEditBody") || $id("wzBody"),area=body.getBoundingClientRect();
var bounds={left:Math.max(0,area.left),right:Math.min(window.innerWidth,area.right),top:Math.max(0,area.top),bottom:Math.min(window.innerHeight,area.bottom)};
var width=Math.min(330,Math.max(1,bounds.right-bounds.left-20));
active.box.style.width=width+"px";
active.box.style.maxHeight="none";
var field=active.anchor.closest(".wz-inline") || active.anchor;
var rect=mqDatePopoverRect(field.getBoundingClientRect(),width,active.box.scrollHeight+2,bounds);
active.box.style.left=rect.left+"px";active.box.style.top=rect.top+"px";active.box.style.maxHeight=rect.maxHeight+"px";
}
function mqCloseDatePopover(){
var active=MQ_DATE_POPOVER;if(!active)return;MQ_DATE_POPOVER=null;
active.box.hidden=true;active.box.classList.remove("mq-date-floating");
active.box.removeAttribute("style");active.anchor.setAttribute("aria-expanded","false");
if(active.parent.isConnected)active.parent.appendChild(active.box);else active.box.remove();
}
function bindJalaliInputs(){
document.querySelectorAll('#wzBody [data-jcalendar],#vEditBody [data-jcalendar]').forEach(function(button){
button.setAttribute("aria-expanded","false");button.setAttribute("aria-controls",button.dataset.jcalendar+"Calendar");
button.onclick=function(){
var id=this.dataset.jcalendar,box=$id(id+'Calendar'),same=MQ_DATE_POPOVER && MQ_DATE_POPOVER.box===box;
mqCloseDatePopover();if(same)return;
var p=jalaliToday(),raw=latinDigits($id(id).value),match=raw.match(/^(\d{4})\/(\d{1,2})/);
if(match && Number(match[1])>=1200 && Number(match[1])<=1600 && Number(match[2])>=1 && Number(match[2])<=12){p.y=Number(match[1]);p.m=Number(match[2]);}
MQ_DATE_POPOVER={box:box,anchor:this,parent:box.parentNode};
box.classList.add("mq-date-floating");(this.closest("#vDialog") ? this.closest(".v-dialog") : $id("mqWz")).appendChild(box);
box.hidden=false;this.setAttribute("aria-expanded","true");
paintJalaliCalendar(id,p.y,p.m);mqPositionDatePopover();
box.onclick=function(){if(box.hidden)mqCloseDatePopover();else mqPositionDatePopover();};
};
});
}
document.addEventListener("pointerdown",function(e){var active=MQ_DATE_POPOVER;if(active && !active.box.contains(e.target) && !active.anchor.contains(e.target))mqCloseDatePopover();},true);
document.addEventListener("keydown",function(e){if(e.key==="Escape" && MQ_DATE_POPOVER){mqCloseDatePopover();e.preventDefault();e.stopImmediatePropagation();}},true);
document.addEventListener("scroll",function(e){var active=MQ_DATE_POPOVER;if(active && !active.box.contains(e.target))mqCloseDatePopover();},true);
window.addEventListener("resize",mqPositionDatePopover);
function paintJalaliCalendar(id,y,m){
var box=$id(id+'Calendar'),first=new Date(jalaliToISO(y,m,1)+"T00:00:00Z"),offset=(first.getUTCDay()+1)%7,days=m<=6?31:30;
if(m===12){try{jalaliToISO(y,12,30);}catch(e){days=29;}}
box.innerHTML='<div class="mq-jcal-head"><button type="button" data-month="-1">ماه قبل</button><b>'+JALALI_MONTHS[m-1]+' '+y+'</b><button type="button" data-month="1">ماه بعد</button></div><div class="mq-jcal-grid">'+["ش","ی","د","س","چ","پ","ج"].map(function(x){return '<span>'+x+'</span>';}).join("")+Array(offset).fill('<span></span>').join("")+Array.from({length:days},function(_,i){return '<button type="button" data-day="'+(i+1)+'">'+(i+1)+'</button>';}).join("")+'</div><button type="button" data-today>امروز</button> <button type="button" data-clear>پاک کردن</button>';
box.querySelectorAll('[data-month]').forEach(function(b){b.onclick=function(){var next=m+Number(this.dataset.month),year=y;if(next<1){next=12;year--;}if(next>12){next=1;year++;}if(year>=1200 && year<=1600)paintJalaliCalendar(id,year,next);};});
function select(p){var el=$id(id),time=latinDigits(el.value).match(/[ T](\d{1,2}:\d{2}(?::\d{2})?)$/);el.value=p.y+'/'+padDate(p.m)+'/'+padDate(p.d)+(el.dataset.jalali==='time'?' '+(time?time[1]:'00:00'):'');el.setCustomValidity('');box.hidden=true;el.dispatchEvent(new Event('input',{bubbles:true}));el.dispatchEvent(new Event('change',{bubbles:true}));}
box.querySelectorAll('[data-day]').forEach(function(b){b.onclick=function(){select({y:y,m:m,d:Number(this.dataset.day)});};});
box.querySelector('[data-today]').onclick=function(){select(jalaliToday());};
box.querySelector('[data-clear]').onclick=function(){var el=$id(id);el.value='';el.setCustomValidity('');el.dispatchEvent(new Event('input',{bubbles:true}));el.dispatchEvent(new Event('change',{bubbles:true}));box.hidden=true;};
}
function field(id, label, value, type, req) {
if (type === "date" || type === "datetime-local") return jalaliField(id,label,value,type === "datetime-local",req);
return '<div class="wz-field"><label for="' + id + '">' + esc(label) + (req ? " *" : "") + '</label><input id="' + id + '" type="' + (type || "text") + '" value="' + esc(value || "") + '"></div>';
}
function selectOptions(rows, selected, labelFn) {
return '<option value="">انتخاب کنید</option>' + rows.map(function (r) {
return '<option value="' + esc(r.id) + '"' + (String(r.id) === String(selected) ? " selected" : "") + ">" + esc((labelFn || labelOf)(r)) + "</option>";
}).join("");
}
function selectField(id, label, rows, selected, req, withPlus) {
return '<div class="wz-field"><label for="' + id + '">' + esc(label) + (req ? " *" : "") + "</label>" +
(withPlus ? '<div class="wz-inline"><select id="' + id + '">' + selectOptions(rows, selected) + '</select><button type="button" class="wz-plus" data-plus="' + id + '" title="ثبت جدید" aria-label="ثبت جدید">+</button></div>' +
'<div class="wz-mini" id="' + id + 'Mini" hidden><input type="text" id="' + id + 'MiniName" placeholder="نام جدید"><button type="button" class="wz-primary" data-miniok="' + id + '">ثبت</button></div>'
: '<select id="' + id + '">' + selectOptions(rows, selected) + "</select>") +
"</div>";
}
function wzPaint() {
mqCloseDatePopover();
wzHeader();
var body = $id("wzBody");
var token = ++W.token;
wzMsg("");
if (W.step === 3) return paintEquipment(token);
body.innerHTML = '<div class="wz-loading">در حال دریافت اطلاعات...</div>';
var cfg = STEPS[W.step];
var need = [apiGet(cfg.kind)];
if (W.step === 0) need.push(Promise.resolve([]));
Promise.all(need).then(function (v) {
if (token !== W.token) return;
var all = v[0], rows = all.filter(cfg.filter);
var html =
'<div class="wz-label">' + esc(cfg.noun) + "</div>" +
'<div class="wz-selected" id="wzSel"></div>' +
'<div class="wz-picker" id="wzPicker"><input class="wz-search" id="wzSearch" type="text" placeholder="جستجو..." autocomplete="off"><div class="wz-list" id="wzList"></div></div>' +
'<button type="button" class="wz-link" id="wzToggle">+ ثبت ' + esc(cfg.noun) + " جدید</button>" +
'<div class="wz-create" id="wzCreate" hidden>' + createHtml(cfg) + "</div>";
body.innerHTML = html;
drawPicker(cfg, rows, "");
$id("wzSearch").oninput = function () { drawPicker(cfg, rows, this.value); };
$id("wzList").onclick = function (e) {
var toggle=e.target.closest("[data-group-toggle]");
if(toggle){var groupId=toggle.getAttribute("data-group-toggle");GROUP_COLLAPSED[groupId]=!GROUP_COLLAPSED[groupId];drawPicker(cfg,rows,$id("wzSearch").value);return;}
if(W.busy)return;
var b = e.target.closest(".wz-item"); if (!b) return;
W.sel[cfg.key] = b.getAttribute("data-id");
if (cfg.key === "group") { W.sel.title = ""; W.sel.model = ""; }
if (cfg.key === "title") { W.sel.model = ""; }
drawPicker(cfg, rows, $id("wzSearch").value);
wzHeader();
};
$id("wzToggle").onclick = function () {
var c = $id("wzCreate"); c.hidden = !c.hidden;
if (!c.hidden) { var f = c.querySelector("input,select"); if (f) f.focus(); }
};
bindCreate(cfg);
}).catch(function (e) { if (token === W.token) { body.innerHTML = ""; wzMsg(e.message, true); } });
}
var GROUP_COLLAPSED = {};
function groupTreeData(rows){
var byId=Object.create(null), parent=Object.create(null), children=Object.create(null), roots=[];
rows.forEach(function(r){byId[String(r.id)]=r;children[String(r.id)]=[];});
rows.forEach(function(r){
var id=String(r.id),p=attr(r,ATTR.groupParent),seen={};
while(p && byId[p] && !seen[p]){seen[p]=true;p=attr(byId[p],ATTR.groupParent);}
var direct=attr(r,ATTR.groupParent);
if(!direct || !byId[direct] || seen[id] || (p && seen[p]))direct="";
parent[id]=direct;
if(direct)children[direct].push(r);else roots.push(r);
});
return {byId:byId,parent:parent,children:children,roots:roots};
}
function renderGroupTree(rows,query,selected){
var tree=groupTreeData(rows),q=searchNorm(query),keep=Object.create(null);
rows.forEach(function(r){if(!q || searchNorm(groupLabel(r)).indexOf(q)>=0){var id=String(r.id),seen={};while(id && !seen[id]){seen[id]=true;keep[id]=true;id=tree.parent[id];}}});
function render(nodes){return nodes.filter(function(r){return keep[String(r.id)];}).map(function(r){
var id=String(r.id),kids=tree.children[id].filter(function(x){return keep[String(x.id)];}),closed=!q && GROUP_COLLAPSED[id],has=kids.length>0;
return '<li role="treeitem" aria-selected="'+(String(selected)===id?'true':'false')+'"'+(has?' aria-expanded="'+(!closed)+'"':'')+'><div class="wz-tree-line">'+
(has?'<button type="button" class="wz-tree-toggle" data-group-toggle="'+esc(id)+'" aria-label="'+(closed?'باز کردن':'بستن')+' '+esc(groupLabel(r))+'">'+(closed?'+':'−')+'</button>':'<span class="wz-tree-spacer"></span>')+
'<button type="button" class="wz-item'+(String(selected)===id?' sel':'')+'" data-id="'+esc(id)+'">'+esc(groupLabel(r))+'</button></div>'+
(has && !closed?'<ul role="group">'+render(kids)+'</ul>':'')+'</li>';
}).join("");}
var body=render(tree.roots);
return body?'<ul class="wz-group-tree" role="tree" aria-label="درخت گروهها">'+body+'</ul>':'<div class="wz-empty">گروهی یافت نشد.</div>';
}
function drawPicker(cfg, rows, q) {
var list = $id("wzList"); if (!list) return;
q = norm(q);
var sel = W.sel[cfg.key], html = "", n = 0;
rows.forEach(function (r) {
var l = cfg.label(r);
if (q && norm(l).indexOf(q) < 0) return;
n++;
html += '<button type="button" class="wz-item' + (String(r.id) === String(sel) ? " sel" : "") + '" data-id="' + esc(r.id) + '">' + esc(l) + "</button>";
});
list.innerHTML = cfg.key === "group" ? renderGroupTree(rows,q,sel) : n ? html : '<div class="wz-empty">' + (rows.length ? "موردی با این عبارت پیدا نشد." : "موردی برای نمایش وجود ندارد؛ از دکمهی ثبت جدید استفاده کنید.") + "</div>";
var box = $id("wzSel"), cur = findRow(cfg.kind, sel);
box.className = "wz-selected" + (cur ? " has" : "");
box.textContent = cur ? "انتخابشده: " + cfg.label(cur) : "هنوز " + cfg.noun + "ی انتخاب نشده است.";
}
function groupParentOptions(groups){
var tree=groupTreeData(groups),out=[];
function walk(rows,path){rows.forEach(function(r){var parts=path.concat([attr(r,ATTR.groupPersian)||labelOf(r)]);out.push({id:r.id,label:parts.join(" / ")});walk(tree.children[String(r.id)],parts);});}
walk(tree.roots,[]);return out;
}
function createHtml(cfg) {
if (cfg.key === "group") {
var groups = cache.groups || [];
return "<strong>ثبت گروه جدید</strong>" + field("wzName", "نام گروه", "", "text", true) +
selectField("wzParent", "گروه والد", groupParentOptions(groups), "", false, false) +
'<button type="button" class="wz-primary" id="wzCreateBtn">ثبت و انتخاب گروه</button>';
}
if (cfg.key === "title") {
return "<strong>ثبت عنوان دستگاه جدید</strong>" + field("wzName", "عنوان دستگاه", "", "text", true) +
'<div class="wz-static">گروه: ' + esc(groupLabel(findRow("groups", W.sel.group) || {})) + "</div>" +
'<button type="button" class="wz-primary" id="wzCreateBtn">ثبت و انتخاب عنوان دستگاه</button>';
}
return '<strong>ثبت مدل جدید</strong><div class="wz-loading" id="wzModelLoading">در حال بارگذاری فرم...</div><div id="wzModelForm"></div>';
}
function bindCreate(cfg) {
var btn = $id("wzCreateBtn");
if (cfg.key === "group" && btn) btn.onclick = createGroup;
if (cfg.key === "title" && btn) btn.onclick = createTitle;
var nameInput = $id("wzName");
if (nameInput) nameInput.onkeydown = function (e) { if (e.key === "Enter") { e.preventDefault(); (cfg.key === "group" ? createGroup : createTitle)(); } };
if (cfg.key === "model") loadModelForm();
}
function afterCreate(kind, selKey, id, okText) {
delete cache[kind];
return apiGet(kind,true).then(function(){
W.sel[selKey]=String(id);
if(selKey === "group"){W.sel.title="";W.sel.model="";W.step=1;}
if(selKey === "title"){W.sel.model="";W.step=2;}
if(selKey !== "model")wzPaint();
else wzHeader();
});
}
function createGroup() {
if (W.busy) return;
var name = clean($id("wzName").value);
if (!name) return wzMsg("نام گروه الزامی است.", true);
var parent = $id("wzParent").value, values = {};
values[String(ATTR.groupPersian)] = name;
if (parent) values[String(ATTR.groupParent)] = parent;
wzBusy(true); wzMsg("در حال ثبت گروه...");
apiWrite("reference", { sourceAttributeId: ATTR.modelGroup, name: name, values: values })
.then(function (r) { return afterCreate("groups", "group", r.id, "گروه ثبت شد."); })
.catch(function (e) { wzMsg(e.message, true); })
.then(function () { wzBusy(false); });
}
function createTitle() {
if (W.busy) return;
if (!W.sel.group) return wzMsg("ابتدا گروه را انتخاب کنید.", true);
var name = clean($id("wzName").value);
if (!name) return wzMsg("عنوان دستگاه الزامی است.", true);
var values = {}; values[String(ATTR.titleGroup)] = W.sel.group;
wzBusy(true); wzMsg("در حال ثبت عنوان دستگاه...");
apiWrite("reference", { sourceAttributeId: ATTR.modelTitle, name: name, values: values })
.then(function (r) { return afterCreate("titles", "title", r.id, "عنوان دستگاه ثبت شد."); })
.catch(function (e) { wzMsg(e.message, true); })
.then(function () { wzBusy(false); });
}
function loadModelForm() {
Promise.all([apiGet("manufacturer"), apiGet("facility")]).then(function (v) {
var host = $id("wzModelForm"); if (!host) return;
var ld = $id("wzModelLoading"); if (ld) ld.parentNode.removeChild(ld);
host.innerHTML = '<div class="wz-grid">' +
selectField("wzManufacturer", "شرکت سازنده", v[0], "", true, true) +
selectField("wzFacility", "نوع", v[1], "", false, true) +
field("wzNature", "ماهیت دستگاه", "") +
field("wzFunction", "کارکرد", "") +
field("wzCriticality", "سطح اهمیت", "") +
field("wzTechnology", "فناوری", "") +
field("wzPower", "برق مصرفی", "") +
field("wzWater", "آب مصرفی", "") +
field("wzGas", "گاز مصرفی", "") +
'<div class="wz-field"><label for="wzAvatar">آواتار مدل (PNG/JPEG، حداکثر ۲ مگابایت)</label><input type="file" id="wzAvatar" accept="image/png,image/jpeg"><img id="wzAvatarPreview" hidden style="width:80px;height:80px;object-fit:contain"></div>' +
'</div><button type="button" class="wz-primary" id="wzCreateBtn">ثبت و انتخاب مدل</button>';
$id("wzAvatar").onchange = function(){
var file = this.files[0], preview = $id("wzAvatarPreview");
if (preview.dataset.url) URL.revokeObjectURL(preview.dataset.url);
preview.hidden = true;
if (!file) return;
if (file.size > 2097152 || !/^image\/(png|jpeg)$/.test(file.type)) { this.value=""; wzMsg("تصویر PNG/JPEG تا ۲ مگابایت انتخاب کنید.",true); return; }
preview.dataset.url = URL.createObjectURL(file); preview.src = preview.dataset.url; preview.hidden = false;
};
$id("wzCreateBtn").onclick = createModel;
bindMini();
}).catch(function (e) { wzMsg(e.message, true); });
}
var MINI = { wzManufacturer: { attr: ATTR.manufacturer, kind: "manufacturer" }, wzFacility: { attr: ATTR.modelType, kind: "facility" } };
function bindMini() {
var plus = document.querySelectorAll("#wzModelForm [data-plus]");
for (var i = 0; i < plus.length; i++) plus[i].onclick = function () {
var id = this.getAttribute("data-plus"), m = $id(id + "Mini");
m.hidden = !m.hidden;
if (!m.hidden) $id(id + "MiniName").focus();
};
var oks = document.querySelectorAll("#wzModelForm [data-miniok]");
for (var j = 0; j < oks.length; j++) oks[j].onclick = function () { miniCreate(this.getAttribute("data-miniok")); };
}
function miniCreate(selId) {
if (W.busy) return;
var cfg = MINI[selId], name = clean($id(selId + "MiniName").value);
if (!name) return wzMsg("نام را وارد کنید.", true);
wzBusy(true); wzMsg("در حال ثبت...");
apiWrite("reference", { sourceAttributeId: cfg.attr, name: name, values: {} })
.then(function (r) {
delete cache[cfg.kind];
return apiGet(cfg.kind, true).then(function (rows) {
var s = $id(selId);
s.innerHTML = selectOptions(rows, r.id);
$id(selId + "MiniName").value = "";
$id(selId + "Mini").hidden = true;
wzMsg("مقدار جدید ثبت و انتخاب شد.");
});
})
.catch(function (e) { wzMsg(e.message, true); })
.then(function () { wzBusy(false); });
}
function createModel() {
if (W.busy) return;
var modelName = "-", manufacturer = $id("wzManufacturer").value;
if (!W.sel.title) return wzMsg("ابتدا عنوان دستگاه را انتخاب کنید.", true);
if (!modelName) return wzMsg("سری / مدل دستگاه الزامی است.", true);
if (!manufacturer) return wzMsg("شرکت سازنده الزامی است.", true);
var payload = {
modelName: modelName,
deviceTitleObjectId: W.sel.title,
manufacturerObjectId: manufacturer,
typeObjectId: $id("wzFacility").value,
groupObjectId: W.sel.group,
nature: clean($id("wzNature").value),
modelFunction: clean($id("wzFunction").value),
criticality: clean($id("wzCriticality").value),
technology: clean($id("wzTechnology").value),
powerRequirement: clean($id("wzPower").value),
waterRequirement: clean($id("wzWater").value),
gasRequirement: clean($id("wzGas").value)
};
wzBusy(true); wzMsg("در حال ثبت مدل...");
var newId = "";
readAvatarFile($id("wzAvatar")).then(function(encoded){
if(encoded) payload.avatarBase64 = encoded;
return apiWrite("model", payload);
}).then(function (r) {
W.pageWarning = "";
W.avatarWarning = r.avatarRequested && !r.avatarSaved ? ("مدل ثبت شد؛ آواتار ذخیره نشد: " + (r.avatarError || "خطای نامشخص")) : "";
newId = String(r.id);
return afterCreate("models", "model", newId, "مدل ثبت شد؛ در حال ساخت صفحه اطلاعات فنی...");
}).then(function () {
wzBusy(true);
return apiPages({
modelObjectId: newId,
modelName: modelName,
classificationName: groupLabel(findRow("groups", W.sel.group) || {}),
equipmentTitleName: labelOf(findRow("titles", W.sel.title))
}).then(function () {
wzMsg(W.avatarWarning || "مدل و صفحه اطلاعات فنی ثبت شدند.", !!W.avatarWarning);
}).catch(function (e) {
W.pageWarning = "مدل ساخته شد ولی ساخت صفحه اطلاعات فنی کامل نشد: " + e.message;
});
}).then(function(){
W.step=3;wzPaint();
if(W.avatarWarning || W.pageWarning)showToast([W.avatarWarning,W.pageWarning].filter(Boolean).join("؛ "));
}).catch(function (e) { wzMsg(e.message, true); })
.then(function () { wzBusy(false); });
}
function readAvatarFile(input) {
return new Promise(function(resolve,reject){
var file=input && input.files && input.files[0];
if(!file) return resolve("");
if(file.size>2097152 || !/^image\/(png|jpeg)$/.test(file.type)) return reject(new Error("تصویر PNG/JPEG تا ۲ مگابایت انتخاب کنید."));
var reader=new FileReader();
reader.onerror=function(){reject(new Error("خواندن تصویر ناموفق بود."));};
reader.onload=function(){resolve(String(reader.result).split(",")[1]);};
reader.readAsDataURL(file);
});
}
var EQUIPMENT_FIELDS = [[6268, "serialNumber", "شماره سریال", "text"], [6273, "purchaseValueRial", "ارزش ریالی خرید", "number"], [6274, "purchaseValueDollar", "ارزش دلاری خرید", "number"], [6275, "manufactureDate", "تاریخ تولید", "date"], [6276, "expiryDate", "تاریخ انقضا", "date"], [6392, "ownerDepartmentObjectId", "بخش (مالک)", "ref", "ownerDepartment"], [6280, "availability", "وضعیت دسترسی", "select"], [6281, "statusReason", "علت وضعیت فعلی", "text"], [6282, "responsibleObjectId", "مسئول بهرهبرداری", "ref", "responsible"], [6283, "recipientObjectId", "تحویلگیرنده", "ref", "recipient"], [6284, "accessoriesObjectIds", "متعلقات", "ref", "accessories"], [6285, "assembly", "نحوه ترکیب اجزا", "select"], [6286, "externalOutput", "آیا خروجی این جزء دستگاه ترکیبی ساقط میشود؟", "boolean"], [6400, "combinedFunction", "عملکرد در مجموعههای ترکیبی", "text"], [6287, "aggregateValue", "ارزش ریالی/دلاری تجمیع", "text"], [6288, "priority", "اولویت", "select"], [6289, "emergency", "فوریت", "select"], [6290, "portable", "قابل حمل", "boolean"], [6402, "portability", "قابلیت حمل", "text"], [6291, "clinicalUse", "کاربرد بالینی", "select"], [6365, "entryDateTime", "زمان ورود", "datetime-local"], [6390, "exitDateTime", "زمان خروج", "datetime-local"], [6396, "ownerCompanyObjectId", "مرکز (مالک)", "ref", "ownerCompany"], [6649, "installationDate", "تاریخ نصب", "date"], [6671, "repairCost", "هزینه تعمیرات", "text"], [6672, "downtimeDays", "روز خواب", "text"]];
var equipmentMetadata = {};
function loadExtraEquipment(){
return jfetch(API.read+"?kind=metadata").then(function(r){
equipmentMetadata = {};
((r.metadata.equipment || {}).attributes || []).forEach(function(a){equipmentMetadata[String(a.id)]=a;});
return Promise.all(EQUIPMENT_FIELDS.filter(function(f){return f[3]==="ref";}).map(function(f){return apiGet(f[4]);}));
});
}
function optionCaption(value){
var key=String(value).toLowerCase();
var names={active:"فعال",inactive:"غیرفعال","entered-in-error":"ثبت اشتباه",lost:"مفقود",damaged:"آسیبدیده",destroyed:"از رده خارج",available:"موجود",high:"زیاد",medium:"متوسط",low:"کم",critical:"بحرانی",urgent:"فوری",normal:"عادی",routine:"معمول",emergency:"اورژانسی",portable:"قابل حمل",fixed:"ثابت",yes:"بله",no:"خیر"};
return names[key] || value;
}
function extraEquipmentHtml(draft,onlyIds){
return EQUIPMENT_FIELDS.filter(function(f){return !onlyIds || onlyIds.indexOf(f[0])>=0;}).map(function(f){
var id="wzExtra"+f[0], m=equipmentMetadata[String(f[0])] || {}, value=draft[f[1]], rows;
if(f[3]==="ref") rows=cache[f[4]] || [];
if(f[3]==="boolean") rows=[{id:"true",label:"بله"},{id:"false",label:"خیر"}];
if(f[3]==="select") rows=String(m.options || "").split(/[,;\r\n]+/).map(function(x){return x.trim();}).filter(Boolean).map(function(x){return {id:x,label:optionCaption(x)};});
if(rows){
var multi=f[3]==="ref" && (Number(m.maximumCardinality)>1 || Number(m.maximumCardinality)===-1);
var chosen=Array.isArray(value)?value.map(String):[String(value==null?"":value)];
return '<div class="wz-field"><label for="'+id+'">'+esc(f[2])+'</label><select id="'+id+'"'+(multi?' multiple size="4"':'')+'>'+(!multi?'<option value="">'+(f[3]==="select" && !rows.length ? 'گزینهای برای این فیلد تعریف نشده' : 'انتخاب کنید')+'</option>':'')+rows.map(function(r){return '<option value="'+esc(r.id)+'"'+(chosen.indexOf(String(r.id))>=0?' selected':'')+'>'+esc(labelOf(r))+'</option>';}).join("")+'</select></div>';
}
return field(id,f[2],value,f[3],Number(m.minimumCardinality)>0);
}).join("");
}
function extraEquipmentValue(f){
var el=$id("wzExtra"+f[0]);
if(!el) return "";
if(el.multiple) return Array.prototype.filter.call(el.options,function(x){return x.selected;}).map(function(x){return x.value;});
return (f[3] === "date" || f[3] === "datetime-local") ? gregorianInput(el.id, f[3] === "datetime-local") : el.value;
}
function bindExtraEquipment(){
EQUIPMENT_FIELDS.forEach(function(f){
var el=$id("wzExtra"+f[0]);
if(f[3]==="number") el.step="any";
el.oninput=el.onchange=function(){W.draft[f[1]]=(f[3] === "date" || f[3] === "datetime-local") ? el.value : extraEquipmentValue(f);};
});
}
function selectEquipmentSegment(index){
mqCloseDatePopover();
W.segment=Number(index);
document.querySelectorAll("#wzBody [data-equipment-panel]").forEach(function(panel){panel.hidden=Number(panel.dataset.equipmentPanel)!==W.segment;});
document.querySelectorAll("#wzBody [data-equipment-tab]").forEach(function(button){var active=Number(button.dataset.equipmentTab)===W.segment;button.classList.toggle("active",active);button.setAttribute("aria-pressed",String(active));});
}
function bindEquipmentSegments(){
var body=$id("wzBody"), panels=body.querySelectorAll("[data-equipment-panel]"),nav=document.createElement("div");
nav.className="wz-segment-tabs";nav.setAttribute("role","group");nav.setAttribute("aria-label","بخشهای اطلاعات دارایی");
nav.innerHTML=Array.prototype.map.call(panels,function(panel,i){return '<button type="button" data-equipment-tab="'+i+'">'+esc(panel.querySelector("legend").textContent)+'</button>';}).join("");
body.insertBefore(nav,panels[0]);
nav.onclick=function(e){var b=e.target.closest("[data-equipment-tab]");if(b && !W.busy)selectEquipmentSegment(b.dataset.equipmentTab);};
selectEquipmentSegment(W.segment || 0);
}
function revealEquipmentField(el){var panel=el.closest("[data-equipment-panel]");if(panel)selectEquipmentSegment(panel.dataset.equipmentPanel);}
function paintEquipment(token) {
var body = $id("wzBody");
body.innerHTML = '<div class="wz-loading">در حال دریافت اطلاعات...</div>';
Promise.all([
apiGet("models"),
apiGet("supplier").catch(function () { return []; }),
apiGet("department"),
loadExtraEquipment()
]).then(function (v) {
if (token !== W.token) return;
var d = W.draft;
var statusRows = Object.keys(STATUS_FA).map(function (k) { return { id: k, label: STATUS_FA[k] }; });
var segmentCounter=0;
function segment(title,body){segmentCounter++;return '<fieldset class="wz-segment" data-equipment-panel="'+(segmentCounter-1)+'"><legend>'+esc(title)+'</legend><div class="wz-grid">'+body+'</div></fieldset>';}
body.innerHTML =
'<div class="wz-static">مدل انتخابشده: '+esc(labelOf(findRow("models",W.sel.model)) || "—")+'</div>'+
segment("مشخصات پایه",field("wzDevId","شناسه دستگاه",d.deviceId,"text",true)+field("wzAssetNo","شماره اموال",d.assetNumber)+extraEquipmentHtml(d,[6268]))+
segment("مشخصات فنی و اجزا",extraEquipmentHtml(d,[6284,6285,6286,6400,6290,6402,6291]))+
segment("اطلاعات مالی و خرید",field("wzPurchase","تاریخ خرید",d.purchaseDate,"date")+selectField("wzSupplier","فروشنده",v[1],d.supplierObjectId,false,false)+extraEquipmentHtml(d,[6273,6274,6287,6671]))+
segment("موقعیت و مسئولان",selectField("wzDept","بخش بهرهبردار",v[2],d.departmentObjectId,false,false)+extraEquipmentHtml(d,[6392,6282,6283,6396]))+
segment("وضعیت و تاریخها",selectField("wzStatus","وضعیت",statusRows,d.status,false,false)+extraEquipmentHtml(d,[6280,6281,6288,6289,6275,6276,6365,6390,6649,6672]));
var ids = ["wzDevId", "wzAssetNo", "wzPurchase", "wzSupplier", "wzDept", "wzStatus"];
var keys = ["deviceId", "assetNumber", "purchaseDate", "supplierObjectId", "departmentObjectId", "status"];
ids.forEach(function (id, i) {
var el = $id(id);
var save = function () { W.draft[keys[i]] = el.value; if(id === "wzDevId")wzHeader(); };
el.oninput = save; el.onchange = save;
});
bindEquipmentSegments();
bindExtraEquipment();
bindJalaliInputs();
$id("wzDevId").focus();
}).catch(function (e) { if (token === W.token) { body.innerHTML = ""; wzMsg(e.message, true); } });
}
function saveEquipment() {
if (W.busy) return;
if (!W.sel.model) return wzMsg("مدل انتخاب نشده است.", true);
if (!validateJalaliInputs()) return;
var p = {
modelObjectId: W.sel.model,
deviceName: "دارایی " + clean($id("wzDevId").value),
deviceId: clean($id("wzDevId").value),
assetNumber: clean($id("wzAssetNo").value),
purchaseDate: gregorianInput("wzPurchase", false),
supplierObjectId: $id("wzSupplier").value,
departmentObjectId: $id("wzDept").value,
status: $id("wzStatus").value
};
EQUIPMENT_FIELDS.forEach(function(f){p[f[1]] = extraEquipmentValue(f);});
if (!p.deviceId) { revealEquipmentField($id("wzDevId"));$id("wzDevId").focus();return wzMsg("شناسه دستگاه الزامی است.", true); }
wzBusy(true); wzMsg("در حال ثبت دستگاه...");
apiWrite("equipment", p).then(function (r) {
wzMsg("دستگاه ثبت شد؛ در حال ساخت صفحه...");
return apiPages({
modelObjectId: W.sel.model,
modelName: labelOf(findRow("models", W.sel.model)),
assetObjectId: r.id,
deviceName: p.deviceName,
deviceId: p.deviceId,
classificationName: groupLabel(findRow("groups", W.sel.group) || {}),
equipmentTitleName: labelOf(findRow("titles", W.sel.title))
}).then(function () { return true; }, function (e) {
showToast("دستگاه ساخته شد ولی ساخت صفحه خطا داد: " + e.message);
return true;
});
}).then(function () {
delete cache.equipment;
closeWizard();
showToast("دستگاه با موفقیت ثبت شد.");
if ($id("mqAssetsHost")) loadAssets("mqAssetsHost", "mqAssetSearch");
}).catch(function (e) { wzMsg(e.message, true); })
.then(function () { wzBusy(false); });
}
function wzNext() {
if (W.busy) return;
if (W.step < 3) {
var cfg = STEPS[W.step];
if (!W.sel[cfg.key]) return wzMsg("ابتدا " + cfg.noun + " را انتخاب کنید.", true);
W.step++; return wzPaint();
}
saveEquipment();
}
function wzPrev() { if (W.busy || W.step === 0) return; W.step--; wzPaint(); }
$id("wzNext").onclick = wzNext;
$id("wzPrev").onclick = wzPrev;
$id("wzClose").onclick = closeWizard;
$id("mqWz").addEventListener("mousedown", function (e) { if (e.target === this) closeWizard(); });
$id("mqDetailClose").onclick = closeDetail;
$id("mqDetail").addEventListener("mousedown", function (e) { if (e.target === this) closeDetail(); });
document.addEventListener("click", function (e) {
var b = e.target.closest ? e.target.closest("[data-detail]") : null;
if (b) openDetail(b.getAttribute("data-detail"));
});
document.addEventListener("keydown", function (e) {
if (e.key !== "Escape") return;
if ($id("mqDetail").classList.contains("open")) closeDetail();
else if (W.open && !W.busy) closeWizard();
});
window.MEDIQ = { version: "V14_ASSET_DASHBOARD", openWizard: openWizard, refresh: function () { loadAssets("mqAssetsHost", "mqAssetSearch"); } };
/* V11: operations interface. All current registration code is preserved. */
var V11={selected:{},states:{},attrs:{department:6277,responsible:6282,status:6279,availability:6280,location:0},ready:false,missing:[],filters:[],searchFields:[],row:null,request:0};
var OP_NAMES={handover:'تحویل و تحول کاربری',entry:'ورود دارایی به انبار',exit:'خروج دارایی از انبار',scrap:'اسقاط دارایی'};
function operations(p){return apiWrite('lifecycle',p);}
function vError(e){return publicMessage(e && e.message || e);}
function vRef(kind,row,aid){var ids=attrList(row,aid);return ids.map(function(id){return labelOf(findRow(kind,id))||id;}).join('، ')||'—';}
function vValues(row,key){
if(key==='key')return [row.key||''];
if(key==='label')return [row.label||''];
var raw=attrList(row,key),field=EQUIPMENT_FIELDS.find(function(f){return String(f[0])===String(key);});
var kind=String(key)==='6277'?'department':String(key)==='6644'?'models':field&&field[3]==='ref'?field[4]:null;
if(kind)raw=raw.concat(attrList(row,key).map(function(id){return labelOf(findRow(kind,id));}));
return raw.map(function(x){return optionCaption(x);});
}
function vFilter(items,query){
var q=searchNorm(query);
return items.filter(function(row){
var all=V11.searchFields.length?[]:[row.key,row.label];(V11.searchFields.length?V11.searchFields:Object.keys(row.attributes||{})).forEach(function(k){all=all.concat(vValues(row,k));});
if(q && searchNorm(all.join(' ')).indexOf(q)<0)return false;
var grouped={};
V11.filters.forEach(function(f){(grouped[String(f.key)]||(grouped[String(f.key)]=[])).push(f);});
return Object.keys(grouped).every(function(key){
var vals=vValues(row,key).map(searchNorm);
return grouped[key].some(function(f){
var wanted=searchNorm(f.value);
if(f.op==='empty')return !attrList(row,key).length;
if(f.op==='eq')return vals.some(function(v){return v===wanted;});
if(f.op==='ne')return !vals.some(function(v){return v===wanted;});
return vals.some(function(v){return v.indexOf(wanted)>=0;});
});
});
});
}
function vReadStates(ids){
return operations({action:'state',ids:ids}).then(function(r){V11.ready=r.ready;V11.missing=r.missing||[];Object.keys(r.states||{}).forEach(function(id){V11.states[id]=Object.assign({checked:true},r.states[id]);});Object.assign(V11.attrs,r.attributes||{});return r;});
}
function vState(row){return V11.states[String(row.id)]||{};}
function vPanel(id){
var row=findRow('equipment',id),box=$id('v11Summary');if(!row||!box)return;
V11.row=String(id);var s=vState(row),a=V11.attrs;
var data=[['مسئول بهرهبردار',vRef('responsible',row,a.responsible)],['بخش بهرهبردار',vRef('department',row,a.department)],['موقعیت فعلی',a.location?vRef('location',row,a.location):'نیازمند تنظیم شناسه موقعیت'],['وضعیت',statusText(attr(row,a.status))],['وضعیت دسترسی',vAccessLabel(attr(row,a.availability))],['وضعیت اموالداری',s.active?(s.conflict?'چند فرایند فعال؛ نیازمند بررسی':'در حال '+(OP_NAMES[s.operation]||'پردازش')):s.checked?'پایدار':'در حال بررسی']];
box.innerHTML='<strong>'+esc(attr(row,ATTR.devName)||row.label)+'</strong>'+data.map(function(d){return '<div class="v-summary-row"><span>'+esc(d[0])+'</span><b>'+esc(d[1])+'</b></div>';}).join('');
if(s.active){
var stages=s.stages||[],at=stages.findIndex(function(x){return String(x.id)===String(s.statusId);});
box.innerHTML+='<h4>روند فرایند</h4><div class="v-steps">'+stages.map(function(x,i){return '<div class="'+(i===at?'current':i<at&&at>=0?'passed':'')+'">'+esc(x.name)+'</div>';}).join('')+'</div><p>'+esc(s.issueKey)+' — '+esc(s.statusName)+'</p>';
if(!stages.length||at<0)box.innerHTML+='<p>مرحلهٔ جاری در مسیر تنظیمشده نیست؛ وضعیت واقعی بالا نمایش داده شده است.</p>';
}
}
function loadAssets(hostId,searchId){
var host=$id(hostId);if(!host)return;var ticket=++V11.request;
host.innerHTML='<div class="wz-loading">در حال دریافت داراییها…</div>';
Promise.all([apiGet('equipment'),apiGet('department'),apiGet('responsible')]).then(function(results){
Promise.all([apiGet('models'),apiGet('location'),loadExtraEquipment()]).catch(function(e){if(window.console)console.warn('MediQ auxiliary data:',e);});
if(ticket!==V11.request||!$id(hostId))return;
var rows=results[0],input=$id(searchId);vRenderStatusDashboard(rows);
function paint(){
host=$id(hostId);if(!host||ticket!==V11.request)return;
var processEl=$id('vProcessFilter'),processValue=processEl?processEl.value:'';
var filtered=vFilter(rows,input?input.value:'').filter(function(row){return (V14_STATUS.filter==='all'||vAssetStatusGroup(row)===V14_STATUS.filter)&&(!processValue||(vState(row).checked&&vState(row).active&&String(vState(row).operation)===processValue));}),part=assetPageSlice(filtered,ASSET_PAGE.page,ASSET_PAGE.size);ASSET_PAGE.page=part.page;
host.innerHTML='<div class="mq-tbl-wrap"><table class="mq-tbl"><thead><tr><th>انتخاب</th><th>شناسه دستگاه</th><th>نام دستگاه</th><th>بخش بهرهبردار</th><th>مسئول بهرهبردار</th><th>وضعیت</th><th>عملیات</th></tr></thead><tbody>'+part.items.map(function(row){var s=vState(row);return '<tr data-vrow="'+esc(row.id)+'"><td><input type="checkbox" data-vselect="'+esc(row.id)+'" aria-label="انتخاب '+esc(row.label)+'" '+(V11.selected[row.id]?'checked ':'')+(s.active?'disabled ':'')+'></td><td>'+esc(attr(row,ATTR.devId)||row.key)+'</td><td>'+esc(attr(row,ATTR.devName)||row.label)+'</td><td><span class="v-tag purple">'+esc(vRef('department',row,6277))+'</span></td><td><span class="v-tag orange">'+esc(vRef('responsible',row,6282))+'</span></td><td><span class="v-status-pill '+vAssetStatusGroup(row)+'">'+esc(statusText(attr(row,ATTR.status)))+'</span>'+(s.active?'<small class="v-active">'+esc(OP_NAMES[s.operation]||'فرایند فعال')+'</small>':'')+'</td><td><div class="v-row-actions"><button type="button" class="mq-assets-btn" data-detail="'+esc(row.id)+'"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M2 12s4-7 10-7 10 7 10 7-4 7-10 7S2 12 2 12Z"/><circle cx="12" cy="12" r="3"/></svg>مشاهده</button><button type="button" class="mq-assets-btn" data-vedit="'+esc(row.id)+'" '+(s.active||!s.checked?'disabled':'')+'><svg viewBox="0 0 24 24" aria-hidden="true"><path d="m15 4 5 5M4 20l5-1L20 8a2 2 0 0 0-5-5L4 14Z"/></svg>ویرایش</button></div></td></tr>';}).join('')+(filtered.length?'':'<tr><td colspan="7">موردی یافت نشد.</td></tr>')+'</tbody></table></div><div class="mq-list-controls"><label>تعداد نمایش <select id="vPageSize">'+['10','20','50','all'].map(function(n){return '<option value="'+n+'" '+(ASSET_PAGE.size===n?'selected':'')+'>'+(n==='all'?'همه':n)+'</option>';}).join('')+'</select></label><span>'+part.start+' تا '+part.end+' از '+filtered.length+' — انتخابشده: '+Object.keys(V11.selected).length+'</span></div><div class="mq-list-controls"><button class="mq-assets-btn" id="vPrev" '+(part.page===1?'disabled':'')+'>قبلی</button><span>صفحه '+part.page+' از '+part.pages+'</span><button class="mq-assets-btn" id="vNext" '+(part.page===part.pages?'disabled':'')+'>بعدی</button></div>';
$id('vPageSize').onchange=function(){ASSET_PAGE.size=this.value;ASSET_PAGE.page=1;paint();};$id('vPrev').onclick=function(){ASSET_PAGE.page--;paint();};$id('vNext').onclick=function(){ASSET_PAGE.page++;paint();};
host.querySelectorAll('[data-vselect]').forEach(function(b){b.onchange=function(){if(b.checked)V11.selected[b.dataset.vselect]=true;else delete V11.selected[b.dataset.vselect];paint();};});
host.querySelectorAll('[data-vrow]').forEach(function(tr){tr.onclick=function(){vPanel(tr.dataset.vrow);};});
host.querySelectorAll('[data-vedit]').forEach(function(b){b.onclick=function(){vEdit(b.dataset.vedit);};});
if(V11.row)vPanel(V11.row);
// Lazy status checks: one request per at most 50 rows, cached until refresh.
var unknown=part.items.filter(function(r){return !vState(r).checked;}).map(function(r){return String(r.id);});
if(unknown.length){
var groups=[];for(var i=0;i<unknown.length;i+=50)groups.push(unknown.slice(i,i+50));
groups.reduce(function(p,ids){return p.then(function(){return vReadStates(ids).then(function(r){ids.forEach(function(id){V11.states[id]=Object.assign({checked:true},r.states[id]);if(V11.states[id].active)delete V11.selected[id];});});});},Promise.resolve()).then(function(){if(ticket===V11.request)paint();}).catch(function(e){var warn=$id('vService');if(warn)warn.textContent='وضعیت فرایندها دریافت نشد: '+vError(e);});
}
}
if(input)input.oninput=function(){ASSET_PAGE.page=1;paint();};V11.paint=paint;paint();
}).catch(function(e){if(ticket===V11.request&&$id(hostId))host.innerHTML='<p>'+esc(vError(e))+'</p>';});
}
function vSearch(){
// Attribute -> actual values, fetched from the complete Assets data already loaded.
var defs=[{id:'key',name:'کد دارایی'},{id:'label',name:'نام دستگاه'}];
Object.keys(equipmentMetadata).forEach(function(k){
var a=equipmentMetadata[k];
if([6270,6366,6401].indexOf(Number(k))<0)defs.push({id:k,name:publicMessage((EQUIPMENT_FIELDS.find(function(f){return String(f[0])===k;})||[])[2]||({'6265':'نام دستگاه','6267':'شناسه دستگاه','6269':'شماره اموال','6277':'بخش بهرهبردار','6279':'وضعیت','6644':'مدل دستگاه'})[k]||a.name)});
});
var old=$id('vInlineFilters');
if(old){old.remove();return;}
var button=$id('vFilters');if(!button)return;
var anchor=button.parentNode;
anchor.classList.add('v-filter-anchor');
var panel=document.createElement('div');panel.id='vInlineFilters';panel.className='v-inline-filters';
panel.innerHTML='<div class="v-filter-top"><strong>فیلتر ویژگیها</strong><button type="button" id="vFilterClose" aria-label="بستن">×</button></div>'+
'<div class="v-filter-columns"><div class="v-filter-attributes"><input type="search" id="vAttributeSearch" placeholder="جستوجوی ویژگی…" autocomplete="off"><div id="vAttributeList" class="v-attribute-list"></div></div>'+
'<div class="v-filter-values"><select id="vFilterKey" hidden><option value="">انتخاب ویژگی</option>'+defs.map(function(a){return '<option value="'+esc(a.id)+'">'+esc(a.name)+'</option>';}).join('')+'</select>'+
'<div id="vFilterDetails" hidden><label for="vFilterOp">شرط فیلتر</label><select id="vFilterOp"><option value="eq">برابر باشد</option><option value="ne">برابر نباشد</option><option value="contains">شامل باشد</option><option value="empty">خالی باشد</option></select><label for="vFilterValue">مقدار ویژگی</label><input type="search" id="vFilterFind" placeholder="جستوجو در مقادیر…" autocomplete="off"><div id="vFilterValue" class="v-filter-checklist" role="group" aria-label="مقادیر ویژگی"></div><small id="vFilterCount"></small></div><p id="vFilterPickHint">یک ویژگی را از فهرست انتخاب کنید.</p></div></div>';
anchor.appendChild(panel);
$id('vFilterClose').onclick=function(){panel.remove();};
var attributeSearch=$id('vAttributeSearch');
function paintAttributes(){
var q=searchNorm(attributeSearch.value);
$id('vAttributeList').innerHTML=defs.filter(function(a){return !q||searchNorm(a.name).indexOf(q)>=0;}).map(function(a){
var current=String($id('vFilterKey').value)===String(a.id);
var selected=V11.filters.some(function(f){return String(f.key)===String(a.id);});
return '<button type="button" class="v-attribute-choice'+(current?' v-attribute-current':'')+'" data-attribute="'+esc(a.id)+'" aria-pressed="'+(selected?'true':'false')+'"><span class="v-attribute-tick" aria-hidden="true">'+(selected?'✓':'')+'</span><span>'+esc(a.name)+'</span></button>';
}).join('')||'<p>ویژگی پیدا نشد.</p>';
$id('vAttributeList').querySelectorAll('[data-attribute]').forEach(function(b){b.onclick=function(){var sel=$id('vFilterKey');sel.value=b.getAttribute('data-attribute');sel.onchange();paintAttributes();$id('vFilterPickHint').hidden=true;};});
}
attributeSearch.oninput=paintAttributes;paintAttributes();
var keyEl=$id('vFilterKey'),opEl=$id('vFilterOp'),valueEl=$id('vFilterValue'),findEl=$id('vFilterFind');
var choices=[];
function valuesFor(key){
var found=Object.create(null),all=[];
(cache.equipment||[]).forEach(function(row){
vValues(row,key).forEach(function(raw){
var display=String(raw==null?'':raw).trim();
if(!display)return;
var norm=searchNorm(display);
if(!found[norm]){found[norm]=true;all.push(display);}
});
});
var meta=equipmentMetadata[String(key)]||{};
String(meta.options||'').split(/[,;\r\n]+/).forEach(function(v){
v=v.trim();if(!v)return;var text=String(optionCaption(v)),norm=searchNorm(text);
if(!found[norm]){found[norm]=true;all.push(text);}
});
return all.sort(function(a,b){return a.localeCompare(b,'fa',{numeric:true});});
}
function repaintTable(){ASSET_PAGE.page=1;if(V11.paint)V11.paint();}
function paintChoices(){
var q=searchNorm(findEl.value),shown=choices.filter(function(x){return !q||searchNorm(x).indexOf(q)>=0;});
var key=keyEl.value,op=opEl.value;
valueEl.innerHTML=shown.map(function(x){
var checked=V11.filters.some(function(f){return String(f.key)===String(key)&&f.op===op&&String(f.value)===String(x);});
return '<label class="v-filter-check-option"><input type="checkbox" data-filter-value="'+esc(x)+'" '+(checked?'checked':'')+' '+(op==='empty'?'disabled':'')+'><span>'+esc(x)+'</span></label>';
}).join('')||'<p class="v-filter-empty">مقداری پیدا نشد.</p>';
$id('vFilterCount').textContent=shown.length+' مقدار قابل انتخاب';
findEl.disabled=op==='empty';
valueEl.querySelectorAll('[data-filter-value]').forEach(function(cb){cb.onchange=function(){
var value=this.getAttribute('data-filter-value');
V11.filters=V11.filters.filter(function(f){return !(String(f.key)===String(key)&&String(f.value)===value);});
if(this.checked)V11.filters.push({key:key,op:op,value:value});
repaintTable();
paintAttributes();
};});
}
keyEl.onchange=function(){
var key=keyEl.value,detail=$id('vFilterDetails');detail.hidden=!key;
if(!key)return;
findEl.value='';
var remembered=V11.filters.find(function(f){return String(f.key)===String(key);});
opEl.value=remembered?remembered.op:'eq';
choices=valuesFor(key);paintChoices();
};
opEl.onchange=function(){
var key=keyEl.value,op=opEl.value;
if(op==='empty'){
V11.filters=V11.filters.filter(function(f){return String(f.key)!==String(key);});
V11.filters.push({key:key,op:'empty',value:''});
repaintTable();
}else{
V11.filters=V11.filters.filter(function(f){return !(String(f.key)===String(key)&&f.op==='empty');});
repaintTable();
}
paintChoices();
paintAttributes();
};
findEl.oninput=paintChoices;
}
function renderAssetSections(mode){
var previousFilter=$id('vInlineFilters');if(previousFilter)previousFilter.remove();
state.screen=mode;state.selectedAssetSection='purchased';heroTitle.textContent='مدیریت اموال و داراییها';heroDesc.textContent='ثبت، ویرایش و پیگیری گردش داراییها';backButton.style.display='inline-block';
buildBreadcrumb(['مدیریت تجهیزات','مدیریت اموال و داراییها']);
view.innerHTML='<section id="vAssetDashboard" aria-label="نمای کلی وضعیت داراییها"></section><div class="mq-list-layout"><aside class="mq-list-menu"><h3>وضعیت دارایی</h3><div id="v11Summary">یک دارایی از لیست انتخاب کنید.</div></aside><div class="mq-preview"><div class="mq-preview-title">لیست داراییها</div><div class="mq-assets-head"><div class="v-search"><input id="mqAssetSearch" type="search" placeholder="جستوجو در داراییها…"><button class="mq-assets-btn" id="vFilters">فیلتر ویژگیها</button><select id="vProcessFilter" class="mq-assets-btn" aria-label="فیلتر فرایند"><option value="">همه فرایندها</option><option value="handover">تحویل و تحول کاربری</option><option value="entry">ورود دارایی به انبار</option><option value="exit">خروج دارایی از انبار</option><option value="scrap">اسقاط دارایی</option></select></div><div class="mq-assets-actions"><button class="mq-assets-btn primary" id="mqAssetsNew">ثبت دارایی جدید</button><button class="mq-assets-btn primary" id="vProcess">تحویل و تحول دارایی</button><button class="mq-assets-btn" id="mqAssetsRefresh">بهروزرسانی لیست</button></div></div><p id="vService" role="status"></p><div id="mqAssetsHost"></div></div></div>';
$id('mqAssetsNew').onclick=openWizard;$id('vProcess').onclick=vProcess;$id('vFilters').onclick=vSearch;var pf=$id('vProcessFilter');if(pf)pf.onchange=function(){
var selected=pf.value,info=$id('vService');
if(!selected){ASSET_PAGE.page=1;if(V11.paint)V11.paint();return;}
if(info)info.textContent='در حال بررسی وضعیت فرایند داراییها…';
var all=cache.equipment||[],unknown=all.filter(function(r){return !vState(r).checked;}).map(function(r){return String(r.id);});
var chunks=[];for(var i=0;i<unknown.length;i+=50)chunks.push(unknown.slice(i,i+50));
var pointer=0;function next(){if(!pf.isConnected||pf.value!==selected)return Promise.resolve();if(pointer>=chunks.length)return Promise.resolve();
var ids=chunks[pointer++];return vReadStates(ids).then(function(){if(info)info.textContent='بررسی فرایندها: '+Math.min(pointer*50,unknown.length)+' از '+unknown.length;return next();});}
next().then(function(){if(!pf.isConnected||pf.value!==selected)return;if(info)info.textContent='';ASSET_PAGE.page=1;if(V11.paint)V11.paint();}).catch(function(e){if(info)info.textContent='خطا در دریافت وضعیت فرایندها: '+vError(e);});
};
$id('mqAssetsRefresh').onclick=function(){V11.states={};delete cache.equipment;loadAssets('mqAssetsHost','mqAssetSearch');};loadAssets('mqAssetsHost','mqAssetSearch');
}
function renderEquipment(){
state.screen='equipment';heroTitle.textContent='مدیریت تجهیزات';heroDesc.textContent='حوزهٔ موردنظر را انتخاب کنید.';backButton.style.display='none';buildBreadcrumb(['مدیریت تجهیزات']);
var cards=[['مدیریت تعمیر و نگهداری',ICONS.maintenance,'maintenance'],['مدیریت تأمین و لجستیک',ICONS.supply,'logistics'],['مدیریت اموال و داراییها',ICONS.property,'property'],['مدیریت مالی و بهرهوری',ICONS.finance,'finance'],['تحلیل و آنالیز','<path d="M4 19h16M6 15V9m6 6V5m6 10v-4M5 7l6-4 7 5"/><circle cx="18" cy="8" r="2"/>','analysis']];
view.innerHTML='<div class="mq-card-grid v-five">'+cards.map(function(c){var children=(c[2]==='property'||c[2]==='logistics');return '<button class="mq-module-card'+(children?' mq-has-children':'')+'" data-vmodule="'+c[2]+'"><span class="mq-module-icon"><svg viewBox="0 0 24 24">'+c[1]+'</svg></span><span class="mq-module-name">'+c[0]+'</span>'+(children?'<span class="mq-hierarchy-arrow" aria-hidden="true">↙</span>':'')+'</button>';}).join('')+'</div>';
view.querySelectorAll('[data-vmodule]').forEach(function(b){b.onclick=function(){var k=b.dataset.vmodule;if(k==='property')renderAssetSections('newAsset');else if(k==='logistics')renderLogistics();else if(k==='analysis')vAnalysis();else mqTreeSimpleEquipmentPage(cards.find(function(c){return c[2]===k;})[0],k);};});mqTreeActivate('equipment');
}
function vAnalysis(){
heroTitle.textContent='تحلیل و آنالیز';heroDesc.textContent='نمای آماری داراییهای ثبتشده';backButton.style.display='inline-block';
view.innerHTML='<div class="wz-loading">در حال دریافت آمار…</div>';
apiGet('equipment').then(function(rows){var counts={};rows.forEach(function(r){var key=statusText(attr(r,ATTR.status));counts[key]=(counts[key]||0)+1;});view.innerHTML='<div class="v-stats"><div><strong>'+rows.length+'</strong><span>کل داراییها</span></div>'+Object.keys(counts).map(function(k){return '<div><strong>'+counts[k]+'</strong><span>'+esc(k)+'</span></div>';}).join('')+'</div>';}).catch(function(e){view.textContent=vError(e);});
}
function vDialog(title,body){
if(W.open || $id('mqDetail').classList.contains('open'))return false;
var el=$id('vDialog');if(!el){el=document.createElement('div');el.id='vDialog';el.className='v-overlay';document.getElementById('mediq-dashboard').appendChild(el);}
V11.editSession=(V11.editSession||0)+1;V11.focus=document.activeElement;
el.innerHTML='<section class="v-dialog" role="dialog" aria-modal="true" aria-labelledby="vDialogTitle"><header><h3 id="vDialogTitle">'+esc(title)+'</h3><button id="vClose" aria-label="بستن">×</button></header><div class="v-dialog-body">'+body+'</div><p id="vMessage" role="status"></p></section>';
el.hidden=false;$id('vClose').onclick=vClose;el.onmousedown=function(e){if(e.target===el)vClose();};$id('vClose').focus();return true;
}
function vClose(){if(V11.busy)return;V11.editSession=(V11.editSession||0)+1;mqCloseDatePopover();var el=$id('vDialog');if(el)el.hidden=true;if(V11.focus&&V11.focus.isConnected)V11.focus.focus();}
function vMessage(text){var el=$id('vMessage');if(el)el.textContent=publicMessage(text);}
function vEdit(id){
var row=findRow('equipment',id);if(!row)return;
if(!vDialog('ویرایش دارایی — '+(row.key||id),'<p>ویرایش مشخصات پایه؛ تغییر مسئول، بخش و موقعیت از تحویلوتحول انجام میشود.</p><div class="v-fields">'+[[6268,'شماره سریال'],[6269,'شماره اموال'],[6281,'علت وضعیت فعلی']].map(function(f){return '<label>'+f[1]+'<input id="vEdit'+f[0]+'" maxlength="500" value="'+esc(attr(row,f[0]))+'"></label>';}).join('')+'</div><button class="mq-assets-btn primary" id="vEditSave">ذخیره تغییرات</button>'))return;
$id('vEditSave').onclick=function(){var vals={};[6268,6269,6281].forEach(function(k){if($id('vEdit'+k).value!==attr(row,k))vals[k]=$id('vEdit'+k).value;});if(!Object.keys(vals).length)return vMessage('تغییری وارد نشده است.');V11.busy=true;this.disabled=true;operations({action:'edit',id:id,values:vals}).then(function(){V11.busy=false;vClose();V11.states={};loadAssets('mqAssetsHost','mqAssetSearch');}).catch(function(e){vMessage(vError(e));}).finally(function(){V11.busy=false;if($id('vEditSave'))$id('vEditSave').disabled=false;});};
}
function vOptions(kind){return '<option value="">انتخاب کنید</option>'+(cache[kind]||[]).map(function(r){return '<option value="'+esc(r.id)+'">'+esc(labelOf(r))+'</option>';}).join('');}
(function(){var header=document.querySelector('#mediq-dashboard .mq-header-left'),hero=document.querySelector('#mediq-dashboard .mq-hero');if(header&&hero)hero.appendChild(header);})();
function vAccessLabel(v){var m={available:'در دسترس',damaged:'آسیب دیده',lost:'گم شده',destroyed:'از بین رفته'};return m[norm(v)]||optionCaption(v)||'—';}
function vProcess(){
if(!vDialog('مدیریت گردش دارایی','<div class="v-operation-choices">'+Object.keys(OP_NAMES).map(function(k){return '<button class="mq-assets-btn" data-vop="'+k+'">'+OP_NAMES[k]+'</button>';}).join('')+'</div><div id="vProcessContent">نوع عملیات را انتخاب کنید.</div>'))return;
var selected=Object.assign({},V11.selected),op='',page=1,token=window.crypto&&crypto.randomUUID?crypto.randomUUID():String(Date.now())+'-'+Math.random().toString(36).slice(2),committed=false;
function fieldSelect(id,label,kind){return '<label>'+label+'<select id="'+id+'">'+vOptions(kind)+'</select></label>';}
function form(){
var labels='';
if(op==='entry')labels=fieldSelect('vTargetLocation','انبار مقصد','location');
else if(op==='exit')labels=fieldSelect('vSourceLocation','انبار مبدأ','location')+fieldSelect('vTargetDepartment','بخش مقصد','department')+fieldSelect('vTargetResponsible','مسئول مقصد','responsible');
else if(op==='scrap')labels=fieldSelect('vSourceLocation','انبار','location');
else labels=fieldSelect('vSourceDepartment','بخش بهرهبردار فعلی','department')+fieldSelect('vSourceResponsible','مسئول فعلی','responsible')+fieldSelect('vTargetDepartment','بخش مقصد','department')+fieldSelect('vTargetResponsible','مسئول مقصد','responsible');
$id('vProcessContent').innerHTML='<h4>'+OP_NAMES[op]+'</h4><div class="v-fields">'+labels+'<label>علت / توضیحات<textarea id="vReason" maxlength="2000"></textarea></label></div><div class="v-process-controls">'+(op==='exit'||op==='scrap'?fieldSelect('vFilterLocation','فیلتر انبار','location'):'')+(op==='handover'||op==='entry'?fieldSelect('vFilterDept','فیلتر بخش فعلی','department')+fieldSelect('vFilterUser','فیلتر مسئول فعلی','responsible'):'')+'</div><div class="v-process-searchline"><input type="search" id="vProcessSearch" placeholder="جستوجو در داراییها"></div><div id="vProcessList"></div><div class="mq-list-controls"><button class="mq-assets-btn" id="vProcessPrev">قبلی</button><span id="vProcessCount"></span><button class="mq-assets-btn" id="vProcessNext">بعدی</button></div><p id="vConfigNotice"></p><button class="mq-assets-btn primary" id="vReview">بازبینی و ثبت</button><div id="vReviewBox"></div>';
var reviewButton=$id('vReview'),filterBar=$id('vProcessList');
if(reviewButton&&filterBar){reviewButton.classList.add('v32-review-top');filterBar.parentNode.insertBefore(reviewButton,filterBar);}
['vProcessSearch','vFilterDept','vFilterUser','vFilterLocation','vSourceDepartment','vSourceResponsible','vSourceLocation'].forEach(function(id){var el=$id(id);if(el){el.addEventListener(id==='vProcessSearch'?'input':'change',function(){page=1;selected={};paint();});}});
$id('vProcessPrev').onclick=function(){page--;paint();};$id('vProcessNext').onclick=function(){page++;paint();};$id('vReview').onclick=review;paint();
}
function matches(row){
var dept=$id('vFilterDept'),user=$id('vFilterUser'),loc=$id('vFilterLocation'),sd=$id('vSourceDepartment'),su=$id('vSourceResponsible'),sl=$id('vSourceLocation');
if(dept&&dept.value&&attrList(row,V11.attrs.department||ATTR.department).indexOf(dept.value)<0)return false;
if(user&&user.value&&attrList(row,V11.attrs.responsible||6282).indexOf(user.value)<0)return false;
if(sd&&sd.value&&attrList(row,V11.attrs.department||ATTR.department).indexOf(sd.value)<0)return false;
if(su&&su.value&&attrList(row,V11.attrs.responsible||6282).indexOf(su.value)<0)return false;
var locId=V11.attrs.location;if((loc&&loc.value)||(sl&&sl.value)){if(!locId)return false;var vals=attrList(row,locId);if(loc&&loc.value&&vals.indexOf(loc.value)<0)return false;if(sl&&sl.value&&vals.indexOf(sl.value)<0)return false;}
if(op==='exit' || op==='scrap'){
var meta=equipmentMetadata||{};var inStoreAttr=Object.keys(meta).find(function(k){return /^(instore|in store|در انبار)$/i.test(String(meta[k].name||meta[k].label||'').trim());});
if(!inStoreAttr)return false;
if(!attrList(row,inStoreAttr).some(function(x){return /^(true|yes|1)$/i.test(x);}))return false;
}
return true;
}
function paint(){
if(!$id('vProcessList'))return;
var rows=vFilter(cache.equipment||[],$id('vProcessSearch').value).filter(matches),part=assetPageSlice(rows,page,'20');page=part.page;
$id('vProcessList').innerHTML='<div class="mq-tbl-wrap"><table class="v-process-table"><thead><tr><th>انتخاب</th><th>دارایی / عنوان</th><th>بخش فعلی</th><th>مسئول فعلی</th><th>وضعیت دسترسی</th></tr></thead><tbody>'+part.items.map(function(r){var st=vState(r);return '<tr><td><input type="checkbox" data-vpselect="'+esc(r.id)+'" '+(selected[r.id]?'checked ':'')+(st.active||!st.checked?'disabled ':'')+'></td><td>'+esc((attr(r,ATTR.devName)||r.label||r.key))+'</td><td>'+esc(vRef('department',r,V11.attrs.department||6277))+'</td><td>'+esc(vRef('responsible',r,V11.attrs.responsible||6282))+'</td><td>'+esc(vAccessLabel(attr(r,V11.attrs.availability||6280)))+'</td></tr>';}).join('')+(rows.length?'':'<tr><td colspan="5">دارایی مطابق فیلتر پیدا نشد.</td></tr>')+'</tbody></table></div>';
$id('vProcessCount').textContent='صفحه '+part.page+' از '+part.pages+' — '+Object.keys(selected).length+' انتخاب';$id('vProcessPrev').disabled=page===1;$id('vProcessNext').disabled=page===part.pages;
$id('vConfigNotice').textContent=V11.ready?'':'ثبت فرایند پس از تکمیل تنظیمات سرویس فعال میشود.';
$id('vProcessList').querySelectorAll('[data-vpselect]').forEach(function(b){b.onchange=function(){if(b.checked)selected[b.dataset.vpselect]=true;else delete selected[b.dataset.vpselect];paint();};});
var ids=part.items.filter(function(r){return !vState(r).checked;}).map(function(r){return String(r.id);});
if(ids.length)vReadStates(ids).then(function(r){ids.forEach(function(id){if(V11.states[id]&&V11.states[id].active)delete selected[id];});if($id('vProcessList')&&!$id('vDialog').hidden)paint();}).catch(function(e){vMessage(vError(e));});
if((op==='exit'||op==='scrap')&&!Object.keys(equipmentMetadata||{}).some(function(k){return /^(instore|in store|در انبار)$/i.test(String(equipmentMetadata[k].name||equipmentMetadata[k].label||'').trim());}))$id('vConfigNotice').textContent='شناسه فیلد InStore در متادیتا مشخص نیست؛ برای جلوگیری از خروج اشتباه، انتخاب دارایی تا تنظیم فیلد غیرفعال است.';
}
function review(){
var ids=Object.keys(selected),responsible=$id('vTargetResponsible'),department=$id('vTargetDepartment'),location=$id('vTargetLocation'),source=$id('vSourceLocation');
if(!ids.length)return vMessage('حداقل یک دارایی انتخاب کنید.');if(ids.length>50)return vMessage('حداکثر ۵۰ دارایی انتخاب کنید.');
var target={responsible:responsible?responsible.value:'',department:department?department.value:'',location:location?location.value:(source?source.value:'')};
if((op==='handover'||op==='exit')&&(!target.responsible||!target.department))return vMessage('مسئول و بخش مقصد الزامی است.');
if((op==='entry'||op==='exit'||op==='scrap')&&!target.location)return vMessage('انتخاب انبار الزامی است.');
if(op==='scrap'&&!$id('vReason').value.trim())return vMessage('علت اسقاط را بنویسید.');
var reason=$id('vReason').value;
$id('vReviewBox').innerHTML='<h4>بازبینی درخواست</h4><p>'+esc(OP_NAMES[op])+' — '+ids.length+' دارایی</p><ul>'+ids.map(function(id){return '<li>'+esc(labelOf(findRow('equipment',id)))+'</li>';}).join('')+'</ul><button class="mq-assets-btn primary" id="vCommit" '+(!V11.ready||committed?'disabled':'')+'>ثبت نهایی درخواست</button>';
$id('vCommit').onclick=function(){if(committed||V11.busy)return;V11.busy=true;this.disabled=true;
operations({action:'start',operation:op,ids:ids,target:target,reason:reason,dateLabel:new Intl.DateTimeFormat('fa-IR',{year:'numeric',month:'2-digit',day:'2-digit'}).format(new Date()),token:token}).then(function(r){committed=true;V11.selected={};V11.states={};$id('vProcessContent').innerHTML='<h3>درخواست '+esc(r.parentKey)+' ثبت شد</h3><p>'+esc(r.message)+'</p>';loadAssets('mqAssetsHost','mqAssetSearch');}).catch(function(e){vMessage(vError(e));if($id('vCommit'))$id('vCommit').disabled=false;}).finally(function(){V11.busy=false;});
};
}
$id('vDialog').querySelectorAll('[data-vop]').forEach(function(b){b.onclick=function(){if(V11.busy||committed)return;op=b.dataset.vop;$id('vDialog').querySelectorAll('[data-vop]').forEach(function(x){x.classList.toggle('primary',x===b);});Promise.all([apiGet('location').catch(function(){return [];}),apiGet('department'),apiGet('responsible'),loadExtraEquipment().catch(function(){return [];})]).then(function(){if(op)form();}).catch(function(e){vMessage(vError(e));});};});
vReadStates([]).catch(function(e){vMessage(vError(e));});
}
document.addEventListener('keydown',function(e){var el=$id('vDialog');if(!el||el.hidden)return;if(e.key==='Escape')vClose();if(e.key==='Tab'){var list=Array.from(el.querySelectorAll('button:not([disabled]),input:not([disabled]),select,textarea')).filter(function(x){return x.offsetParent!==null;});if(!list.length)return;var first=list[0],last=list[list.length-1];if(e.shiftKey&&document.activeElement===first){e.preventDefault();last.focus();}else if(!e.shiftKey&&document.activeElement===last){e.preventDefault();first.focus();}}});
/* Full metadata-driven equipment editor, V12. */
function vEditDefinitions(){
var excluded=[6265,6270,6366,6401];
var captions={6261:'کد دارایی',6263:'تاریخ ایجاد',6264:'آخرین تغییر',6267:'شناسه دستگاه',6269:'شماره اموال',6271:'تاریخ خرید',6272:'فروشنده',6277:'بخش بهرهبردار / موقعیت مکانی فعلی',6279:'وضعیت',6644:'مدل دستگاه',6698:'آزمایشی'};
var segments=[['مشخصات پایه',[6261,6263,6264,6644,6267,6268,6269]],['فنی و اجزا',[6284,6285,6286,6400,6290,6402,6291]],['مالی و خرید',[6271,6272,6273,6274,6287,6671]],['موقعیت و مسئولان',[6277,6392,6282,6283,6396]],['وضعیت و تاریخها',[6279,6280,6281,6288,6289,6275,6276,6365,6390,6649,6672]]];
var fields=Object.keys(equipmentMetadata).map(function(key){var m=equipmentMetadata[key],id=Number(key),known=EQUIPMENT_FIELDS.find(function(f){return f[0]===id;});
var kind=m.objectReference||String(m.type)==='REFERENCED_OBJECT'?'ref':m.dateTimeType?'datetime-local':m.dateType?'date':m.booleanType?'boolean':m.numericType?'number':String(m.options||'').trim()||id===6279?'select':'text';
var bucket=segments.findIndex(function(s){return s[1].indexOf(id)>=0;});
return {id:id,meta:m,label:captions[id]||(known?known[2]:publicMessage(m.name)),kind:kind,segment:bucket<0?5:bucket,multi:Number(m.maximumCardinality)>1||Number(m.maximumCardinality)===-1,required:Number(m.minimumCardinality)>0,editable:[6261,6263,6264].indexOf(id)<0&&['DEFAULT','REFERENCED_OBJECT'].indexOf(String(m.type))>=0};
}).filter(function(f){return excluded.indexOf(f.id)<0;}).sort(function(a,b){return a.segment-b.segment||a.id-b.id;});
return {fields:fields,segments:segments.map(function(x){return x[0];}).concat(['سایر اطلاعات'])};
}
function vEdit(id){
var row=findRow('equipment',id);if(!row)return;
if(!vDialog('ویرایش دارایی — '+(row.key||id),'<div class="wz-loading">در حال دریافت تمام فیلدهای دارایی…</div>'))return;
var session=++V11.editSession||1;V11.editSession=session;
var dialog=$id('vDialog');
jfetch(API.read+'?kind=metadata').then(function(r){
if(dialog.hidden||session!==V11.editSession)return null;
equipmentMetadata={};((r.metadata.equipment||{}).attributes||[]).forEach(function(a){equipmentMetadata[String(a.id)]=a;});
var def=vEditDefinitions();
return Promise.all(def.fields.filter(function(f){return f.kind==='ref';}).map(function(f){return apiGet('equipmentRef_'+f.id).then(function(rows){f.rows=rows;});})).then(function(){return def;});
}).then(function(def){
if(!def||dialog.hidden||session!==V11.editSession)return;
var fields=def.fields,initial={},editing=true;
function options(f){
var rows=f.kind==='ref'?(f.rows||[]):f.kind==='boolean'?[{id:'true',label:'بله'},{id:'false',label:'خیر'}]:String(f.meta.options||'').split(/[,;\r\n]+/).map(function(s){return s.trim();}).filter(Boolean).map(function(v){return {id:v,label:optionCaption(v)};});
if(f.id===6279&&!rows.length)rows=Object.keys(STATUS_FA).map(function(k){return {id:k,label:STATUS_FA[k]};});
rows=rows.slice();attrList(row,f.id).forEach(function(v){if(!rows.some(function(r){return String(r.id)===String(v);}))rows.push({id:v,label:f.kind==='ref'?'مقدار ثبتشده: '+v:optionCaption(v)});});
return rows;
}
function render(f){
var cid='vAll'+f.id,values=attrList(row,f.id),value=values[0]||'',body='';
if(f.id===6261)value=row.key||value;
if(!f.editable)return '<div class="wz-field"><label>'+esc(f.label)+'</label><input readonly value="'+esc(f.kind==='date'||f.kind==='datetime-local'?displayJalali(value,f.kind==='datetime-local'):f.id===6261?value:values.join('، '))+'"></div>';
if(['ref','select','boolean'].indexOf(f.kind)>=0){
body='<select id="'+cid+'" '+(f.multi?'multiple size="5"':'')+' '+(f.required?'required':'')+'>'+(!f.multi?'<option value="">انتخاب کنید</option>':'')+options(f).map(function(r){return '<option value="'+esc(r.id)+'" '+(values.indexOf(String(r.id))>=0?'selected':'')+'>'+esc(labelOf(r))+'</option>';}).join('')+'</select>';
}else if(f.kind==='date'||f.kind==='datetime-local')return jalaliField(cid,f.label,value,f.kind==='datetime-local',f.required);
else if(f.multi)body='<textarea id="'+cid+'" rows="4" '+(f.required?'required':'')+'>'+esc(values.join('\n'))+'</textarea><small>هر مقدار در یک خط</small>';
else body='<input id="'+cid+'" type="'+(f.kind==='number'?'number':'text')+'" '+(f.kind==='number'?'step="any"':'')+' '+(f.required?'required':'')+' value="'+esc(value)+'">';
return '<div class="wz-field"><label for="'+cid+'">'+esc(f.label)+(f.required?' *':'')+'</label>'+body+'</div>';
}
dialog.querySelector('.v-dialog-body').id='vEditBody';
var groups=def.segments.map(function(label,i){return {index:i,label:label,fields:fields.filter(function(f){return f.segment===i;})};}).filter(function(g){return g.fields.length;});
$id('vEditBody').innerHTML='<div class="v-editor-tabs" role="tablist">'+groups.map(function(g,j){return '<button type="button" role="tab" id="vEditTab'+g.index+'" data-edit-tab="'+g.index+'" aria-controls="vEditPanel'+g.index+'" aria-selected="'+(j===0)+'">'+g.label+'</button>';}).join('')+'</div><div class="v-editor-sections">'+groups.map(function(g,j){return '<section role="tabpanel" id="vEditPanel'+g.index+'" aria-labelledby="vEditTab'+g.index+'" data-edit-panel="'+g.index+'" '+(j?'hidden':'')+'><h4>'+g.label+'</h4><div class="v-fields">'+g.fields.map(render).join('')+'</div></section>';}).join('')+'</div><div class="v-editor-footer"><span>فقط فیلدهای تغییرکرده ذخیره میشوند.</span><button type="button" class="mq-assets-btn primary" id="vEditSave">ذخیره تغییرات</button></div>';
function tab(index){mqCloseDatePopover();dialog.querySelectorAll('[data-edit-panel]').forEach(function(p){p.hidden=p.dataset.editPanel!==String(index);});dialog.querySelectorAll('[data-edit-tab]').forEach(function(b){var active=b.dataset.editTab===String(index);b.classList.toggle('active',active);b.setAttribute('aria-selected',String(active));b.tabIndex=active?0:-1;});}
dialog.querySelectorAll('[data-edit-tab]').forEach(function(b){b.onclick=function(){tab(b.dataset.editTab);};b.onkeydown=function(e){if(['ArrowLeft','ArrowRight','Home','End'].indexOf(e.key)<0)return;e.preventDefault();var buttons=Array.from(dialog.querySelectorAll('[data-edit-tab]')),i=buttons.indexOf(b);i=e.key==='Home'?0:e.key==='End'?buttons.length-1:(i+(e.key==='ArrowLeft'?1:-1)+buttons.length)%buttons.length;tab(buttons[i].dataset.editTab);buttons[i].focus();};});tab(groups[0].index);
function raw(f){var el=$id('vAll'+f.id);return el.multiple?Array.from(el.selectedOptions).map(function(o){return o.value;}):el.value;}
fields.filter(function(f){return f.editable;}).forEach(function(f){initial[f.id]=JSON.stringify(raw(f));});
bindJalaliInputs();
$id('vEditSave').onclick=function(){
if(V11.busy||!editing)return;
var values={},expected={};
try{fields.filter(function(f){return f.editable;}).forEach(function(f){var el=$id('vAll'+f.id),value=raw(f);if(JSON.stringify(value)===initial[f.id])return;
if(!el.checkValidity()){tab(f.segment);el.focus();el.reportValidity();throw new Error('مقدار «'+f.label+'» معتبر نیست.');}
if(f.kind==='date'||f.kind==='datetime-local'){try{value=parseJalali(value,f.kind==='datetime-local');}catch(e){tab(f.segment);el.focus();throw e;}}
else if(f.multi&&!el.multiple)value=String(value).split(/\r?\n/).map(function(v){return v.trim();}).filter(Boolean);
values[String(f.id)]=value;expected[String(f.id)]=attrList(row,f.id);
});}catch(e){vMessage(vError(e));return;}
if(!Object.keys(values).length)return vMessage('تغییری وارد نشده است.');
mqCloseDatePopover();V11.busy=true;this.disabled=true;
operations({action:'edit',id:String(id),values:values,expected:expected}).then(function(){editing=false;V11.busy=false;vClose();V11.states={};loadAssets('mqAssetsHost','mqAssetSearch');}).catch(function(e){vMessage(vError(e));}).finally(function(){V11.busy=false;if($id('vEditSave'))$id('vEditSave').disabled=false;});
};
}).catch(function(e){if(!dialog.hidden&&session===V11.editSession){dialog.querySelector('.v-dialog-body').textContent='دریافت فرم ویرایش کامل نشد.';vMessage(vError(e));}});
}
/* Live process progress. The only polling action is state (read-only). */
var V13_LIVE={busy:false,sequence:0,lastAsset:null,error:'',updated:0};
function vTimelineStates(s){
var path=s.stages||[],current=path.findIndex(function(step){return String(step.id)===String(s.statusId);});
return path.map(function(step,i){
var left=step.leftAt,entered=step.enteredAt,confirmed=!!(entered&&left&&left>=entered);
var state=i===current?(s.active?'current':s.completed?'done':'pending'):(i<current&&confirmed?'done':'pending');
return {id:step.id,label:step.name,state:state,enteredAt:entered||'',leftAt:left||''};
});
}
function vTimelineHost(){
var root=$id('v11Summary');if(!root)return null;
var host=$id('vLiveTimeline');if(!host){host=document.createElement('section');host.id='vLiveTimeline';host.className='v-live-timeline';host.setAttribute('aria-label','روند فرایند دارایی');root.parentNode.appendChild(host);}
return host;
}
function vRenderTimeline(row,s){
var host=vTimelineHost();if(!host)return;
host.innerHTML='<header><strong>'+(s.active?'روند فرایند':s.hasProcess?'آخرین فرایند':'روند فرایند')+'</strong></header>';
if(!s.checked){host.innerHTML+='<p>در حال دریافت اطلاعات…</p>';return;}
if(!s.hasProcess&&!s.issueKey){host.innerHTML+='<p>فرایند ثبتشدهای برای این دارایی یافت نشد.</p>';return;}
var steps=vTimelineStates(s);
host.innerHTML+='<ol class="v-circle-track" aria-label="مراحل فرایند">'+steps.map(function(step,i){return '<li class="v-circle-step '+step.state+'" '+(step.state==='current'?'aria-current="step"':'')+'><div class="v-circle-rail"><span class="v-circle-node" aria-hidden="true">'+(step.state==='done'?'✓':step.state==='current'?'<i></i>':'')+'</span><span class="v-circle-line '+(steps[i+1]&&step.state==='done'&&(steps[i+1].state==='done'||steps[i+1].state==='current')?'done':'')+'"></span></div><strong>'+esc(step.label)+'</strong><small>'+esc(step.state==='current'?'مرحلهٔ جاری':step.state==='done'?'انجامشده':step.enteredAt?'قبلاً طی شده':'در انتظار')+'</small></li>';}).join('')+'</ol>';
if(s.historyWarning)host.innerHTML+='<p class="v-timeline-warning">اطلاعات سابقهٔ مراحل کامل نیست.</p>';
if(steps.length&&!steps.some(function(x){return String(x.id)===String(s.statusId);}))host.innerHTML+='<p class="v-timeline-warning">وضعیت جاری در مسیر نمایش تنظیمشده نیست.</p>';
}
function vPanel(id){
var row=findRow('equipment',id),box=$id('v11Summary');if(!row||!box)return;
if(V13_LIVE.lastAsset!==String(id)){V13_LIVE.sequence++;V13_LIVE.lastAsset=String(id);V13_LIVE.error='';V13_LIVE.updated=0;}
V11.row=String(id);var s=vState(row),a=V11.attrs;
var labels={handover:'در حال تحویل کاربری',entry:'در حال ورود به انبار',exit:'در حال خروج از انبار',scrap:'در حال اسقاط'};
var data=[['مسئول بهرهبردار',vRef('responsible',row,a.responsible)],['بخش بهرهبردار',vRef('department',row,a.department)],['موقعیت فعلی',vRef('location',row,a.location||6277)],['وضعیت',statusText(attr(row,a.status))],['وضعیت دسترسی',vAccessLabel(attr(row,a.availability))],['وضعیت اموالداری',s.active?(s.conflict?'چند فرایند فعال؛ نیازمند بررسی':labels[s.operation]||'در حال پردازش'):s.checked?'پایدار':'در حال بررسی']];
box.innerHTML='<strong>'+esc(attr(row,ATTR.devName)||row.label)+'</strong>'+data.map(function(d){return '<div class="v-summary-row"><span>'+esc(d[0])+'</span><b>'+esc(d[1])+'</b></div>';}).join('');
vRenderTimeline(row,s);
}
function vLiveRefresh(){
if(V13_LIVE.busy||V11.busy||document.hidden||!$id('v11Summary')||!V11.row)return;
var id=String(V11.row),seq=V13_LIVE.sequence;V13_LIVE.busy=true;
operations({action:'state',ids:[id]}).then(function(r){
if(seq!==V13_LIVE.sequence||String(V11.row)!==id||!$id('v11Summary'))return;
if(!r.states||!r.states[id])throw new Error('پاسخ بررسی وضعیت کامل نیست.');
V11.states[id]=Object.assign({checked:true},r.states[id]);V13_LIVE.error='';V13_LIVE.updated=Date.now();
V11.ready=r.ready;V11.missing=r.missing||[];Object.assign(V11.attrs,r.attributes||{});
vPanel(id);
document.querySelectorAll('[data-vselect="'+id+'"],[data-vedit="'+id+'"]').forEach(function(b){b.disabled=!!r.states[id].active;if(r.states[id].active&&b.type==='checkbox'){b.checked=false;delete V11.selected[id];}});
}).catch(function(e){if(seq===V13_LIVE.sequence){V13_LIVE.error=vError(e);var row=findRow('equipment',id);if(row)vRenderTimeline(row,vState(row));}}).finally(function(){V13_LIVE.busy=false;});
}
setInterval(vLiveRefresh,5000);
document.addEventListener('visibilitychange',function(){if(!document.hidden)vLiveRefresh();});
window.addEventListener('focus',vLiveRefresh);
/* Equipment status summary is calculated over the complete equipment list. */
var V14_STATUS={filter:'all'};
function vAssetStatusGroup(row){
var raw=searchNorm(attr(row,ATTR.status)).replace(/\s+/g,'');
if(raw==='active'||raw==='فعال')return 'active';
if(raw==='inactive'||raw==='غیرفعال'||raw==='غيرفعال')return 'inactive';
return 'other';
}
function vAssetStatusCounts(rows){
var counts={all:rows.length,active:0,inactive:0,other:0};
rows.forEach(function(row){counts[vAssetStatusGroup(row)]++;});return counts;
}
function vRenderStatusDashboard(rows){
var host=$id('vAssetDashboard');if(!host)return;
var counts=vAssetStatusCounts(rows),fa=new Intl.NumberFormat('fa-IR');
var icons={all:'<rect x="3" y="3" width="7" height="7" rx="2"/><rect x="14" y="3" width="7" height="7" rx="2"/><rect x="3" y="14" width="7" height="7" rx="2"/><rect x="14" y="14" width="7" height="7" rx="2"/>',active:'<circle cx="12" cy="12" r="9"/><path d="m8 12 3 3 5-6"/>',inactive:'<circle cx="12" cy="12" r="9"/><path d="M9 8v8m6-8v8"/>',other:'<path d="m12 3 10 17H2Z"/><path d="M12 9v4m0 3v1"/>'};
var names={all:'کل داراییها',active:'داراییهای فعال',inactive:'داراییهای غیرفعال',other:'سایر وضعیتها'};
host.innerHTML='<div class="v-dashboard-heading"><div><strong>نمای کلی داراییها</strong><span>آمار کل داراییها؛ مستقل از جستوجو و صفحهبندی</span></div><small>برای فیلتر لیست، یک کارت را انتخاب کنید.</small></div><div class="v-status-cards">'+['all','active','inactive','other'].map(function(key){var value=counts[key],percent=counts.all?Math.round(value/counts.all*100):0;return '<button type="button" class="v-stat-card '+key+(V14_STATUS.filter===key?' selected':'')+'" data-status-card="'+key+'" aria-pressed="'+(V14_STATUS.filter===key)+'"><span class="v-stat-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">'+icons[key]+'</svg></span><span class="v-stat-label">'+names[key]+'</span><strong>'+fa.format(value)+'</strong><span class="v-stat-bottom">'+(key==='all'?'نمایش همهٔ وضعیتها':fa.format(percent)+'٪ از کل داراییها')+'</span><span class="v-stat-meter" aria-hidden="true"><i style="width:'+percent+'%"></i></span></button>';}).join('')+'</div>';
host.querySelectorAll('[data-status-card]').forEach(function(b){b.onclick=function(){V14_STATUS.filter=b.dataset.statusCard;ASSET_PAGE.page=1;vRenderStatusDashboard(rows);if(V11.paint)V11.paint();};});
}
/* V30 logistics navigation override: preserve existing backend routes. */
function renderLogistics(){
state.screen='logistics';heroTitle.textContent='مدیریت تأمین و لجستیک';heroDesc.textContent='دسته موردنظر را انتخاب کنید.';backButton.style.display='inline-block';buildBreadcrumb(['مدیریت تجهیزات','مدیریت تأمین و لجستیک']);
var options=[['کالاهای مصرفی','consumable',ICONS.consumable],['داراییهای ثابت','fixed',ICONS.property],['تأمینکنندهها','suppliers',ICONS.supply]];
view.innerHTML='<div class="mq-card-grid">'+options.map(function(o){return '<button type="button" class="mq-module-card mq-has-children" data-logistic="'+o[1]+'"><span class="mq-module-icon"><svg viewBox="0 0 24 24">'+o[2]+'</svg></span><span class="mq-module-name">'+o[0]+'</span><span class="mq-hierarchy-arrow" aria-hidden="true">↙</span></button>';}).join('')+'</div>';
view.querySelectorAll('[data-logistic]').forEach(function(btn){btn.onclick=function(){var k=btn.dataset.logistic;if(k==='suppliers')vSupplierScreen();else if(k==='fixed')renderAssetSections('newAsset');else{state.screen='consumable';renderSimplePage('کالاهای مصرفی');mqTreeActivate('consumable');}};});mqTreeActivate('logistics');
}
function vSupplierScreen(){
state.screen='suppliers';heroTitle.textContent='تأمینکنندهها';heroDesc.textContent='فهرست تأمینکنندگان ثبتشده در سامانه داراییها';backButton.style.display='inline-block';buildBreadcrumb(['مدیریت تجهیزات','مدیریت تأمین و لجستیک','تأمینکنندهها']);
mqTreeActivate('suppliers');view.innerHTML='<div class="mq-preview"><div class="mq-preview-title">تأمینکنندهها</div><div class="mq-assets-head"><input class="mq-edit-search" id="vSupplierSearch" placeholder="جستوجوی تأمینکننده"><button type="button" class="mq-assets-btn" id="vSupplierReload">بهروزرسانی لیست</button></div><div id="vSupplierList" class="mq-assets-host"><div class="wz-loading">در حال دریافت اطلاعات…</div></div></div>';
var rows=[];function paint(){var host=$id('vSupplierList');if(!host)return;var q=searchNorm($id('vSupplierSearch').value);var subset=rows.filter(function(r){return searchNorm([r.key,r.label,r.id].join(' ')).indexOf(q)>=0;}).slice(0,250);host.innerHTML='<div class="mq-tbl-wrap"><table class="mq-tbl"><thead><tr><th>شناسه</th><th>نام تأمینکننده</th></tr></thead><tbody>'+subset.map(function(r){return '<tr><td>'+esc(r.key||r.id)+'</td><td>'+esc(labelOf(r))+'</td></tr>';}).join('')+'</tbody></table></div><p>'+subset.length+' مورد نمایش داده شده</p>';}
function load(force){apiGet('supplier',force).then(function(r){rows=r;paint();}).catch(function(e){$id('vSupplierList').textContent=vError(e);});}
$id('vSupplierSearch').oninput=paint;$id('vSupplierReload').onclick=function(){load(true);};load(false);
}
/* V31: internal navigation history. Capture real entry routes, not hard-coded previous screens. */
var MQ_V31_HISTORY=[];
var MQ_V31_CURRENT=null;
var MQ_V31_REPLAY=false;
var MQ_V31_NESTING=0;
function mqV31Route(key,args){return {key:key,args:Array.prototype.slice.call(args||[])};}
function mqV31Equal(a,b){return !!a&&!!b&&a.key===b.key&&JSON.stringify(a.args)===JSON.stringify(b.args);}
function mqV31Track(key,fn){
return function(){
var next=mqV31Route(key,arguments),top=MQ_V31_NESTING===0;
if(top&&!MQ_V31_REPLAY&&!mqV31Equal(MQ_V31_CURRENT,next)){
if(MQ_V31_CURRENT)MQ_V31_HISTORY.push(MQ_V31_CURRENT);
MQ_V31_CURRENT=next;
}
MQ_V31_NESTING++;
try { return fn.apply(this,arguments); }
finally { MQ_V31_NESTING--;mqV31BackVisibility(); }
};
}
function mqV31BackVisibility(){
if(backButton)backButton.style.display=MQ_V31_HISTORY.length?'inline-block':'none';
}
var MQ_V31_RENDERERS={
equipment:renderEquipment,
logistics:renderLogistics,
property:renderAssetSections,
simple:renderSimplePage,
generic:mqTreeSimpleEquipmentPage,
analysis:vAnalysis,
suppliers:vSupplierScreen,
cycle:renderOtherCycle
};
renderEquipment=mqV31Track('equipment',MQ_V31_RENDERERS.equipment);
renderLogistics=mqV31Track('logistics',MQ_V31_RENDERERS.logistics);
renderAssetSections=mqV31Track('property',MQ_V31_RENDERERS.property);
renderSimplePage=mqV31Track('simple',MQ_V31_RENDERERS.simple);
mqTreeSimpleEquipmentPage=mqV31Track('generic',MQ_V31_RENDERERS.generic);
vAnalysis=mqV31Track('analysis',MQ_V31_RENDERERS.analysis);
vSupplierScreen=mqV31Track('suppliers',MQ_V31_RENDERERS.suppliers);
renderOtherCycle=mqV31Track('cycle',MQ_V31_RENDERERS.cycle);
backButton.onclick=function(){
if(!MQ_V31_HISTORY.length)return;
var prev=MQ_V31_HISTORY.pop(),renderer=MQ_V31_RENDERERS[prev.key];
if(!renderer)return;
MQ_V31_REPLAY=true;
try { MQ_V31_CURRENT=prev;renderer.apply(null,prev.args); }
finally { MQ_V31_REPLAY=false;mqV31BackVisibility(); }
};
/* ============================================================
INITIAL
============================================================ */
function mqBoot(){
try {
bindTree();
document.querySelectorAll('#mqTree [data-v32-nav]').forEach(function(el){el.onclick=function(){
var k=this.getAttribute('data-v32-nav');
if(k==='suppliers')vSupplierScreen();
else if(k==='fixed'||k==='assets')renderAssetSections('newAsset');
else if(k==='handover'){renderAssetSections('newAsset');vProcess();}
else if(k==='consumable')renderSimplePage('کالاهای مصرفی');
mqTreeActivate(k==='assets'||k==='handover'?'property':k);
};});
renderEquipment();
} catch (initErr) {
mqShowFatal(initErr && initErr.message ? initErr.message : String(initErr));
if (window.console && console.error) console.error("MEDIQ INIT ERROR", initErr);
}
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", mqBoot, { once: true });
} else {
mqBoot();
}
})();
</script>
</div> |