var wl=Object.defineProperty;var $l=(ee,W,re)=>W in ee?wl(ee,W,{enumerable:!0,configurable:!0,writable:!0,value:re}):ee[W]=re;var g=(ee,W,re)=>$l(ee,typeof W!="symbol"?W+"":W,re);(function(){"use strict";var It,Sa;const ee="modulepreload",W=function(p){return"/"+p},re={},Ta=function(e,t,s){let a=Promise.resolve();function i(n){const r=new Event("vite:preloadError",{cancelable:!0});if(r.payload=n,window.dispatchEvent(r),!r.defaultPrevented)throw n}return a.then(n=>{for(const r of n||[])r.status==="rejected"&&i(r.reason);return e().catch(i)})};let Ma=class{constructor(){this.events=new Map}on(e,t){return this.events.has(e)||this.events.set(e,new Set),this.events.get(e).add(t),()=>this.off(e,t)}off(e,t){this.events.has(e)&&(this.events.get(e).delete(t),this.events.get(e).size===0&&this.events.delete(e))}emit(e,t=null){if(!this.events.has(e))return;const s=this.events.get(e);for(const a of s)try{a(t)}catch(i){console.error("EventBus listener error:",i)}}once(e,t){const s=a=>{t(a),this.off(e,s)};this.on(e,s)}};class Ra{constructor(e){this.eventBus=e,this.state={auth:{user:null,nonce:null,loggedIn:!1},ui:{loading:!1},context:{project:null},modules:{}}}get(e){const t=e.split(".");let s=this.state;for(const a of t){if(s[a]===void 0)return null;s=s[a]}return s}set(e,t){const s=e.split(".");let a=this.state;for(let i=0;i<s.length-1;i++){const n=s[i];a[n]||(a[n]={}),a=a[n]}a[s[s.length-1]]=t,this.eventBus.emit(`store:changed:${e}`,t)}update(e,t){const s=this.get(e),a=t(s);this.set(e,a)}}class qa{constructor({config:e={},store:t,eventBus:s}={}){var i;this.store=t,this.eventBus=s,this.apiFetch=(i=window.wp)==null?void 0:i.apiFetch;const a=e.apiUrl||"/wp-json/acc/v1";this.baseUrl=a.replace(/\/+$/,"")}getToken(){var e,t;return((t=(e=this.store)==null?void 0:e.get("session"))==null?void 0:t.token)||sessionStorage.getItem("acc_token")||null}buildHeaders(e={}){const t={"Content-Type":"application/json",Accept:"application/json",...e},s=this.getToken();return s&&(t.Authorization=`Bearer ${s}`),t}async request(e,t,s=null,a={}){const i=String(t||"").replace(/^\/+/,"");let n=`${this.baseUrl}/${i}`;if(n=n.replace(/([^:]\/)\/+/g,"$1"),a.query&&typeof a.query=="object"){const c=new URLSearchParams;Object.entries(a.query).forEach(([h,u])=>{u!=null&&u!==""&&c.append(h,u)});const d=c.toString();d&&(n+=(n.includes("?")?"&":"?")+d)}const r={method:e,headers:this.buildHeaders(a.headers||{})};s&&e!=="GET"&&e!=="HEAD"&&(r.body=JSON.stringify(s));const o=await fetch(n,r);let l=null;try{l=await o.json()}catch{l=null}if(!o.ok)throw o.status===401&&this.handleUnauthorized(),new Error((l==null?void 0:l.message)||`HTTP ${o.status}`);return l}handleUnauthorized(){var e,t;sessionStorage.removeItem("acc_token"),(e=this.store)==null||e.set("auth",{user:null,loggedIn:!1}),(t=this.eventBus)==null||t.emit("auth:unauthorized")}get(e,t={},s={}){return this.request("GET",e,null,{...s,query:t})}post(e,t={},s={}){return this.request("POST",e,t,s)}put(e,t={},s={}){return this.request("PUT",e,t,s)}delete(e,t={}){return this.request("DELETE",e,null,t)}}class Ha{constructor({api:e,store:t,eventBus:s}){this.api=e,this.store=t,this.eventBus=s,this.root=null,this._tab="login"}render(e){this.root=e,e.innerHTML=this._skeleton(),this._bindAuthTabs(),this._bindAuthForms(),this._bindReveal()}_skeleton(){var i,n;const e=((n=(i=window.ACC_APP_BOOT)==null?void 0:i.restBase)==null?void 0:n.replace("/api.php/",""))||"/acc-engine/",t=e.endsWith("/")?e:e+"/",a=[{href:t+"melk.php",tag:"Melk",title:"اقتصاد ملک",desc:"شبکه بنگاه و مشارکت شیراز",cls:"hl-portal--melk"},{href:t+"wholesale.php",tag:"Wholesale",title:"عمده‌فروشی قشم",desc:"B2B · قیمت پلکانی · MOQ",cls:"hl-portal--ws"},{href:t+"service.php",tag:"Service",title:"خدمات HVAC",desc:"سفارش، تکنسین، حسابداری فعالیت",cls:"hl-portal--svc"},{href:t+"education.php",tag:"Campus",title:"آموزش",desc:"جلسه، کلاس، گراف هزینه آموزشی",cls:"hl-portal--edu"},{href:t+"growth.php",tag:"Growth",title:"رشدگاه / سفیران",desc:"خدمات مالک · ارجاع · کمیسیون",cls:"hl-portal--growth"},{href:t+"election.php",tag:"Civic",title:"انتخابات",desc:"کمپین، هوادار، حسابداری ستاد",cls:"hl-portal--el"},{href:t+"shop.php",tag:"Shop",title:"فروشگاه",desc:"خرده‌فروشی و حسابداری فروش",cls:"hl-portal--shop"},{href:t+"dev.php",tag:"Dev",title:"پشتیبان‌گیری و مستندات",desc:"بک‌آپ کد و دیتابیس + handoff توسعه‌دهنده",cls:"hl-portal--dev"}].map(r=>`
            <a href="${r.href}" class="hl-portal ${r.cls}">
                <span class="hl-portal__tag">${r.tag}</span>
                <strong>${r.title}</strong>
                <small>${r.desc}</small>
                <span class="hl-portal__go">ورود ←</span>
            </a>`).join("");return`
        <div class="hl-wrap" dir="rtl">
            <div class="hl-util">
                <a href="${t}">ACC Engine</a>
                <a href="${t}melk.php">املاک</a>
                <a href="${t}wholesale.php">عمده</a>
                <a href="${t}service.php">خدمات</a>
                <a href="${t}education.php">آموزش</a>
                <a href="${t}growth.php">رشدگاه</a>
                <a href="${t}election.php">انتخابات</a>
                <a href="${t}shop.php">فروشگاه</a>
                <a href="${t}dev.php">پشتیبان</a>
            </div>

            <header class="hl-header" id="hl-header">
                <a href="${t}" class="hl-brand">
                    <span class="hl-brand__mark">A</span>
                    <span class="hl-brand__text">
                        <span class="hl-brand__name">ACC <em>Engine</em></span>
                        <span class="hl-brand__sub">Holding Operations Platform</span>
                    </span>
                </a>
                <nav class="hl-nav">
                    <a href="#hl-portals">پورتال‌ها</a>
                    <a href="#hl-erp">ERP</a>
                    <button type="button" id="lp-open-auth">ورود / ثبت‌نام</button>
                </nav>
                <button type="button" class="hl-header__cta" id="lp-hero-auth">ورود به ERP</button>
            </header>

            <div class="hl-main">
                <section class="hl-hero">
                    <div class="hl-hero__media" aria-hidden="true"></div>
                    <div class="hl-hero__grain" aria-hidden="true"></div>
                    <div class="hl-hero__content">
                        <p class="hl-hero__brand">ACC <span>Engine</span></p>
                        <h1>سامانه یکپارچه<br><em>عملیات هلدینگ</em></h1>
                        <p class="hl-hero__lead">از نقشه و حسابداری تا املاک، خدمات، آموزش و انتخابات — یک هویت، یک ورود، ماژول‌های هماهنگ.</p>
                        <div class="hl-hero__actions">
                            <button type="button" class="hl-btn hl-btn--cyan" id="hl-cta-erp">ورود به ERP</button>
                            <a href="#hl-portals" class="hl-btn hl-btn--ghost">کشف پورتال‌ها</a>
                        </div>
                    </div>
                </section>

                <aside class="lp-auth-panel hl-auth" id="lp-auth-panel">
                    <div class="lp-auth-card">
                        <div class="lp-auth-tabs">
                            <button class="lp-auth-tab active" data-tab="login">ورود</button>
                            <button class="lp-auth-tab" data-tab="register">ثبت‌نام</button>
                            <button class="lp-auth-tab" data-tab="forgot">فراموشی رمز</button>
                        </div>

                        <form class="lp-form" id="lp-form-login" autocomplete="on">
                            <div class="lp-form__title">ورود به پورتال ERP</div>
                            <div class="lp-field">
                                <label>نام کاربری یا ایمیل</label>
                                <input name="username" placeholder="username یا email" autocomplete="username">
                            </div>
                            <div class="lp-field">
                                <label>رمز عبور</label>
                                <div class="lp-pass-wrap">
                                    <input name="password" type="password" placeholder="••••••••" autocomplete="current-password" id="lp-pass-input">
                                    <button type="button" class="lp-pass-toggle" id="lp-pass-toggle">👁</button>
                                </div>
                            </div>
                            <div class="lp-form__row">
                                <label class="lp-checkbox"><input type="checkbox" name="remember"> مرا به خاطر بسپار</label>
                                <button type="button" class="lp-link" data-tab="forgot">فراموشی رمز؟</button>
                            </div>
                            <button type="submit" class="lp-btn">ورود به ERP</button>
                            <div class="lp-msg" id="lp-msg-login"></div>
                        </form>

                        <form class="lp-form lp-form--hidden" id="lp-form-register" autocomplete="on">
                            <div class="lp-form__title">ایجاد حساب جدید</div>
                            <div class="lp-field-row">
                                <div class="lp-field">
                                    <label>نام</label>
                                    <input name="firstname" placeholder="نام" autocomplete="given-name">
                                </div>
                                <div class="lp-field">
                                    <label>نام خانوادگی</label>
                                    <input name="lastname" placeholder="نام خانوادگی" autocomplete="family-name">
                                </div>
                            </div>
                            <div class="lp-field">
                                <label>نام کاربری <span class="lp-req">*</span></label>
                                <input name="username" placeholder="username" autocomplete="username" required>
                            </div>
                            <div class="lp-field">
                                <label>ایمیل <span class="lp-req">*</span></label>
                                <input name="email" type="email" placeholder="email@example.com" autocomplete="email" required>
                            </div>
                            <div class="lp-field">
                                <label>رمز عبور <span class="lp-req">*</span></label>
                                <input name="password" type="password" placeholder="••••••••" autocomplete="new-password" required>
                            </div>
                            <div class="lp-field">
                                <label>تکرار رمز عبور <span class="lp-req">*</span></label>
                                <input name="password2" type="password" placeholder="••••••••" autocomplete="new-password" required>
                            </div>
                            <button type="submit" class="lp-btn">ایجاد حساب</button>
                            <div class="lp-msg" id="lp-msg-register"></div>
                        </form>

                        <form class="lp-form lp-form--hidden" id="lp-form-forgot">
                            <div class="lp-form__title">بازیابی رمز عبور</div>
                            <p class="lp-form__desc">ایمیل یا نام کاربری خود را وارد کنید.</p>
                            <div class="lp-field">
                                <label>ایمیل یا نام کاربری</label>
                                <input name="login" placeholder="email یا username">
                            </div>
                            <button type="submit" class="lp-btn">ارسال لینک بازیابی</button>
                            <div class="lp-msg" id="lp-msg-forgot"></div>
                            <div class="lp-form__row" style="margin-top:12px;justify-content:center;">
                                <button type="button" class="lp-link" data-tab="login">← بازگشت به ورود</button>
                            </div>
                        </form>
                    </div>
                </aside>
            </div>

            <section class="hl-section" id="hl-erp">
                <div class="hl-section__head hl-reveal">
                    <span class="hl-kicker">ERP Core</span>
                    <h2>ماژول‌های عملیاتی هلدینگ</h2>
                    <p>نقشه، حسابداری، انبار، فروش، CRM و ده‌ها ماژول — پس از ورود در یک workspace یکپارچه.</p>
                </div>
                <div class="hl-reveal" style="text-align:center">
                    <button type="button" class="hl-btn hl-btn--dark" id="hl-open-erp">باز کردن پورتال ERP ←</button>
                </div>
            </section>

            <section class="hl-section hl-section--mist" id="hl-portals">
                <div class="hl-section__head hl-reveal">
                    <span class="hl-kicker">Portals</span>
                    <h2>پورتال‌های تخصصی</h2>
                    <p>هر کسب‌وکار هویت بصری و فضای کاری خود را دارد — متصل به همان موتور ACC.</p>
                </div>
                <div class="hl-portals hl-reveal">${a}</div>
            </section>

            <footer class="hl-footer">
                <span>© ACC Engine — Holding Operations</span>
                <span>
                    <a href="${t}melk.php">املاک</a> ·
                    <a href="${t}growth.php">رشدگاه</a> ·
                    <a href="${t}service.php">خدمات</a> ·
                    <a href="${t}shop.php">فروشگاه</a> ·
                    <a href="${t}dev.php">پشتیبان</a>
                </span>
            </footer>
        </div>`}_bindReveal(){const e=this.root.querySelector("#hl-header"),t=()=>e==null?void 0:e.classList.toggle("hl-header--scrolled",window.scrollY>12);if(window.addEventListener("scroll",t,{passive:!0}),t(),"IntersectionObserver"in window){const s=new IntersectionObserver(a=>{a.forEach(i=>{i.isIntersecting&&i.target.classList.add("is-in")})},{threshold:.12});this.root.querySelectorAll(".hl-reveal").forEach(a=>s.observe(a))}else this.root.querySelectorAll(".hl-reveal").forEach(s=>s.classList.add("is-in"))}_bindAuthTabs(){var s,a,i,n,r;const e=this.root.querySelector("#lp-auth-panel"),t=()=>{e==null||e.classList.add("lp-auth-panel--open"),this._switchTab("login"),e==null||e.scrollIntoView({behavior:"smooth",block:"nearest"})};(s=this.root.querySelector("#lp-open-auth"))==null||s.addEventListener("click",()=>{e==null||e.classList.toggle("lp-auth-panel--open")}),(a=this.root.querySelector("#lp-hero-auth"))==null||a.addEventListener("click",t),(i=this.root.querySelector("#hl-cta-erp"))==null||i.addEventListener("click",t),(n=this.root.querySelector("#hl-open-erp"))==null||n.addEventListener("click",t),this.root.querySelectorAll("[data-tab]").forEach(o=>{o.addEventListener("click",()=>this._switchTab(o.dataset.tab))}),(r=this.root.querySelector("#lp-pass-toggle"))==null||r.addEventListener("click",()=>{const o=this.root.querySelector("#lp-pass-input");o&&(o.type=o.type==="password"?"text":"password")})}_switchTab(e){this._tab=e,this.root.querySelectorAll(".lp-auth-tab").forEach(t=>t.classList.toggle("active",t.dataset.tab===e)),this.root.querySelectorAll(".lp-form").forEach(t=>t.classList.toggle("lp-form--hidden",t.id!==`lp-form-${e}`))}_bindAuthForms(){var e,t,s;(e=this.root.querySelector("#lp-form-login"))==null||e.addEventListener("submit",a=>{a.preventDefault(),this._doLogin(a.target)}),(t=this.root.querySelector("#lp-form-register"))==null||t.addEventListener("submit",a=>{a.preventDefault(),this._doRegister(a.target)}),(s=this.root.querySelector("#lp-form-forgot"))==null||s.addEventListener("submit",a=>{a.preventDefault(),this._doForgot(a.target)})}async _doLogin(e){const t=this.root.querySelector("#lp-msg-login"),s=Object.fromEntries(new FormData(e));this._setMsg(t,"",""),this._setBusy(e,!0);try{const a=await this._post("/public/auth/login",{username:s.username,password:s.password});if(a.success&&a.token){sessionStorage.setItem("acc_token",a.token);const i=new URLSearchParams(window.location.search).get("tab")||sessionStorage.getItem("acc_pending_tab");i&&sessionStorage.setItem("acc_pending_tab",i);const n={user:a.user,token:a.token,isCustomLogin:!0};this.store.set("session",n),this.eventBus.emit("auth:login:success",n)}else this._setMsg(t,a.message||"ورود ناموفق بود.","error")}catch(a){this._setMsg(t,a.message||"خطا در ورود","error")}finally{this._setBusy(e,!1)}}async _doRegister(e){const t=this.root.querySelector("#lp-msg-register"),s=Object.fromEntries(new FormData(e));if(s.password!==s.password2)return this._setMsg(t,"رمز عبور و تکرار آن یکسان نیستند.","error");this._setMsg(t,"",""),this._setBusy(e,!0);try{const a=await this._post("/public/auth/register",s);a.success?(this._setMsg(t,a.message||"حساب ایجاد شد. اکنون وارد شوید.","ok"),this._switchTab("login")):this._setMsg(t,a.message||"ثبت‌نام ناموفق","error")}catch(a){this._setMsg(t,a.message||"خطا","error")}finally{this._setBusy(e,!1)}}async _doForgot(e){const t=this.root.querySelector("#lp-msg-forgot"),s=Object.fromEntries(new FormData(e));this._setMsg(t,"",""),this._setBusy(e,!0);try{const a=await this._post("/public/auth/forgot",s);this._setMsg(t,a.message||"در صورت وجود حساب، لینک ارسال می‌شود.","ok")}catch(a){this._setMsg(t,a.message||"خطا","error")}finally{this._setBusy(e,!1)}}async _post(e,t){var n,r;if((n=this.api)!=null&&n.post)return this.api.post(e.replace(/^\//,""),t);const s=(((r=window.ACC_CONFIG)==null?void 0:r.api)||"/acc-engine/api.php/acc/v1").replace(/\/$/,""),a=await fetch(`${s}/${e.replace(/^\//,"")}`,{method:"POST",headers:{"Content-Type":"application/json",Accept:"application/json"},body:JSON.stringify(t)}),i=await a.json().catch(()=>({}));if(!a.ok)throw new Error(i.message||`HTTP ${a.status}`);return i}_setMsg(e,t,s){e&&(e.textContent=t||"",e.className="lp-msg"+(s==="error"?" lp-msg--error":s==="ok"?" lp-msg--ok":""))}_setBusy(e,t){const s=e==null?void 0:e.querySelector('[type="submit"]');s&&(s.disabled=!!t)}}class Ba{constructor(){this._loaded=!1,this._loadPromise=null,this._api=null,this.userId=null,this.roles=[],this.permissions=new Map,this.menus=[],this.scopes={},this._listeners=new Set}async load(e){return this._loaded?this:this._loadPromise?this._loadPromise:(this._api=e,this._loadPromise=this._fetchMe(),await this._loadPromise,this._loadPromise=null,this)}async refresh(){return this._loaded=!1,this.permissions.clear(),this.roles=[],this.menus=[],this.scopes={},this.load(this._api)}async _fetchMe(){try{const e=await this._api.get("/acl/me");this.userId=(e==null?void 0:e.user_id)??null,this.roles=(e==null?void 0:e.roles)??[],this.menus=(e==null?void 0:e.menus)??[],this.scopes=(e==null?void 0:e.scopes)??{},this.permissions.clear();for(const t of(e==null?void 0:e.permissions)??[]){this.permissions.has(t.key)||this.permissions.set(t.key,new Set);const s=t.scope_type==="global"||!t.scope_id?"*":`${t.scope_type}:${t.scope_id}`;this.permissions.get(t.key).add(s)}this._loaded=!0,this._notify()}catch(e){console.warn("AclService.load failed",e),this._loaded=!0}}can(e,t=null,s=null){if(!this._loaded)return!1;const a=this.permissions.get(e);return a?a.has("*")?!0:t&&s!==null?a.has(`${t}:${s}`):!1:!1}cannot(e,t=null,s=null){return!this.can(e,t,s)}hasRole(e){return this.roles.some(t=>t.slug===e)}isSuperAdmin(){return this.hasRole("super_admin")}filterByPermission(e,t="requiredPermission"){return e.filter(s=>{const a=s[t]??s.permission??null;return!a||this.can(a)})}filterScopeList(e,t="warehouse",s="id"){var n;const a=(n=this.scopes)==null?void 0:n[t];if(!a||a.unrestricted)return e;const i=new Set((a.ids??[]).map(Number));return(e??[]).filter(r=>i.has(+r[s]))}hasUnrestrictedScope(e="warehouse"){var t,s;return!!((s=(t=this.scopes)==null?void 0:t[e])!=null&&s.unrestricted)}onUpdate(e){return this._listeners.add(e),()=>this._listeners.delete(e)}_notify(){this._listeners.forEach(e=>{try{e(this)}catch(t){console.warn("acl listener",t)}})}}const L=new Ba;typeof window<"u"&&(window.acl=L);class za{constructor(){this.configs=new Map}register(e){if(!e.key)throw new Error("TabConfig must have a 'key'");this.configs.set(e.key,e)}get(e){return this.configs.get(e)}getAll(){return Array.from(this.configs.values())}getDefaults(){return this.getAll().filter(e=>e.fixed).sort((e,t)=>(e.sortOrder||0)-(t.sortOrder||0))}}class ja{constructor(){this.byTabKey=new Map,this.byModuleView=new Map}registerByTabKey(e,t){this.byTabKey.set(e,t)}registerByModuleView(e,t,s){this.byModuleView.set(`${e}:${t}`,s)}getByTabKey(e){return this.byTabKey.get(e)}getByModuleView(e,t){return this.byModuleView.get(`${e}:${t}`)}register(e,t){this.registerByTabKey(e,t)}}class Aa{constructor(e){this.registry=e,this._cache=new Map}async resolve(e,t){if(!e)throw new Error("ViewResolver: tabKey is required");if(this._cache.has(e))return this._cache.get(e);let s=this.registry.getByTabKey(e);if(!s&&t&&t.module&&t.view&&(s=this.registry.getByModuleView(t.module,t.view)),!s)throw new Error(`ViewResolver: view not registered for key "${e}"`);let a;if(typeof s=="function"&&!s.prototype){const i=await s();a=i.default||i}else a=s;return this._cache.set(e,a),a}}const Pt=new za,E=new ja,Fa=new Aa(E);[{key:"sidebar",title:"منو",module:"core",view:"sidebar",icon:"dashicons-menu",fixed:!0,order:0},{key:"dashboard",title:"دشبورد",module:"core",view:"dashboard",icon:"dashicons-chart-bar",fixed:!1,order:1},{key:"users",title:"لیست کاربران",module:"users",view:"UsersListView",icon:"dashicons-groups",fixed:!1,sortOrder:10,persist:!1},{key:"projectsAuo",title:"لیست پروژه‌ها",module:"projects",view:"ProjectsRuntimeView",icon:"dashicons-portfolio",fixed:!1,sortOrder:20,persist:!1},{key:"cpm",title:"📊 کنترل پروژه",icon:"📊",fixed:!1,persist:!1},{key:"accounting",title:"📦 حسابداری",icon:"📦",fixed:!1,persist:!1},{key:"sales",title:"🧾 فروش",icon:"🧾",fixed:!1,persist:!1},{key:"purchase",title:"🛒 خرید",icon:"🛒",fixed:!1,persist:!1},{key:"payroll",title:"👨‍💼 حقوق",icon:"👨‍💼",fixed:!1,persist:!1},{key:"access",title:"🛡️ دسترسی‌ها",icon:"🛡️",fixed:!1,persist:!1},{key:"roleeditor",title:"🛡️ تب ویرایش دسترسی",icon:"🛡️",fixed:!1,persist:!1},{key:"basesetpermission",title:"🔐 Base Set Permissions",icon:"🔐",fixed:!1,persist:!1},{key:"tree",title:"🌳 درخت",view:"tree-view",icon:"🌳",fixed:!1,persist:!1},{key:"lands",title:"🌳 زمین",view:"lands-view",icon:"🌳",fixed:!1,persist:!1},{key:"manager",title:"📋 مدیریت وردپرس",view:"menu-manager-view",icon:"📋",fixed:!1,persist:!1},{key:"gis",title:"🗺️ نقشه هوشمند",icon:"🗺️",fixed:!1,persist:!1},{key:"contracts",title:"📋 قراردادها",icon:"📋",fixed:!1,persist:!1},{key:"unitsales",title:"🏢 فروش واحد",icon:"🏢",fixed:!1,persist:!1},{key:"treasury",title:"💰 خزانه پروژه",icon:"💰",fixed:!1,persist:!1},{key:"permits",title:"📋 مجوزها",icon:"📋",fixed:!1,persist:!1},{key:"crm",title:"🎯 CRM",icon:"🎯",fixed:!1,persist:!1},{key:"inventory",title:"🏭 انبار",icon:"🏭",fixed:!1,persist:!1},{key:"acl",title:"🛡️ مدیریت دسترسی‌ها",icon:"🛡️",fixed:!1,persist:!1},{key:"hr",title:"👨‍💼 نیروی انسانی",icon:"👨‍💼",fixed:!1,persist:!1},{key:"shipping",title:"🚚 حمل و نقل",icon:"🚚",fixed:!1,persist:!1},{key:"assets",title:"🏢 مدیریت اموال",icon:"🏢",fixed:!1,persist:!1},{key:"commission",title:"🔨 کمیسیون ماده ۱۰۰",icon:"🔨",fixed:!1,persist:!1},{key:"workflow",title:"🔄 Workflow پروژه‌ها",icon:"🔄",fixed:!1,persist:!1},{key:"wpproducts",title:"🛍️ محصولات فروشگاه",icon:"🛍️",fixed:!1,persist:!1},{key:"chat",title:"💬 چت و پشتیبانی",icon:"💬",fixed:!1,persist:!1},{key:"service",title:"🔧 خدمات میدانی",icon:"🔧",fixed:!1,persist:!1},{key:"realestate",title:"🏘️ داشبورد املاک",icon:"🏘️",fixed:!1,persist:!1},{key:"usedash",title:"🧭 داشبورد کاربری",icon:"🧭",fixed:!1,persist:!1},{key:"projects-manager",title:"📁 مدیریت پروژه‌ها",icon:"📁",fixed:!1,persist:!1},{key:"eqtesad_melk",title:"🏛️ اقتصاد ملک",icon:"🏛️",fixed:!1,persist:!1}].forEach(p=>Pt.register(p));let C=class{constructor({eventBus:e,store:t,tab:s}={}){this.eventBus=e||null,this.store=t||null,this.tab=s||null,this.container=null,this.el=null,this.$el=null,this.boundEvents=[],this.busEvents=[],this.refs={},this.isDestroyed=!1,this._eventsBound=!1}async render(e){if(!e)return console.error(`[BaseView] Render failed: container undefined (${this.constructor.name})`),this;this.container=e,this.el=e,typeof window.jQuery<"u"&&(this.$el=window.jQuery(e)),typeof this.beforeRender=="function"&&await this.beforeRender();const t=await this.template(),s=`
            ${this._renderModuleHeader()}
            <div class="view-body" data-ref="body">
                ${t||""}
            </div>
        `;this.container.innerHTML=s,this._bindRefs(),this._bindModuleHeaderEvents(),typeof this.afterRender=="function"&&await this.afterRender(),!this._eventsBound&&typeof this.bindEvents=="function"&&(this.bindEvents(),this._eventsBound=!0);try{this.applyAclToDom()}catch{}return this}async mount(e){return this.render(e)}async template(){return"<div>در حال واکشی اطلاعات</div>"}_renderModuleHeader(){var r,o,l,c,d,h,u;const e=this.constructor.title||((r=this.tab)==null?void 0:r.title)||"",t=((o=this.tab)==null?void 0:o.fixed)??!1,s=((l=this.tab)==null?void 0:l.userContext)??null,a=((h=(d=(c=this.store)==null?void 0:c.get)==null?void 0:d.call(c,"auth"))==null?void 0:h.user)??null;let i="";s?i=s.display_name||s.fullname||s.username||"":a&&(i=a.display_name||a.username||"");let n="";try{if((u=L==null?void 0:L.roles)!=null&&u.length){const f=L.roles[0],b={super_admin:"#dc2626",manager:"#7c3aed",accountant:"#0891b2",warehouse_keeper:"#ea580c",sales_user:"#16a34a",purchase_user:"#0d9488",gis_user:"#2563eb",project_manager:"#c026d3",viewer:"#64748b"}[f.slug]||"#475569";n=`<span class="bv-hdr__role" style="background:${b}22;color:${b};border:1px solid ${b}44;">${this.escape(f.name)}</span>`}}catch{}return`
        <div class="bv-hdr">
            <span class="bv-hdr__title">${this.escape(e)}</span>
            <div class="bv-hdr__user">
                ${i?`<span class="bv-hdr__uname">👤 ${this.escape(i)}</span>`:""}
                ${n}
            </div>
            <div class="bv-hdr__actions">
                <button class="bv-hdr__btn bv-hdr__btn--refresh" data-ref="bvRefresh" title="بارگذاری مجدد">⟳</button>
                ${t?"":'<button class="bv-hdr__btn bv-hdr__btn--close" data-ref="bvClose" title="بستن تب">×</button>'}
            </div>
        </div>`}_bindModuleHeaderEvents(){var s;const e=this.ref("bvRefresh"),t=this.ref("bvClose");e&&this.eventBus&&this.on(e,"click",()=>{this.eventBus.emit("tabs:refreshActive")}),t&&this.eventBus&&((s=this.tab)!=null&&s.id)&&this.on(t,"click",()=>{this.eventBus.emit("tabs:closeById",this.tab.id)})}_updateTabbarRight(){var l,c,d,h,u;const e=document.getElementById("acc-tabbar-right");if(!e)return;const t=this.constructor.title||"",s=((l=this.tab)==null?void 0:l.userContext)??null,a=((h=(d=(c=this.store)==null?void 0:c.get)==null?void 0:d.call(c,"auth"))==null?void 0:h.user)??null;let i="system",n=null;s?typeof s=="string"?i=s:(i=s.display_name||s.fullname||s.username||"system",n=s.id||null):a&&(i=a.display_name||a.username||"system",n=a.id||null);let r="";try{if((u=L==null?void 0:L.roles)!=null&&u.length){const f=L.roles[0],b={super_admin:"#dc2626",manager:"#7c3aed",accountant:"#0891b2",warehouse_keeper:"#ea580c",sales_user:"#16a34a",purchase_user:"#0d9488",gis_user:"#2563eb",project_manager:"#c026d3",viewer:"#64748b"}[f.slug]||"#475569";r=`<span class="tbr-role" style="background:${b}22;color:${b};border:1px solid ${b}55;">${this.escape(f.name)}</span>`}}catch{}e.innerHTML=`
            ${t?`<span class="tbr-title">${this.escape(t)}</span>`:""}
            <span class="tbr-user">👤 ${this.escape(i)}${n?` <small>(#${n})</small>`:""}</span>
            ${r}
            <button class="tbr-switch" data-ref="switchUserBtn" title="تغییر کاربر">⚙</button>
        `;const o=e.querySelector(".tbr-switch");o&&this.eventBus&&o.addEventListener("click",()=>{var f;this.eventBus.emit("view:switchUser",{view:this,user:((f=this.tab)==null?void 0:f.userContext)||null})})}_renderRoleBadges(){var e;try{if(!((e=L==null?void 0:L.roles)!=null&&e.length))return"";const t={super_admin:"#dc2626",manager:"#7c3aed",accountant:"#0891b2",warehouse_keeper:"#ea580c",sales_user:"#16a34a",purchase_user:"#0d9488",gis_user:"#2563eb",project_manager:"#c026d3",viewer:"#64748b"};return`<span class="view-roles" style="display:inline-flex;flex-wrap:wrap;gap:2px;margin-right:8px;">${L.roles.map(a=>{const i=t[a.slug]||"#475569",n=a.scope_type==="global"?"":`<small style="opacity:.7;margin-right:3px;">[${a.scope_type}${a.scope_id?":"+a.scope_id:""}]</small>`;return`<span class="view-role-badge" style="background:${i}1a;color:${i};border:1px solid ${i}55;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;margin-right:4px;" title="نقش: ${this.escape(a.name)} | scope: ${a.scope_type}">
                    🛡️ ${this.escape(a.name)}${n}
                </span>`}).join("")}</span>`}catch{return""}}_renderHeader(){var o,l,c,d,h;const e=this.constructor.title||"Untitled",t=((o=this.tab)==null?void 0:o.userContext)??null,s=((d=(c=(l=this.store)==null?void 0:l.get)==null?void 0:c.call(l,"auth"))==null?void 0:d.user)??null;let a="system",i=null;t?typeof t=="string"?a=t:typeof t=="object"&&(a=t.display_name||t.fullname||t.username||"system",i=t.id||null):s&&(a=s.display_name||s.username||"system",i=s.id||null);const n=((h=this.store)==null?void 0:h.get("context.project"))??null,r=n?`<span class="view-context-badge" data-ref="contextBadge" title="پروژه فعال فیلتر">
                   <span class="view-context-badge__label">📁 ${this.escape(n.title||n.name||"#"+n.id)}</span>
                   <button class="view-context-badge__clear" data-action="clear-context" aria-label="حذف فیلتر پروژه">✕</button>
               </span>`:'<span class="view-context-badge view-context-badge--empty" data-ref="contextBadge"></span>';return`
        <div class="view-header">

            <h2 class="view-title">${e}</h2>

            ${this.useContextBadge?r:""}

            <div class="view-user-context">

                <span class="user-name">
                    👤 ${a}
                    ${i?`<small class="user-id">(#${i})</small>`:""}
                </span>

                ${this._renderRoleBadges()}

                <button
                    class="switch-user-btn"
                    data-ref="switchUserBtn"
                    type="button"
                    title="تغییر کاربر"
                    aria-label="تغییر کاربر"
                >
                    <i class="fa-solid fa-user-gear" aria-hidden="true"></i>
                </button>

            </div>

        </div>`}_bindRefs(){if(!this.container)return;this.refs={},this.container.querySelectorAll("[data-ref]").forEach(t=>{const s=t.dataset.ref;s&&(this.refs[s]=t)})}ref(e){return this.refs[e]||null}on(e,t,s){!e||!t||!s||(e.addEventListener(t,s),this.boundEvents.push({element:e,event:t,handler:s}))}listen(e,t){if(!this.eventBus)return;const s=this.eventBus.on(e,t);s&&this.busEvents.push(s)}bindEvents(){const e=this.ref("switchUserBtn");if(e&&this.eventBus&&this.on(e,"click",()=>{var t;this.eventBus.emit("view:switchUser",{view:this,user:((t=this.tab)==null?void 0:t.userContext)||null})}),this.useContextBadge&&this.container){const t=this.container.querySelector("[data-action='clear-context']");t&&this.on(t,"click",s=>{var a;s.stopPropagation(),(a=this.store)==null||a.set("context.project",null)})}this.useContextBadge&&this.store&&this.listen("store:changed:context.project",()=>{this._refreshContextBadge()})}_refreshContextBadge(){var s;if(!this.container)return;const e=this.container.querySelector("[data-ref='contextBadge']");if(!e)return;const t=((s=this.store)==null?void 0:s.get("context.project"))??null;if(t){e.className="view-context-badge",e.innerHTML=`
                <span class="view-context-badge__label">📁 ${this.escape(t.title||t.name||"#"+t.id)}</span>
                <button class="view-context-badge__clear" data-action="clear-context" aria-label="حذف فیلتر پروژه">✕</button>`;const a=e.querySelector("[data-action='clear-context']");a&&this.on(a,"click",i=>{i.stopPropagation(),this.store.set("context.project",null)})}else e.className="view-context-badge view-context-badge--empty",e.innerHTML=""}destroy(){this.isDestroyed||(this.boundEvents.forEach(e=>{try{e.element.removeEventListener(e.event,e.handler)}catch{}}),this.busEvents.forEach(e=>{try{typeof e=="function"&&e()}catch{}}),this.boundEvents=[],this.busEvents=[],this.refs={},this.container=null,this.el=null,this.$el=null,this._eventsBound=!1,this.isDestroyed=!0)}api(){var e;return((e=this.tab)==null?void 0:e.api)||null}can(e,t=null,s=null){return L.can(e,t,s)}cannot(e,t=null,s=null){return!L.can(e,t,s)}applyAclToDom(e=null){const t=e||this.container;t&&t.querySelectorAll("[data-perm]").forEach(s=>{const a=s.dataset.perm;if(!a||L.can(a))return;(s.dataset.permMode||"hide")==="disable"?(s.setAttribute("disabled","disabled"),s.style.opacity="0.5",s.style.cursor="not-allowed",s.title="🚫 دسترسی ندارید"):s.style.display="none"})}getCache(e){var t,s,a;return(a=(s=(t=this.tab)==null?void 0:t.cache)==null?void 0:s.get)==null?void 0:a.call(s,e)}setCache(e,t){var s,a,i;(i=(a=(s=this.tab)==null?void 0:s.cache)==null?void 0:a.set)==null||i.call(a,e,t)}getContextProject(){var e;return((e=this.store)==null?void 0:e.get("context.project"))??null}onContextProjectChange(e){this.listen("store:changed:context.project",e)}escape(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}};class Ia extends C{constructor(e={}){super(e),this.api=e.api,this.constructor.title="اطلاعات کاربری",this.data=null,this.user=null,this.loading=!1}async render(e){return await super.render(e),await this.loadData(),this}async template(){return`

<style>

.acc-dashboard{
max-width:1200px;
margin:auto;
}

/* tabs */

.acc-tabs{
display:flex;
gap:6px;
border-bottom:1px solid #e5e7eb;
margin-bottom:16px;
}

.acc-tab{
padding:8px 14px;
font-size:13px;
cursor:pointer;
border-radius:6px 6px 0 0;
background:#f3f4f6;
}

.acc-tab.active{
background:#fff;
border:1px solid #e5e7eb;
border-bottom:none;
font-weight:600;
}

.acc-tab-panel{
display:none;
}

.acc-tab-panel.active{
display:block;
}

/* profile */

.acc-profile-card{
background:#fff;
border-radius:12px;
border:1px solid #e5e7eb;
padding:1.5rem;
box-shadow:0 4px 10px rgba(0,0,0,0.05);
}

.acc-profile-header{
display:flex;
align-items:center;
gap:12px;
margin-bottom:16px;
}

.acc-profile-avatar{
width:48px;
height:48px;
border-radius:50%;
background:#3b82f6;
color:#fff;
display:flex;
align-items:center;
justify-content:center;
font-weight:700;
font-size:18px;
}

.acc-profile-name{
font-weight:700;
font-size:15px;
}

.acc-profile-username{
font-size:12px;
color:#6b7280;
}

.acc-profile-body{
display:flex;
flex-direction:column;
gap:10px;
}

.acc-profile-row{
display:flex;
justify-content:space-between;
font-size:13px;
padding:6px 0;
border-bottom:1px dashed #eee;
}

/* permissions */

.acc-permission-accordion{
display:flex;
flex-direction:column;
gap:8px;
}

.acc-permission-item{
border:1px solid #e5e7eb;
border-radius:8px;
background:#fff;
overflow:hidden;
}

.acc-permission-header{
padding:10px 14px;
display:flex;
justify-content:space-between;
cursor:pointer;
background:#f9fafb;
font-weight:600;
font-size:13px;
}

.acc-permission-body{
display:none;
padding:12px 14px;
}

.acc-permission-item.open .acc-permission-body{
display:block;
}

.acc-permission-row{
display:flex;
justify-content:space-between;
padding:6px 0;
font-size:12px;
}

.acc-perm-badge{
background:#eff6ff;
color:#1d4ed8;
padding:2px 6px;
border-radius:4px;
font-size:11px;
margin-left:4px;
}

</style>

<div class="acc-dashboard">

<div class="view-header">
<div>
<h2 class="fw-bold mb-1">داشبورد کاربری</h2>
</div>

<button class="btn btn-outline-secondary btn-sm" data-ref="refreshBtn">
بروزرسانی
</button>
</div>

<div data-ref="alertBox"></div>

<!-- tabs -->

<div class="acc-tabs">

<div class="acc-tab active" data-tab="profile">
پروفایل
</div>

<div class="acc-tab" data-tab="access">
دسترسی‌ها
</div>

<div class="acc-tab" data-tab="future">
تب آینده
</div>

</div>

<!-- tab profile -->

<div class="acc-tab-panel active" data-panel="profile">

<div data-ref="profileSection">
${this.blockSkeleton(4)}
</div>

</div>

<!-- tab access -->

<div class="acc-tab-panel" data-panel="access">

<div data-ref="accessSection">
${this.blockSkeleton(6)}
</div>

</div>

<!-- future tab -->

<div class="acc-tab-panel" data-panel="future">

<div class="text-muted">
در این قسمت می‌توانید تب‌های جدید اضافه کنید
</div>

</div>

</div>
`}blockSkeleton(e=4){return`
<div class="placeholder-glow">
${Array.from({length:e}).map(()=>'<div class="placeholder col-12 mb-2" style="height:16px;"></div>').join("")}
</div>
`}async afterRender(){const e=this.ref("refreshBtn");e&&this.on(e,"click",()=>this.loadData(!0)),this.el.querySelectorAll(".acc-tab").forEach(t=>{t.addEventListener("click",()=>{this.el.querySelectorAll(".acc-tab").forEach(a=>a.classList.remove("active")),this.el.querySelectorAll(".acc-tab-panel").forEach(a=>a.classList.remove("active")),t.classList.add("active");const s=t.dataset.tab;this.el.querySelector('[data-panel="'+s+'"]').classList.add("active")})}),this.el.addEventListener("click",t=>{const s=t.target.closest(".acc-permission-header");if(!s)return;s.parentElement.classList.toggle("open")})}async loadData(e=!1){var s,a,i;if(this.loading&&!e)return;this.loading=!0;const t=this.ref("alertBox");t&&(t.innerHTML="");try{const n=await this.api.get("/dashboard");this.data=n;const r=((i=(a=(s=this.store)==null?void 0:s.get)==null?void 0:a.call(s,"auth"))==null?void 0:i.user)||null;this.user=n.user||r||null,this.renderProfile(this.user),this.renderAccess(n.my_access||[])}catch(n){console.error(n),t&&(t.innerHTML=`
<div class="alert alert-danger">
خطا در بارگذاری اطلاعات داشبورد
</div>
`)}finally{this.loading=!1}}renderProfile(e){const t=this.ref("profileSection");if(!t)return;if(!e){t.innerHTML='<div class="text-muted">کاربر یافت نشد</div>';return}const s=e.accj_role||null,a=s?s.name||s.code||"نقش":"بدون نقش",i=(e.username||"U").substring(0,2).toUpperCase();t.innerHTML=`

<div class="acc-profile-card">

<div class="acc-profile-header">

<div class="acc-profile-avatar">${this.escape(i)}</div>

<div>
<div class="acc-profile-name">
${this.escape(e.name||e.display_name||"کاربر")}
</div>

<div class="acc-profile-username">
${this.escape(e.username||"-")}
</div>
</div>

</div>

<div class="acc-profile-body">

<div class="acc-profile-row">
<span>ایمیل</span>
<strong>${this.escape(e.email||"-")}</strong>
</div>

<div class="acc-profile-row">
<span>نقش</span>
<strong>${this.escape(a)}</strong>
</div>

</div>

</div>

`}renderAccess(e){const t=this.ref("accessSection");if(!t)return;if(!e.length){t.innerHTML='<div class="text-muted">هیچ دسترسی ثبت نشده است</div>';return}const s={};e.forEach(a=>{const i=a.module||a.code||"module";s[i]||(s[i]=[]),s[i].push(a)}),t.innerHTML=`

<div class="acc-permission-accordion">

${Object.entries(s).map(([a,i])=>`

<div class="acc-permission-item">

<div class="acc-permission-header">
<span>${this.escape(a)}</span>
<span>▾</span>
</div>

<div class="acc-permission-body">

${i.map(n=>this.renderPermissionRow(n)).join("")}

</div>

</div>

`).join("")}

</div>

`}renderPermissionRow(e){const t=e.permissions||e.actions||[],s=e.menu_title||e.name||e.code||"آیتم";return`

<div class="acc-permission-row">

<span>${this.escape(s)}</span>

<div>
${t.map(a=>`
<span class="acc-perm-badge">
${a}
</span>
`).join("")}
</div>

</div>

`}escape(e){return e?String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;"):""}}E.registerByTabKey("dashboard",Ia);class Da extends C{constructor(e={}){super(e),this.api=e.api,this.constructor.title="سیستم منو هلدینگ",this.cacheKey="acc_sidebar_menus",this.cacheTTL=5*60*1e3,this.menuTree=[]}async render(e){await super.render(e);const t=this.ref("body");if(!t)return this;const s=await this.loadMenus();return this.menuTree=this.buildTree(s),t.innerHTML=`
            <div class="acc-menu-wrapper">
                ${this.renderLevel(this.menuTree,null)}
            </div>
        `,this.bindEvents(),this}async loadMenus(){var t,s;if(!(((s=(t=this.store)==null?void 0:t.get("session"))==null?void 0:s.token)||sessionStorage.getItem("acc_token")))return this.setCache([]),[];try{L._loaded||await L.load(this.api);const a=(L.menus??[]).map(i=>({id:i.id,parent_id:i.parent_key?this._findParentId(L.menus,i.parent_key):0,title:i.title,description:"",icon:i.icon,route:i.route}));if(a.length)return this.setCache(a),a}catch(a){console.error("ACL Load failed, switching to fallback menus:",a)}try{const a=await this.api.get("acl/menus"),i=Array.isArray(a)?a:Array.isArray(a==null?void 0:a.items)?a.items:Array.isArray(a==null?void 0:a.data)?a.data:[],n=i.map(r=>({id:r.id,parent_id:r.parent_id??(r.parent_key?this._findParentId(i,r.parent_key):0),title:r.title??r.name??"",description:r.description??"",icon:r.icon??"",route:r.route??r.url??""}));return this.setCache(n),n}catch(a){return console.error("Fallback menus load failed:",a),this.setCache([]),[]}}_findParentId(e,t){const s=e.find(a=>a.menu_key===t);return(s==null?void 0:s.id)??0}getCache(){try{const e=sessionStorage.getItem(this.cacheKey);if(!e)return null;const t=JSON.parse(e);return Date.now()>t.expire?(sessionStorage.removeItem(this.cacheKey),null):Array.isArray(t.data)?t.data:null}catch{return null}}setCache(e){try{const t={expire:Date.now()+this.cacheTTL,data:Array.isArray(e)?e:[]};sessionStorage.setItem(this.cacheKey,JSON.stringify(t))}catch{}}buildTree(e){const t={},s=[];return Array.isArray(e)?(e.forEach(a=>{a.children=[],t[a.id]=a}),e.forEach(a=>{a.parent_id&&t[a.parent_id]?t[a.parent_id].children.push(a):s.push(a)}),s):(console.warn("[SidebarView] buildTree called with non-array items:",e),s)}renderLevel(e,t=null){return`
            <div class="acc-card-grid">
                ${t?this.renderBackCard(t):""}
                ${this.renderTree(e)}
            </div>
        `}renderBackCard(e){const t=e.title||"";return`
            <div class="acc-card-item acc-card-back">
                <div class="acc-card-link"
                     data-back="1"
                     data-parent="${e.parent_id||0}">
                     
                    <span class="acc-card-title">برگشت به قبل</span>
    
                    <div class="acc-card-desc acc-back-desc">
                        با زدن این دکمه به مرحله قبل بر می گردید
                    </div>
    
                    <div class="acc-card-meta acc-back-parent">
                        بازگشت به: ${t}
                    </div>
    
                </div>
            </div>
        `}renderTree(e){return!Array.isArray(e)||e.length===0?`
                <div class="acc-card-item">
                    <div class="acc-card-link">
                        <span class="acc-card-title">هیچ منویی تعریف نشده است</span>
                    </div>
                </div>
            `:e.map(t=>{const s=t.children&&t.children.length>0,a=s?t.children.length:0;return`
                <div class="acc-card-item ${s?"has-children":""}">
                    
                    <div class="acc-card-link"
                         data-id="${t.id}"
                         data-route="${t.route||""}"
                         data-has-children="${s?"1":"0"}"
                    >
    
                        <!-- ردیف اول -->
                        <div class="acc-card-row acc-card-header">
                            ${t.icon?`<span class="acc-card-icon dashicons dashicons-${t.icon}"></span>`:""}
                            <span class="acc-card-title">${t.title}</span>
                        </div>
    
                        <!-- ردیف دوم -->
                        ${t.description?`
                            <div class="acc-card-desc">
                                ${t.description}
                            </div>
                        `:""}
    
                        <!-- ردیف سوم -->
                        ${s?`
                            <div class="acc-card-meta">
                                ${a} زیرمنو
                            </div>
                        `:""}
    
                    </div>
    
                </div>
            `}).join("")}findNode(e,t=this.menuTree){for(const s of t){if(s.id==e)return s;const a=this.findNode(e,s.children);if(a)return a}return null}bindEvents(){const e=document.querySelector(".acc-menu-wrapper");e&&e.addEventListener("click",t=>{var r,o,l;const s=t.target.closest(".acc-card-link");if(!s)return;if(s.dataset.back==="1"){const c=s.dataset.parent;if(!c||c==="0"){e.innerHTML=this.renderLevel(this.menuTree,null);return}const d=this.findNode(c);d&&(e.innerHTML=this.renderLevel(d.children,d));return}const a=s.dataset.id,i=s.dataset.hasChildren==="1",n=s.dataset.route;if(i){const c=this.findNode(a);e.innerHTML=this.renderLevel(c.children,c);return}if(n){const c={access:"acl",roles:"acl",permissions:"acl"},d=(r=E.getByTabKey)!=null&&r.call(E,n)?n:c[n]&&((o=E.getByTabKey)!=null&&o.call(E,c[n]))?c[n]:null;d?(l=this.eventBus)==null||l.emit("tab:open",{key:d}):(console.warn("ERP module view not registered:",n),alert("ماژول هنوز ثبت نشده: "+n))}})}}E.registerByTabKey("sidebar",Da);class j{constructor(e){this.table=e}reloadData(e,t,s){return this.table.dataLoader.load(e,void 0,void 0,void 0,t,s)}langText(){return this.table.modules.localize.getText(...arguments)}langBind(){return this.table.modules.localize.bind(...arguments)}langLocale(){return this.table.modules.localize.getLocale(...arguments)}commsConnections(){return this.table.modules.comms.getConnections(...arguments)}commsSend(){return this.table.modules.comms.send(...arguments)}layoutMode(){return this.table.modules.layout.getMode()}layoutRefresh(e){return this.table.modules.layout.layout(e)}subscribe(){return this.table.eventBus.subscribe(...arguments)}unsubscribe(){return this.table.eventBus.unsubscribe(...arguments)}subscribed(e){return this.table.eventBus.subscribed(e)}subscriptionChange(){return this.table.eventBus.subscriptionChange(...arguments)}dispatch(){return this.table.eventBus.dispatch(...arguments)}chain(){return this.table.eventBus.chain(...arguments)}confirm(){return this.table.eventBus.confirm(...arguments)}dispatchExternal(){return this.table.externalEvents.dispatch(...arguments)}subscribedExternal(e){return this.table.externalEvents.subscribed(e)}subscriptionChangeExternal(){return this.table.externalEvents.subscriptionChange(...arguments)}options(e){return this.table.options[e]}setOption(e,t){return typeof t<"u"&&(this.table.options[e]=t),this.table.options[e]}deprecationCheck(e,t,s){return this.table.deprecationAdvisor.check(e,t,s)}deprecationCheckMsg(e,t){return this.table.deprecationAdvisor.checkMsg(e,t)}deprecationMsg(e){return this.table.deprecationAdvisor.msg(e)}module(e){return this.table.module(e)}}class B{static elVisible(e){return!(e.offsetWidth<=0&&e.offsetHeight<=0)}static elOffset(e){var t=e.getBoundingClientRect();return{top:t.top+window.pageYOffset-document.documentElement.clientTop,left:t.left+window.pageXOffset-document.documentElement.clientLeft}}static retrieveNestedData(e,t,s){var a=e?t.split(e):[t],i=a.length,n;for(let r=0;r<i&&(s=s[a[r]],n=s,!!s);r++);return n}static deepClone(e,t,s=[]){var a={}.__proto__,i=[].__proto__;t||(t=Object.assign(Array.isArray(e)?[]:{},e));for(var n in e){let r=e[n],o,l;r!=null&&typeof r=="object"&&(r.__proto__===a||r.__proto__===i)&&(o=s.findIndex(c=>c.subject===r),o>-1?t[n]=s[o].copy:(l=Object.assign(Array.isArray(r)?[]:{},r),s.unshift({subject:r,copy:l}),t[n]=this.deepClone(r,l,s)))}return t}}let Pa=class Ca extends j{constructor(e,t,s){super(e),this.element=t,this.container=this._lookupContainer(),this.parent=s,this.reversedX=!1,this.childPopup=null,this.blurable=!1,this.blurCallback=null,this.blurEventsBound=!1,this.renderedCallback=null,this.visible=!1,this.hideable=!0,this.element.classList.add("tabulator-popup-container"),this.blurEvent=this.hide.bind(this,!1),this.escEvent=this._escapeCheck.bind(this),this.destroyBinding=this.tableDestroyed.bind(this),this.destroyed=!1}tableDestroyed(){this.destroyed=!0,this.hide(!0)}_lookupContainer(){var e=this.table.options.popupContainer;return typeof e=="string"?(e=document.querySelector(e),e||console.warn("Menu Error - no container element found matching selector:",this.table.options.popupContainer,"(defaulting to document body)")):e===!0&&(e=this.table.element),e&&!this._checkContainerIsParent(e)&&(e=!1,console.warn("Menu Error - container element does not contain this table:",this.table.options.popupContainer,"(defaulting to document body)")),e||(e=document.body),e}_checkContainerIsParent(e,t=this.table.element){return e===t?!0:t.parentNode?this._checkContainerIsParent(e,t.parentNode):!1}renderCallback(e){this.renderedCallback=e}containerEventCoords(e){var t=!(e instanceof MouseEvent),s=t?e.touches[0].pageX:e.pageX,a=t?e.touches[0].pageY:e.pageY;if(this.container!==document.body){let i=B.elOffset(this.container);s-=i.left,a-=i.top}return{x:s,y:a}}elementPositionCoords(e,t="right"){var s=B.elOffset(e),a,i,n;switch(this.container!==document.body&&(a=B.elOffset(this.container),s.left-=a.left,s.top-=a.top),t){case"right":i=s.left+e.offsetWidth,n=s.top-1;break;case"bottom":i=s.left,n=s.top+e.offsetHeight;break;case"left":i=s.left,n=s.top-1;break;case"top":i=s.left,n=s.top;break;case"center":i=s.left+e.offsetWidth/2,n=s.top+e.offsetHeight/2;break}return{x:i,y:n,offset:s}}show(e,t){var s,a,i,n,r;return this.destroyed||this.table.destroyed?this:(e instanceof HTMLElement?(i=e,r=this.elementPositionCoords(e,t),n=r.offset,s=r.x,a=r.y):typeof e=="number"?(n={top:0,left:0},s=e,a=t):(r=this.containerEventCoords(e),s=r.x,a=r.y,this.reversedX=!1),this.element.style.top=a+"px",this.element.style.left=s+"px",this.container.appendChild(this.element),typeof this.renderedCallback=="function"&&this.renderedCallback(),this._fitToScreen(s,a,i,n,t),this.visible=!0,this.subscribe("table-destroy",this.destroyBinding),this.element.addEventListener("mousedown",o=>{o.stopPropagation()}),this)}_fitToScreen(e,t,s,a,i){var n=this.container===document.body?document.documentElement.scrollTop:this.container.scrollTop;(e+this.element.offsetWidth>=this.container.offsetWidth||this.reversedX)&&(this.element.style.left="",s?this.element.style.right=this.container.offsetWidth-a.left+"px":this.element.style.right=this.container.offsetWidth-e+"px",this.reversedX=!0);let r=Math.max(this.container.offsetHeight,n?this.container.scrollHeight:0);if(t+this.element.offsetHeight>r)if(s)switch(i){case"bottom":this.element.style.top=parseInt(this.element.style.top)-this.element.offsetHeight-s.offsetHeight-1+"px";break;default:this.element.style.top=parseInt(this.element.style.top)-this.element.offsetHeight+s.offsetHeight+1+"px"}else this.element.style.height=r+"px"}isVisible(){return this.visible}hideOnBlur(e){return this.blurable=!0,this.visible&&(setTimeout(()=>{this.visible&&(this.table.rowManager.element.addEventListener("scroll",this.blurEvent),this.subscribe("cell-editing",this.blurEvent),document.body.addEventListener("click",this.blurEvent),document.body.addEventListener("contextmenu",this.blurEvent),document.body.addEventListener("mousedown",this.blurEvent),window.addEventListener("resize",this.blurEvent),document.body.addEventListener("keydown",this.escEvent),this.blurEventsBound=!0)},100),this.blurCallback=e),this}_escapeCheck(e){e.key==27&&this.hide()}blockHide(){this.hideable=!1}restoreHide(){this.hideable=!0}hide(e=!1){return this.visible&&this.hideable&&(this.blurable&&this.blurEventsBound&&(document.body.removeEventListener("keydown",this.escEvent),document.body.removeEventListener("click",this.blurEvent),document.body.removeEventListener("contextmenu",this.blurEvent),document.body.removeEventListener("mousedown",this.blurEvent),window.removeEventListener("resize",this.blurEvent),this.table.rowManager.element.removeEventListener("scroll",this.blurEvent),this.unsubscribe("cell-editing",this.blurEvent),this.blurEventsBound=!1),this.childPopup&&this.childPopup.hide(),this.parent&&(this.parent.childPopup=null),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.visible=!1,this.blurCallback&&!e&&this.blurCallback(),this.unsubscribe("table-destroy",this.destroyBinding)),this}child(e){return this.childPopup&&this.childPopup.hide(),this.childPopup=new Ca(this.table,e,this),this.childPopup}};class I extends j{constructor(e,t){super(e),this._handler=null}initialize(){}registerTableOption(e,t){this.table.optionsList.register(e,t)}registerColumnOption(e,t){this.table.columnManager.optionsList.register(e,t)}registerTableFunction(e,t){typeof this.table[e]>"u"?this.table[e]=(...s)=>(this.table.initGuard(e),t(...s)):console.warn("Unable to bind table function, name already in use",e)}registerComponentFunction(e,t,s){return this.table.componentFunctionBinder.bind(e,t,s)}registerDataHandler(e,t){this.table.rowManager.registerDataPipelineHandler(e,t),this._handler=e}registerDisplayHandler(e,t){this.table.rowManager.registerDisplayPipelineHandler(e,t),this._handler=e}displayRows(e){var t=this.table.rowManager.displayRows.length-1,s;if(this._handler&&(s=this.table.rowManager.displayPipeline.findIndex(a=>a.handler===this._handler),s>-1&&(t=s)),e&&(t=t+e),this._handler)return t>-1?this.table.rowManager.getDisplayRows(t):this.activeRows()}activeRows(){return this.table.rowManager.activeRows}refreshData(e,t){t||(t=this._handler),t&&this.table.rowManager.refreshActiveData(t,!1,e)}footerAppend(e){return this.table.footerManager.append(e)}footerPrepend(e){return this.table.footerManager.prepend(e)}footerRemove(e){return this.table.footerManager.remove(e)}popup(e,t){return new Pa(this.table,e,t)}alert(e,t){return this.table.alertManager.alert(e,t)}clearAlert(){return this.table.alertManager.clear()}}var Oa={method:"GET"};function Ge(p,e){var t=[];if(e=e||"",Array.isArray(p))p.forEach((a,i)=>{t=t.concat(Ge(a,e?e+"["+i+"]":i))});else if(typeof p=="object")for(var s in p)t=t.concat(Ge(p[s],e?e+"["+s+"]":s));else t.push({key:e,value:p});return t}function Na(p){var e=Ge(p),t=[];return e.forEach(function(s){t.push(encodeURIComponent(s.key)+"="+encodeURIComponent(s.value))}),t.join("&")}function Ot(p,e,t){return p&&t&&Object.keys(t).length&&(!e.method||e.method.toLowerCase()=="get")&&(e.method="get",p+=(p.includes("?")?"&":"?")+Na(t)),p}function Va(p,e,t){var s;return new Promise((a,i)=>{if(p=this.urlGenerator.call(this.table,p,e,t),e.method.toUpperCase()!="GET")if(s=typeof this.table.options.ajaxContentType=="object"?this.table.options.ajaxContentType:this.contentTypeFormatters[this.table.options.ajaxContentType],s){for(var n in s.headers)e.headers||(e.headers={}),typeof e.headers[n]>"u"&&(e.headers[n]=s.headers[n]);e.body=s.body.call(this,p,e,t)}else console.warn("Ajax Error - Invalid ajaxContentType value:",this.table.options.ajaxContentType);p?(typeof e.headers>"u"&&(e.headers={}),typeof e.headers.Accept>"u"&&(e.headers.Accept="application/json"),typeof e.headers["X-Requested-With"]>"u"&&(e.headers["X-Requested-With"]="XMLHttpRequest"),typeof e.mode>"u"&&(e.mode="cors"),e.mode=="cors"?(typeof e.headers.Origin>"u"&&(e.headers.Origin=window.location.origin),typeof e.credentials>"u"&&(e.credentials="same-origin")):typeof e.credentials>"u"&&(e.credentials="include"),fetch(p,e).then(r=>{r.ok?r.json().then(o=>{a(o)}).catch(o=>{i(o),console.warn("Ajax Load Error - Invalid JSON returned",o)}):(console.error("Ajax Load Error - Connection Error: "+r.status,r.statusText),i(r))}).catch(r=>{console.error("Ajax Load Error - Connection Error: ",r),i(r)})):(console.warn("Ajax Load Error - No URL Set"),a([]))})}function Ke(p,e){var t=[];if(e=e||"",Array.isArray(p))p.forEach((a,i)=>{t=t.concat(Ke(a,e?e+"["+i+"]":i))});else if(typeof p=="object")for(var s in p)t=t.concat(Ke(p[s],e?e+"["+s+"]":s));else t.push({key:e,value:p});return t}var Wa={json:{headers:{"Content-Type":"application/json"},body:function(p,e,t){return JSON.stringify(t)}},form:{headers:{},body:function(p,e,t){var s=Ke(t),a=new FormData;return s.forEach(function(i){a.append(i.key,i.value)}),a}}};const D=class D extends I{constructor(e){super(e),this.config={},this.url="",this.urlGenerator=!1,this.params=!1,this.loaderPromise=!1,this.registerTableOption("ajaxURL",!1),this.registerTableOption("ajaxURLGenerator",!1),this.registerTableOption("ajaxParams",{}),this.registerTableOption("ajaxConfig","get"),this.registerTableOption("ajaxContentType","form"),this.registerTableOption("ajaxRequestFunc",!1),this.registerTableOption("ajaxRequesting",function(){}),this.registerTableOption("ajaxResponse",!1),this.contentTypeFormatters=D.contentTypeFormatters}initialize(){this.loaderPromise=this.table.options.ajaxRequestFunc||D.defaultLoaderPromise,this.urlGenerator=this.table.options.ajaxURLGenerator||D.defaultURLGenerator,this.table.options.ajaxURL&&this.setUrl(this.table.options.ajaxURL),this.setDefaultConfig(this.table.options.ajaxConfig),this.registerTableFunction("getAjaxUrl",this.getUrl.bind(this)),this.subscribe("data-loading",this.requestDataCheck.bind(this)),this.subscribe("data-params",this.requestParams.bind(this)),this.subscribe("data-load",this.requestData.bind(this))}requestParams(e,t,s,a){var i=this.table.options.ajaxParams;return i&&(typeof i=="function"&&(i=i.call(this.table)),a=Object.assign(Object.assign({},i),a)),a}requestDataCheck(e,t,s,a){return!!(!e&&this.url||typeof e=="string")}requestData(e,t,s,a,i){var n;return!i&&this.requestDataCheck(e)?(e&&this.setUrl(e),n=this.generateConfig(s),this.sendRequest(this.url,t,n)):i}setDefaultConfig(e={}){this.config=Object.assign({},D.defaultConfig),typeof e=="string"?this.config.method=e:Object.assign(this.config,e)}generateConfig(e={}){var t=Object.assign({},this.config);return typeof e=="string"?t.method=e:Object.assign(t,e),t}setUrl(e){this.url=e}getUrl(){return this.url}sendRequest(e,t,s){return this.table.options.ajaxRequesting.call(this.table,e,t)!==!1?this.loaderPromise(e,s,t).then(a=>(this.table.options.ajaxResponse&&(a=this.table.options.ajaxResponse.call(this.table,e,t,a)),a)):Promise.reject()}};g(D,"moduleName","ajax"),g(D,"defaultConfig",Oa),g(D,"defaultURLGenerator",Ot),g(D,"defaultLoaderPromise",Va),g(D,"contentTypeFormatters",Wa);let Le=D;class Nt{constructor(e){return this._cell=e,new Proxy(this,{get:function(t,s,a){return typeof t[s]<"u"?t[s]:t._cell.table.componentFunctionBinder.handle("cell",t._cell,s)}})}getValue(){return this._cell.getValue()}getOldValue(){return this._cell.getOldValue()}getInitialValue(){return this._cell.initialValue}getElement(){return this._cell.getElement()}getRow(){return this._cell.row.getComponent()}getData(e){return this._cell.row.getData(e)}getType(){return"cell"}getField(){return this._cell.column.getField()}getColumn(){return this._cell.column.getComponent()}setValue(e,t){typeof t>"u"&&(t=!0),this._cell.setValue(e,t)}restoreOldValue(){this._cell.setValueActual(this._cell.getOldValue())}restoreInitialValue(){this._cell.setValueActual(this._cell.initialValue)}checkHeight(){this._cell.checkHeight()}getTable(){return this._cell.table}_getSelf(){return this._cell}}class Vt extends j{constructor(e,t){super(e.table),this.table=e.table,this.column=e,this.row=t,this.element=null,this.value=null,this.initialValue,this.oldValue=null,this.modules={},this.height=null,this.width=null,this.minWidth=null,this.component=null,this.loaded=!1,this.build()}build(){this.generateElement(),this.setWidth(),this._configureCell(),this.setValueActual(this.column.getFieldValue(this.row.data)),this.initialValue=this.value}generateElement(){this.element=document.createElement("div"),this.element.className="tabulator-cell",this.element.setAttribute("role","gridcell"),this.column.isRowHeader&&this.element.classList.add("tabulator-row-header")}_configureCell(){var e=this.element,t=this.column.getField(),s={top:"flex-start",bottom:"flex-end",middle:"center"},a={left:"flex-start",right:"flex-end",center:"center"};if(e.style.textAlign=this.column.hozAlign,this.column.vertAlign&&(e.style.display="inline-flex",e.style.alignItems=s[this.column.vertAlign]||"",this.column.hozAlign&&(e.style.justifyContent=a[this.column.hozAlign]||"")),t&&e.setAttribute("tabulator-field",t),this.column.definition.cssClass){var i=this.column.definition.cssClass.split(" ");i.forEach(n=>{e.classList.add(n)})}this.dispatch("cell-init",this),this.column.visible||this.hide()}_generateContents(){var e;switch(e=this.chain("cell-format",this,null,()=>this.element.innerHTML=this.value),typeof e){case"object":if(e instanceof Node){for(;this.element.firstChild;)this.element.removeChild(this.element.firstChild);this.element.appendChild(e)}else this.element.innerHTML="",e!=null&&console.warn("Format Error - Formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:",e);break;case"undefined":this.element.innerHTML="";break;default:this.element.innerHTML=e}}cellRendered(){this.dispatch("cell-rendered",this)}getElement(e){return this.loaded||(this.loaded=!0,e||this.layoutElement()),this.element}getValue(){return this.value}getOldValue(){return this.oldValue}setValue(e,t,s){var a=this.setValueProcessData(e,t,s);a&&(this.dispatch("cell-value-updated",this),this.cellRendered(),this.column.definition.cellEdited&&this.column.definition.cellEdited.call(this.table,this.getComponent()),this.dispatchExternal("cellEdited",this.getComponent()),this.subscribedExternal("dataChanged")&&this.dispatchExternal("dataChanged",this.table.rowManager.getData()))}setValueProcessData(e,t,s){var a=!1;return(this.value!==e||s)&&(a=!0,t&&(e=this.chain("cell-value-changing",[this,e],null,e))),this.setValueActual(e),a&&this.dispatch("cell-value-changed",this),a}setValueActual(e){this.oldValue=this.value,this.value=e,this.dispatch("cell-value-save-before",this),this.column.setFieldValue(this.row.data,e),this.dispatch("cell-value-save-after",this),this.loaded&&this.layoutElement()}layoutElement(){this._generateContents(),this.dispatch("cell-layout",this)}setWidth(){this.width=this.column.width,this.element.style.width=this.column.widthStyled}clearWidth(){this.width="",this.element.style.width=""}getWidth(){return this.width||this.element.offsetWidth}setMinWidth(){this.minWidth=this.column.minWidth,this.element.style.minWidth=this.column.minWidthStyled}setMaxWidth(){this.maxWidth=this.column.maxWidth,this.element.style.maxWidth=this.column.maxWidthStyled}checkHeight(){this.row.reinitializeHeight()}clearHeight(){this.element.style.height="",this.height=null,this.dispatch("cell-height",this,"")}setHeight(){this.height=this.row.height,this.element.style.height=this.row.heightStyled,this.dispatch("cell-height",this,this.row.heightStyled)}getHeight(){return this.height||this.element.offsetHeight}show(){this.element.style.display=this.column.vertAlign?"inline-flex":""}hide(){this.element.style.display="none"}delete(){this.dispatch("cell-delete",this),!this.table.rowManager.redrawBlock&&this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.element=!1,this.column.deleteCell(this),this.row.deleteCell(this),this.calcs={}}getIndex(){return this.row.getCellIndex(this)}getComponent(){return this.component||(this.component=new Nt(this)),this.component}}class Wt{constructor(e){return this._column=e,this.type="ColumnComponent",new Proxy(this,{get:function(t,s,a){return typeof t[s]<"u"?t[s]:t._column.table.componentFunctionBinder.handle("column",t._column,s)}})}getElement(){return this._column.getElement()}getDefinition(){return this._column.getDefinition()}getField(){return this._column.getField()}getTitleDownload(){return this._column.getTitleDownload()}getCells(){var e=[];return this._column.cells.forEach(function(t){e.push(t.getComponent())}),e}isVisible(){return this._column.visible}show(){this._column.isGroup?this._column.columns.forEach(function(e){e.show()}):this._column.show()}hide(){this._column.isGroup?this._column.columns.forEach(function(e){e.hide()}):this._column.hide()}toggle(){this._column.visible?this.hide():this.show()}delete(){return this._column.delete()}getSubColumns(){var e=[];return this._column.columns.length&&this._column.columns.forEach(function(t){e.push(t.getComponent())}),e}getParentColumn(){return this._column.getParentComponent()}_getSelf(){return this._column}scrollTo(e,t){return this._column.table.columnManager.scrollToColumn(this._column,e,t)}getTable(){return this._column.table}move(e,t){var s=this._column.table.columnManager.findColumn(e);s?this._column.table.columnManager.moveColumn(this._column,s,t):console.warn("Move Error - No matching column found:",s)}getNextColumn(){var e=this._column.nextColumn();return e?e.getComponent():!1}getPrevColumn(){var e=this._column.prevColumn();return e?e.getComponent():!1}updateDefinition(e){return this._column.updateDefinition(e)}getWidth(){return this._column.getWidth()}setWidth(e){var t;return e===!0?t=this._column.reinitializeWidth(!0):t=this._column.setWidth(e),this._column.table.columnManager.rerenderColumns(!0),t}}var Ut={title:void 0,field:void 0,columns:void 0,visible:void 0,hozAlign:void 0,vertAlign:void 0,width:void 0,minWidth:40,maxWidth:void 0,maxInitialWidth:void 0,cssClass:void 0,variableHeight:void 0,headerVertical:void 0,headerHozAlign:void 0,headerWordWrap:!1,editableTitle:void 0};const Z=class Z extends j{constructor(e,t,s){super(t.table),this.definition=e,this.parent=t,this.type="column",this.columns=[],this.cells=[],this.isGroup=!1,this.isRowHeader=s,this.element=this.createElement(),this.contentElement=!1,this.titleHolderElement=!1,this.titleElement=!1,this.groupElement=this.createGroupElement(),this.hozAlign="",this.vertAlign="",this.field="",this.fieldStructure="",this.getFieldValue="",this.setFieldValue="",this.titleDownload=null,this.titleFormatterRendered=!1,this.mapDefinitions(),this.setField(this.definition.field),this.modules={},this.width=null,this.widthStyled="",this.maxWidth=null,this.maxWidthStyled="",this.maxInitialWidth=null,this.minWidth=null,this.minWidthStyled="",this.widthFixed=!1,this.visible=!0,this.component=null,this.definition.columns?(this.isGroup=!0,this.definition.columns.forEach((a,i)=>{var n=new Z(a,this);this.attachColumn(n)}),this.checkColumnVisibility()):t.registerColumnField(this),this._initialize()}createElement(){var e=document.createElement("div");switch(e.classList.add("tabulator-col"),e.setAttribute("role","columnheader"),e.setAttribute("aria-sort","none"),this.isRowHeader&&e.classList.add("tabulator-row-header"),this.table.options.columnHeaderVertAlign){case"middle":e.style.justifyContent="center";break;case"bottom":e.style.justifyContent="flex-end";break}return e}createGroupElement(){var e=document.createElement("div");return e.classList.add("tabulator-col-group-cols"),e}mapDefinitions(){var e=this.table.options.columnDefaults;if(e)for(let t in e)typeof this.definition[t]>"u"&&(this.definition[t]=e[t]);this.definition=this.table.columnManager.optionsList.generate(Z.defaultOptionList,this.definition)}checkDefinition(){Object.keys(this.definition).forEach(e=>{Z.defaultOptionList.indexOf(e)===-1&&console.warn("Invalid column definition option in '"+(this.field||this.definition.title)+"' column:",e)})}setField(e){this.field=e,this.fieldStructure=e?this.table.options.nestedFieldSeparator?e.split(this.table.options.nestedFieldSeparator):[e]:[],this.getFieldValue=this.fieldStructure.length>1?this._getNestedData:this._getFlatData,this.setFieldValue=this.fieldStructure.length>1?this._setNestedData:this._setFlatData}registerColumnPosition(e){this.parent.registerColumnPosition(e)}registerColumnField(e){this.parent.registerColumnField(e)}reRegisterPosition(){this.isGroup?this.columns.forEach(function(e){e.reRegisterPosition()}):this.registerColumnPosition(this)}_initialize(){for(var e=this.definition;this.element.firstChild;)this.element.removeChild(this.element.firstChild);e.headerVertical&&(this.element.classList.add("tabulator-col-vertical"),e.headerVertical==="flip"&&this.element.classList.add("tabulator-col-vertical-flip")),this.contentElement=this._buildColumnHeaderContent(),this.element.appendChild(this.contentElement),this.isGroup?this._buildGroupHeader():this._buildColumnHeader(),this.dispatch("column-init",this)}_buildColumnHeader(){var e=this.definition;if(this.dispatch("column-layout",this),typeof e.visible<"u"&&(e.visible?this.show(!0):this.hide(!0)),e.cssClass){var t=e.cssClass.split(" ");t.forEach(s=>{this.element.classList.add(s)})}e.field&&this.element.setAttribute("tabulator-field",e.field),this.setMinWidth(parseInt(e.minWidth)),e.maxInitialWidth&&(this.maxInitialWidth=parseInt(e.maxInitialWidth)),e.maxWidth&&this.setMaxWidth(parseInt(e.maxWidth)),this.reinitializeWidth(),this.hozAlign=this.definition.hozAlign,this.vertAlign=this.definition.vertAlign,this.titleElement.style.textAlign=this.definition.headerHozAlign}_buildColumnHeaderContent(){var e=document.createElement("div");return e.classList.add("tabulator-col-content"),this.titleHolderElement=document.createElement("div"),this.titleHolderElement.classList.add("tabulator-col-title-holder"),e.appendChild(this.titleHolderElement),this.titleElement=this._buildColumnHeaderTitle(),this.titleHolderElement.appendChild(this.titleElement),e}_buildColumnHeaderTitle(){var e=this.definition,t=document.createElement("div");if(t.classList.add("tabulator-col-title"),e.headerWordWrap&&t.classList.add("tabulator-col-title-wrap"),e.editableTitle){var s=document.createElement("input");s.classList.add("tabulator-title-editor"),s.addEventListener("click",a=>{a.stopPropagation(),s.focus()}),s.addEventListener("mousedown",a=>{a.stopPropagation()}),s.addEventListener("change",()=>{e.title=s.value,this.dispatchExternal("columnTitleChanged",this.getComponent())}),t.appendChild(s),e.field?this.langBind("columns|"+e.field,a=>{s.value=a||e.title||"&nbsp;"}):s.value=e.title||"&nbsp;"}else e.field?this.langBind("columns|"+e.field,a=>{this._formatColumnHeaderTitle(t,a||e.title||"&nbsp;")}):this._formatColumnHeaderTitle(t,e.title||"&nbsp;");return t}_formatColumnHeaderTitle(e,t){var s=this.chain("column-format",[this,t,e],null,()=>t);switch(typeof s){case"object":s instanceof Node?e.appendChild(s):(e.innerHTML="",console.warn("Format Error - Title formatter has returned a type of object, the only valid formatter object return is an instance of Node, the formatter returned:",s));break;case"undefined":e.innerHTML="";break;default:e.innerHTML=s}}_buildGroupHeader(){if(this.element.classList.add("tabulator-col-group"),this.element.setAttribute("role","columngroup"),this.element.setAttribute("aria-title",this.definition.title),this.definition.cssClass){var e=this.definition.cssClass.split(" ");e.forEach(t=>{this.element.classList.add(t)})}this.titleElement.style.textAlign=this.definition.headerHozAlign,this.element.appendChild(this.groupElement)}_getFlatData(e){return e[this.field]}_getNestedData(e){var t=e,s=this.fieldStructure,a=s.length,i;for(let n=0;n<a&&(t=t[s[n]],i=t,!!t);n++);return i}_setFlatData(e,t){this.field&&(e[this.field]=t)}_setNestedData(e,t){var s=e,a=this.fieldStructure,i=a.length;for(let n=0;n<i;n++)if(n==i-1)s[a[n]]=t;else{if(!s[a[n]])if(typeof t<"u")s[a[n]]={};else break;s=s[a[n]]}}attachColumn(e){this.groupElement?(this.columns.push(e),this.groupElement.appendChild(e.getElement()),e.columnRendered()):console.warn("Column Warning - Column being attached to another column instead of column group")}verticalAlign(e,t){var s=this.parent.isGroup?this.parent.getGroupElement().clientHeight:t||this.parent.getHeadersElement().clientHeight;this.element.style.height=s+"px",this.dispatch("column-height",this,this.element.style.height),this.isGroup&&(this.groupElement.style.minHeight=s-this.contentElement.offsetHeight+"px"),this.columns.forEach(function(a){a.verticalAlign(e)})}clearVerticalAlign(){this.element.style.paddingTop="",this.element.style.height="",this.element.style.minHeight="",this.groupElement.style.minHeight="",this.columns.forEach(function(e){e.clearVerticalAlign()}),this.dispatch("column-height",this,"")}getElement(){return this.element}getGroupElement(){return this.groupElement}getField(){return this.field}getTitleDownload(){return this.titleDownload}getFirstColumn(){return this.isGroup?this.columns.length?this.columns[0].getFirstColumn():!1:this}getLastColumn(){return this.isGroup?this.columns.length?this.columns[this.columns.length-1].getLastColumn():!1:this}getColumns(e){var t=[];return e?this.columns.forEach(s=>{t.push(s),t=t.concat(s.getColumns(!0))}):t=this.columns,t}getCells(){return this.cells}getTopColumn(){return this.parent.isGroup?this.parent.getTopColumn():this}getDefinition(e){var t=[];return this.isGroup&&e&&(this.columns.forEach(function(s){t.push(s.getDefinition(!0))}),this.definition.columns=t),this.definition}checkColumnVisibility(){var e=!1;this.columns.forEach(function(t){t.visible&&(e=!0)}),e?(this.show(),this.dispatchExternal("columnVisibilityChanged",this.getComponent(),!1)):this.hide()}show(e,t){this.visible||(this.visible=!0,this.element.style.display="",this.parent.isGroup&&this.parent.checkColumnVisibility(),this.cells.forEach(function(s){s.show()}),!this.isGroup&&this.width===null&&this.reinitializeWidth(),this.table.columnManager.verticalAlignHeaders(),this.dispatch("column-show",this,t),e||this.dispatchExternal("columnVisibilityChanged",this.getComponent(),!0),this.parent.isGroup&&this.parent.matchChildWidths(),this.silent||this.table.columnManager.rerenderColumns())}hide(e,t){this.visible&&(this.visible=!1,this.element.style.display="none",this.table.columnManager.verticalAlignHeaders(),this.parent.isGroup&&this.parent.checkColumnVisibility(),this.cells.forEach(function(s){s.hide()}),this.dispatch("column-hide",this,t),e||this.dispatchExternal("columnVisibilityChanged",this.getComponent(),!1),this.parent.isGroup&&this.parent.matchChildWidths(),this.silent||this.table.columnManager.rerenderColumns())}matchChildWidths(){var e=0;this.contentElement&&this.columns.length&&(this.columns.forEach(function(t){t.visible&&(e+=t.getWidth())}),this.contentElement.style.maxWidth=e-1+"px",this.table.initialized&&(this.element.style.width=e+"px"),this.parent.isGroup&&this.parent.matchChildWidths())}removeChild(e){var t=this.columns.indexOf(e);t>-1&&this.columns.splice(t,1),this.columns.length||this.delete()}setWidth(e){this.widthFixed=!0,this.setWidthActual(e)}setWidthActual(e){isNaN(e)&&(e=Math.floor(this.table.element.clientWidth/100*parseInt(e))),e=Math.max(this.minWidth,e),this.maxWidth&&(e=Math.min(this.maxWidth,e)),this.width=e,this.widthStyled=e?e+"px":"",this.element.style.width=this.widthStyled,this.isGroup||this.cells.forEach(function(t){t.setWidth()}),this.parent.isGroup&&this.parent.matchChildWidths(),this.dispatch("column-width",this),this.subscribedExternal("columnWidth")&&this.dispatchExternal("columnWidth",this.getComponent())}checkCellHeights(){var e=[];this.cells.forEach(function(t){t.row.heightInitialized&&(t.row.getElement().offsetParent!==null?(e.push(t.row),t.row.clearCellHeight()):t.row.heightInitialized=!1)}),e.forEach(function(t){t.calcHeight()}),e.forEach(function(t){t.setCellHeight()})}getWidth(){var e=0;return this.isGroup?this.columns.forEach(function(t){t.visible&&(e+=t.getWidth())}):e=this.width,e}getLeftOffset(){var e=this.element.offsetLeft;return this.parent.isGroup&&(e+=this.parent.getLeftOffset()),e}getHeight(){return Math.ceil(this.element.getBoundingClientRect().height)}setMinWidth(e){this.maxWidth&&e>this.maxWidth&&(e=this.maxWidth,console.warn("the minWidth ("+e+"px) for column '"+this.field+"' cannot be bigger that its maxWidth ("+this.maxWidthStyled+")")),this.minWidth=e,this.minWidthStyled=e?e+"px":"",this.element.style.minWidth=this.minWidthStyled,this.cells.forEach(function(t){t.setMinWidth()})}setMaxWidth(e){this.minWidth&&e<this.minWidth&&(e=this.minWidth,console.warn("the maxWidth ("+e+"px) for column '"+this.field+"' cannot be smaller that its minWidth ("+this.minWidthStyled+")")),this.maxWidth=e,this.maxWidthStyled=e?e+"px":"",this.element.style.maxWidth=this.maxWidthStyled,this.cells.forEach(function(t){t.setMaxWidth()})}delete(){return new Promise((e,t)=>{this.isGroup&&this.columns.forEach(function(a){a.delete()}),this.dispatch("column-delete",this);var s=this.cells.length;for(let a=0;a<s;a++)this.cells[0].delete();this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.element=!1,this.contentElement=!1,this.titleElement=!1,this.groupElement=!1,this.parent.isGroup&&this.parent.removeChild(this),this.table.columnManager.deregisterColumn(this),this.table.columnManager.rerenderColumns(!0),this.dispatch("column-deleted",this),e()})}columnRendered(){this.titleFormatterRendered&&this.titleFormatterRendered(),this.dispatch("column-rendered",this)}generateCell(e){var t=new Vt(this,e);return this.cells.push(t),t}nextColumn(){var e=this.table.columnManager.findColumnIndex(this);return e>-1?this._nextVisibleColumn(e+1):!1}_nextVisibleColumn(e){var t=this.table.columnManager.getColumnByIndex(e);return!t||t.visible?t:this._nextVisibleColumn(e+1)}prevColumn(){var e=this.table.columnManager.findColumnIndex(this);return e>-1?this._prevVisibleColumn(e-1):!1}_prevVisibleColumn(e){var t=this.table.columnManager.getColumnByIndex(e);return!t||t.visible?t:this._prevVisibleColumn(e-1)}reinitializeWidth(e){this.widthFixed=!1,typeof this.definition.width<"u"&&!e&&this.setWidth(this.definition.width),this.dispatch("column-width-fit-before",this),this.fitToData(e),this.dispatch("column-width-fit-after",this)}fitToData(e){if(!this.isGroup){this.widthFixed||(this.element.style.width="",this.cells.forEach(a=>{a.clearWidth()}));var t=this.element.offsetWidth;if((!this.width||!this.widthFixed)&&(this.cells.forEach(a=>{var i=a.getWidth();i>t&&(t=i)}),t)){var s=t+1;e?this.setWidth(s):(this.maxInitialWidth&&!e&&(s=Math.min(s,this.maxInitialWidth)),this.setWidthActual(s))}}}updateDefinition(e){var t;return this.isGroup||this.parent.isGroup?(console.error("Column Update Error - The updateDefinition function is only available on ungrouped columns"),Promise.reject("Column Update Error - The updateDefinition function is only available on columns, not column groups")):(t=Object.assign({},this.getDefinition()),t=Object.assign(t,e),this.table.columnManager.addColumn(t,!1,this).then(s=>(t.field==this.field&&(this.field=!1),this.delete().then(()=>s.getComponent()))))}deleteCell(e){var t=this.cells.indexOf(e);t>-1&&this.cells.splice(t,1)}getComponent(){return this.component||(this.component=new Wt(this)),this.component}getPosition(){return this.table.columnManager.getVisibleColumnsByIndex().indexOf(this)+1}getParentComponent(){return this.parent instanceof Z?this.parent.getComponent():!1}};g(Z,"defaultOptionList",Ut);let te=Z;class Je{constructor(e){return this._row=e,new Proxy(this,{get:function(t,s,a){return typeof t[s]<"u"?t[s]:t._row.table.componentFunctionBinder.handle("row",t._row,s)}})}getData(e){return this._row.getData(e)}getElement(){return this._row.getElement()}getCells(){var e=[];return this._row.getCells().forEach(function(t){e.push(t.getComponent())}),e}getCell(e){var t=this._row.getCell(e);return t?t.getComponent():!1}getIndex(){return this._row.getData("data")[this._row.table.options.index]}getPosition(){return this._row.getPosition()}watchPosition(e){return this._row.watchPosition(e)}delete(){return this._row.delete()}scrollTo(e,t){return this._row.table.rowManager.scrollToRow(this._row,e,t)}move(e,t){this._row.moveToRow(e,t)}update(e){return this._row.updateData(e)}normalizeHeight(){this._row.normalizeHeight(!0)}_getSelf(){return this._row}reformat(){return this._row.reinitialize()}getTable(){return this._row.table}getNextRow(){var e=this._row.nextRow();return e&&e.getComponent()}getPrevRow(){var e=this._row.prevRow();return e&&e.getComponent()}}class Y extends j{constructor(e,t,s="row"){super(t.table),this.parent=t,this.data={},this.type=s,this.element=!1,this.modules={},this.cells=[],this.height=0,this.heightStyled="",this.manualHeight=!1,this.outerHeight=0,this.initialized=!1,this.heightInitialized=!1,this.position=0,this.positionWatchers=[],this.component=null,this.created=!1,this.setData(e)}create(){this.created||(this.created=!0,this.generateElement())}createElement(){var e=document.createElement("div");e.classList.add("tabulator-row"),e.setAttribute("role","row"),this.element=e}getElement(){return this.create(),this.element}detachElement(){this.element&&this.element.parentNode&&this.element.parentNode.removeChild(this.element)}generateElement(){this.createElement(),this.dispatch("row-init",this)}generateCells(){this.cells=this.table.columnManager.generateCells(this)}initialize(e,t){if(this.create(),!this.initialized||e){for(this.deleteCells();this.element.firstChild;)this.element.removeChild(this.element.firstChild);this.dispatch("row-layout-before",this),this.generateCells(),this.initialized=!0,this.table.columnManager.renderer.renderRowCells(this,t),e&&this.normalizeHeight(),this.dispatch("row-layout",this),this.table.options.rowFormatter&&this.table.options.rowFormatter(this.getComponent()),this.dispatch("row-layout-after",this)}else this.table.columnManager.renderer.rerenderRowCells(this,t)}rendered(){this.cells.forEach(e=>{e.cellRendered()})}reinitializeHeight(){this.heightInitialized=!1,this.element&&this.element.offsetParent!==null&&this.normalizeHeight(!0)}deinitialize(){this.initialized=!1}deinitializeHeight(){this.heightInitialized=!1}reinitialize(e){this.initialized=!1,this.heightInitialized=!1,this.manualHeight||(this.height=0,this.heightStyled=""),this.element&&this.element.offsetParent!==null&&this.initialize(!0),this.dispatch("row-relayout",this)}calcHeight(e){var t=0,s=0;this.table.options.rowHeight?this.height=this.table.options.rowHeight:(s=this.calcMinHeight(),t=this.calcMaxHeight(),e?this.height=Math.max(t,s):this.height=this.manualHeight?this.height:Math.max(t,s)),this.heightStyled=this.height?this.height+"px":"",this.outerHeight=this.element.offsetHeight}calcMinHeight(){return this.table.options.resizableRows?this.element.clientHeight:0}calcMaxHeight(){var e=0;return this.cells.forEach(function(t){var s=t.getHeight();s>e&&(e=s)}),e}setCellHeight(){this.cells.forEach(function(e){e.setHeight()}),this.heightInitialized=!0}clearCellHeight(){this.cells.forEach(function(e){e.clearHeight()})}normalizeHeight(e){e&&!this.table.options.rowHeight&&this.clearCellHeight(),this.calcHeight(e),this.setCellHeight()}setHeight(e,t){(this.height!=e||t)&&(this.manualHeight=!0,this.height=e,this.heightStyled=e?e+"px":"",this.setCellHeight(),this.outerHeight=this.element.offsetHeight,this.subscribedExternal("rowHeight")&&this.dispatchExternal("rowHeight",this.getComponent()))}getHeight(){return this.outerHeight}getWidth(){return this.element.offsetWidth}deleteCell(e){var t=this.cells.indexOf(e);t>-1&&this.cells.splice(t,1)}setData(e){this.data=this.chain("row-data-init-before",[this,e],void 0,e),this.dispatch("row-data-init-after",this)}updateData(e){var t=this.element&&B.elVisible(this.element),s={},a;return new Promise((i,n)=>{typeof e=="string"&&(e=JSON.parse(e)),this.dispatch("row-data-save-before",this),this.subscribed("row-data-changing")&&(s=Object.assign(s,this.data),s=Object.assign(s,e)),a=this.chain("row-data-changing",[this,s,e],null,e);const r=[];for(let o in e)this.table.columnManager.getColumnsByFieldRoot(o).forEach(c=>{let d=this.getCell(c.getField());if(d){let h=c.getFieldValue(a);d.getValue()!==h&&r.push([d,h])}});for(let o in a)this.data[o]=a[o];this.dispatch("row-data-save-after",this),r.forEach(([o,l])=>{o.setValueProcessData(l),t&&o.cellRendered()}),t?(this.normalizeHeight(!0),this.table.options.rowFormatter&&this.table.options.rowFormatter(this.getComponent())):(this.initialized=!1,this.height=0,this.heightStyled=""),this.dispatch("row-data-changed",this,t,e),this.dispatchExternal("rowUpdated",this.getComponent()),this.subscribedExternal("dataChanged")&&this.dispatchExternal("dataChanged",this.table.rowManager.getData()),i()})}getData(e){return e?this.chain("row-data-retrieve",[this,e],null,this.data):this.data}getCell(e){var t=!1;return e=this.table.columnManager.findColumn(e),!this.initialized&&this.cells.length===0&&this.generateCells(),t=this.cells.find(function(s){return s.column===e}),t}getCellIndex(e){return this.cells.findIndex(function(t){return t===e})}findCell(e){return this.cells.find(t=>t.element===e)}getCells(){return!this.initialized&&this.cells.length===0&&this.generateCells(),this.cells}nextRow(){var e=this.table.rowManager.nextDisplayRow(this,!0);return e||!1}prevRow(){var e=this.table.rowManager.prevDisplayRow(this,!0);return e||!1}moveToRow(e,t){var s=this.table.rowManager.findRow(e);s?(this.table.rowManager.moveRowActual(this,s,!t),this.table.rowManager.refreshActiveData("display",!1,!0)):console.warn("Move Error - No matching row found:",e)}delete(){return this.dispatch("row-delete",this),this.deleteActual(),Promise.resolve()}deleteActual(e){this.detachModules(),this.table.rowManager.deleteRow(this,e),this.deleteCells(),this.initialized=!1,this.heightInitialized=!1,this.element=!1,this.dispatch("row-deleted",this)}detachModules(){this.dispatch("row-deleting",this)}deleteCells(){var e=this.cells.length;for(let t=0;t<e;t++)this.cells[0].delete()}wipe(){if(this.detachModules(),this.deleteCells(),this.element){for(;this.element.firstChild;)this.element.removeChild(this.element.firstChild);this.element.parentNode&&this.element.parentNode.removeChild(this.element)}this.element=!1,this.modules={}}isDisplayed(){return this.table.rowManager.getDisplayRows().includes(this)}getPosition(){return this.isDisplayed()?this.position:!1}setPosition(e){e!=this.position&&(this.position=e,this.positionWatchers.forEach(t=>{t(this.position)}))}watchPosition(e){this.positionWatchers.push(e),e(this.position)}getGroup(){return this.modules.group||!1}getComponent(){return this.component||(this.component=new Je(this)),this.component}}function Se(p,e){var t=e.mask,s=typeof e.maskLetterChar<"u"?e.maskLetterChar:"A",a=typeof e.maskNumberChar<"u"?e.maskNumberChar:"9",i=typeof e.maskWildcardChar<"u"?e.maskWildcardChar:"*";function n(r){var o=t[r];typeof o<"u"&&o!==i&&o!==s&&o!==a&&(p.value=p.value+""+o,n(r+1))}p.addEventListener("keydown",r=>{var o=p.value.length,l=r.key;if(r.key.length===1&&!r.ctrlKey&&!r.metaKey){if(o>=t.length)return r.preventDefault(),r.stopPropagation(),!1;switch(t[o]){case s:if(l.toUpperCase()==l.toLowerCase())return r.preventDefault(),r.stopPropagation(),!1;break;case a:if(isNaN(l))return r.preventDefault(),r.stopPropagation(),!1;break;case i:break;default:if(l!==t[o])return r.preventDefault(),r.stopPropagation(),!1}}}),p.addEventListener("keyup",r=>{r.key.length===1&&e.maskAutoFill&&n(p.value.length)}),p.placeholder||(p.placeholder=t),e.maskAutoFill&&n(p.value.length)}function Ua(p,e,t,s,a){var i=p.getValue(),n=document.createElement("input");if(n.setAttribute("type",a.search?"search":"text"),n.style.padding="4px",n.style.width="100%",n.style.boxSizing="border-box",a.elementAttributes&&typeof a.elementAttributes=="object")for(let o in a.elementAttributes)o.charAt(0)=="+"?(o=o.slice(1),n.setAttribute(o,n.getAttribute(o)+a.elementAttributes["+"+o])):n.setAttribute(o,a.elementAttributes[o]);n.value=typeof i<"u"?i:"",e(function(){p.getType()==="cell"&&(n.focus({preventScroll:!0}),n.style.height="100%",a.selectContents&&n.select())});function r(o){(i===null||typeof i>"u")&&n.value!==""||n.value!==i?t(n.value)&&(i=n.value):s()}return n.addEventListener("change",r),n.addEventListener("blur",r),n.addEventListener("keydown",function(o){switch(o.key){case"Enter":r();break;case"Escape":s();break;case"End":case"Home":o.stopPropagation();break}}),a.mask&&Se(n,a),n}function Ga(p,e,t,s,a){var i=p.getValue(),n=a.verticalNavigation||"hybrid",r=String(i!==null&&typeof i<"u"?i:""),o=document.createElement("textarea"),l=0;if(o.style.display="block",o.style.padding="2px",o.style.height="100%",o.style.width="100%",o.style.boxSizing="border-box",o.style.whiteSpace="pre-wrap",o.style.resize="none",a.elementAttributes&&typeof a.elementAttributes=="object")for(let d in a.elementAttributes)d.charAt(0)=="+"?(d=d.slice(1),o.setAttribute(d,o.getAttribute(d)+a.elementAttributes["+"+d])):o.setAttribute(d,a.elementAttributes[d]);o.value=r,e(function(){p.getType()==="cell"&&(o.focus({preventScroll:!0}),o.style.height="100%",o.scrollHeight,o.style.height=o.scrollHeight+"px",p.getRow().normalizeHeight(),a.selectContents&&o.select())});function c(d){(i===null||typeof i>"u")&&o.value!==""||o.value!==i?(t(o.value)&&(i=o.value),setTimeout(function(){p.getRow().normalizeHeight()},300)):s()}return o.addEventListener("change",c),o.addEventListener("blur",c),o.addEventListener("keyup",function(){o.style.height="";var d=o.scrollHeight;o.style.height=d+"px",d!=l&&(l=d,p.getRow().normalizeHeight())}),o.addEventListener("keydown",function(d){switch(d.key){case"Enter":d.shiftKey&&a.shiftEnterSubmit&&c();break;case"Escape":s();break;case"ArrowUp":(n=="editor"||n=="hybrid"&&o.selectionStart)&&(d.stopImmediatePropagation(),d.stopPropagation());break;case"ArrowDown":(n=="editor"||n=="hybrid"&&o.selectionStart!==o.value.length)&&(d.stopImmediatePropagation(),d.stopPropagation());break;case"End":case"Home":d.stopPropagation();break}}),a.mask&&Se(o,a),o}function Ka(p,e,t,s,a){var i=p.getValue(),n=a.verticalNavigation||"editor",r=document.createElement("input");if(r.setAttribute("type","number"),typeof a.max<"u"&&r.setAttribute("max",a.max),typeof a.min<"u"&&r.setAttribute("min",a.min),typeof a.step<"u"&&r.setAttribute("step",a.step),r.style.padding="4px",r.style.width="100%",r.style.boxSizing="border-box",a.elementAttributes&&typeof a.elementAttributes=="object")for(let c in a.elementAttributes)c.charAt(0)=="+"?(c=c.slice(1),r.setAttribute(c,r.getAttribute(c)+a.elementAttributes["+"+c])):r.setAttribute(c,a.elementAttributes[c]);r.value=i;var o=function(c){l()};e(function(){p.getType()==="cell"&&(r.removeEventListener("blur",o),r.focus({preventScroll:!0}),r.style.height="100%",r.addEventListener("blur",o),a.selectContents&&r.select())});function l(){var c=r.value;!isNaN(c)&&c!==""&&(c=Number(c)),c!==i?t(c)&&(i=c):s()}return r.addEventListener("keydown",function(c){switch(c.key){case"Enter":l();break;case"Escape":s();break;case"ArrowUp":case"ArrowDown":n=="editor"&&(c.stopImmediatePropagation(),c.stopPropagation());break;case"End":case"Home":c.stopPropagation();break}}),a.mask&&Se(r,a),r}function Ja(p,e,t,s,a){var i=p.getValue(),n=document.createElement("input");if(n.setAttribute("type","range"),typeof a.max<"u"&&n.setAttribute("max",a.max),typeof a.min<"u"&&n.setAttribute("min",a.min),typeof a.step<"u"&&n.setAttribute("step",a.step),n.style.padding="4px",n.style.width="100%",n.style.boxSizing="border-box",a.elementAttributes&&typeof a.elementAttributes=="object")for(let o in a.elementAttributes)o.charAt(0)=="+"?(o=o.slice(1),n.setAttribute(o,n.getAttribute(o)+a.elementAttributes["+"+o])):n.setAttribute(o,a.elementAttributes[o]);n.value=i,e(function(){p.getType()==="cell"&&(n.focus({preventScroll:!0}),n.style.height="100%")});function r(){var o=n.value;!isNaN(o)&&o!==""&&(o=Number(o)),o!=i?t(o)&&(i=o):s()}return n.addEventListener("blur",function(o){r()}),n.addEventListener("keydown",function(o){switch(o.key){case"Enter":r();break;case"Escape":s();break}}),n}function Ya(p,e,t,s,a){var i=a.format,n=a.verticalNavigation||"editor",r=i?window.DateTime||luxon.DateTime:null,o=p.getValue(),l=document.createElement("input");function c(h){var u;return r.isDateTime(h)?u=h:i==="iso"?u=r.fromISO(String(h)):u=r.fromFormat(String(h),i),u.toFormat("yyyy-MM-dd")}if(l.type="date",l.style.padding="4px",l.style.width="100%",l.style.boxSizing="border-box",a.max&&l.setAttribute("max",i?c(a.max):a.max),a.min&&l.setAttribute("min",i?c(a.min):a.min),a.elementAttributes&&typeof a.elementAttributes=="object")for(let h in a.elementAttributes)h.charAt(0)=="+"?(h=h.slice(1),l.setAttribute(h,l.getAttribute(h)+a.elementAttributes["+"+h])):l.setAttribute(h,a.elementAttributes[h]);o=typeof o<"u"?o:"",i&&(r?o=c(o):console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js")),l.value=o,e(function(){p.getType()==="cell"&&(l.focus({preventScroll:!0}),l.style.height="100%",a.selectContents&&l.select())});function d(){var h=l.value,u;if((o===null||typeof o>"u")&&h!==""||h!==o){if(h&&i)switch(u=r.fromFormat(String(h),"yyyy-MM-dd"),i){case!0:h=u;break;case"iso":h=u.toISO();break;default:h=u.toFormat(i)}t(h)&&(o=l.value)}else s()}return l.addEventListener("blur",function(h){(h.relatedTarget||h.rangeParent||h.explicitOriginalTarget!==l)&&d()}),l.addEventListener("keydown",function(h){switch(h.key){case"Enter":d();break;case"Escape":s();break;case"End":case"Home":h.stopPropagation();break;case"ArrowUp":case"ArrowDown":n=="editor"&&(h.stopImmediatePropagation(),h.stopPropagation());break}}),l}function Qa(p,e,t,s,a){var i=a.format,n=a.verticalNavigation||"editor",r=i?window.DateTime||luxon.DateTime:null,o,l=p.getValue(),c=document.createElement("input");if(c.type="time",c.style.padding="4px",c.style.width="100%",c.style.boxSizing="border-box",a.elementAttributes&&typeof a.elementAttributes=="object")for(let h in a.elementAttributes)h.charAt(0)=="+"?(h=h.slice(1),c.setAttribute(h,c.getAttribute(h)+a.elementAttributes["+"+h])):c.setAttribute(h,a.elementAttributes[h]);l=typeof l<"u"?l:"",i&&(r?(r.isDateTime(l)?o=l:i==="iso"?o=r.fromISO(String(l)):o=r.fromFormat(String(l),i),l=o.toFormat("HH:mm")):console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js")),c.value=l,e(function(){p.getType()=="cell"&&(c.focus({preventScroll:!0}),c.style.height="100%",a.selectContents&&c.select())});function d(){var h=c.value,u;if((l===null||typeof l>"u")&&h!==""||h!==l){if(h&&i)switch(u=r.fromFormat(String(h),"hh:mm"),i){case!0:h=u;break;case"iso":h=u.toISO();break;default:h=u.toFormat(i)}t(h)&&(l=c.value)}else s()}return c.addEventListener("blur",function(h){(h.relatedTarget||h.rangeParent||h.explicitOriginalTarget!==c)&&d()}),c.addEventListener("keydown",function(h){switch(h.key){case"Enter":d();break;case"Escape":s();break;case"End":case"Home":h.stopPropagation();break;case"ArrowUp":case"ArrowDown":n=="editor"&&(h.stopImmediatePropagation(),h.stopPropagation());break}}),c}function Za(p,e,t,s,a){var i=a.format,n=a.verticalNavigation||"editor",r=i?this.table.dependencyRegistry.lookup(["luxon","DateTime"],"DateTime"):null,o,l=p.getValue(),c=document.createElement("input");if(c.type="datetime-local",c.style.padding="4px",c.style.width="100%",c.style.boxSizing="border-box",a.elementAttributes&&typeof a.elementAttributes=="object")for(let h in a.elementAttributes)h.charAt(0)=="+"?(h=h.slice(1),c.setAttribute(h,c.getAttribute(h)+a.elementAttributes["+"+h])):c.setAttribute(h,a.elementAttributes[h]);l=typeof l<"u"?l:"",i&&(r?(r.isDateTime(l)?o=l:i==="iso"?o=r.fromISO(String(l)):o=r.fromFormat(String(l),i),l=o.toFormat("yyyy-MM-dd")+"T"+o.toFormat("HH:mm")):console.error("Editor Error - 'date' editor 'format' param is dependant on luxon.js")),c.value=l,e(function(){p.getType()==="cell"&&(c.focus({preventScroll:!0}),c.style.height="100%",a.selectContents&&c.select())});function d(){var h=c.value,u;if((l===null||typeof l>"u")&&h!==""||h!==l){if(h&&i)switch(u=r.fromISO(String(h)),i){case!0:h=u;break;case"iso":h=u.toISO();break;default:h=u.toFormat(i)}t(h)&&(l=c.value)}else s()}return c.addEventListener("blur",function(h){(h.relatedTarget||h.rangeParent||h.explicitOriginalTarget!==c)&&d()}),c.addEventListener("keydown",function(h){switch(h.key){case"Enter":d();break;case"Escape":s();break;case"End":case"Home":h.stopPropagation();break;case"ArrowUp":case"ArrowDown":n=="editor"&&(h.stopImmediatePropagation(),h.stopPropagation());break}}),c}let Xa=class{constructor(e,t,s,a,i,n){this.edit=e,this.table=e.table,this.cell=t,this.params=this._initializeParams(n),this.data=[],this.displayItems=[],this.currentItems=[],this.focusedItem=null,this.input=this._createInputElement(),this.listEl=this._createListElement(),this.initialValues=null,this.isFilter=t.getType()==="header",this.filterTimeout=null,this.filtered=!1,this.typing=!1,this.values=[],this.popup=null,this.listIteration=0,this.lastAction="",this.filterTerm="",this.blurable=!0,this.actions={success:a,cancel:i},this._deprecatedOptionsCheck(),this._initializeValue(),s(this._onRendered.bind(this))}_deprecatedOptionsCheck(){}_initializeValue(){var e=this.cell.getValue();typeof e>"u"&&typeof this.params.defaultValue<"u"&&(e=this.params.defaultValue),this.initialValues=this.params.multiselect?e:[e],this.isFilter&&(this.input.value=this.initialValues?this.initialValues.join(","):"",this.headerFilterInitialListGen())}_onRendered(){var e=this.cell.getElement();function t(s){s.stopPropagation()}this.isFilter||(this.input.style.height="100%",this.input.focus({preventScroll:!0})),e.addEventListener("click",t),setTimeout(()=>{e.removeEventListener("click",t)},1e3),this.input.addEventListener("mousedown",this._preventPopupBlur.bind(this))}_createListElement(){var e=document.createElement("div");return e.classList.add("tabulator-edit-list"),e.addEventListener("mousedown",this._preventBlur.bind(this)),e.addEventListener("keydown",this._inputKeyDown.bind(this)),e}_setListWidth(){var e=this.isFilter?this.input:this.cell.getElement();this.listEl.style.minWidth=e.offsetWidth+"px",this.params.maxWidth&&(this.params.maxWidth===!0?this.listEl.style.maxWidth=e.offsetWidth+"px":typeof this.params.maxWidth=="number"?this.listEl.style.maxWidth=this.params.maxWidth+"px":this.listEl.style.maxWidth=this.params.maxWidth)}_createInputElement(){var e=this.params.elementAttributes,t=document.createElement("input");if(t.setAttribute("type",this.params.clearable?"search":"text"),t.style.padding="4px",t.style.width="100%",t.style.boxSizing="border-box",this.params.autocomplete||(t.style.cursor="default",t.style.caretColor="transparent"),e&&typeof e=="object")for(let s in e)s.charAt(0)=="+"?(s=s.slice(1),t.setAttribute(s,t.getAttribute(s)+e["+"+s])):t.setAttribute(s,e[s]);return this.params.mask&&Se(t,this.params),this._bindInputEvents(t),t}_initializeParams(e){var t=["values","valuesURL","valuesLookup"],s;return e=Object.assign({},e),e.verticalNavigation=e.verticalNavigation||"editor",e.placeholderLoading=typeof e.placeholderLoading>"u"?"Searching ...":e.placeholderLoading,e.placeholderEmpty=typeof e.placeholderEmpty>"u"?"No Results Found":e.placeholderEmpty,e.filterDelay=typeof e.filterDelay>"u"?300:e.filterDelay,e.emptyValue=Object.keys(e).includes("emptyValue")?e.emptyValue:"",s=Object.keys(e).filter(a=>t.includes(a)).length,s?s>1&&console.warn("list editor config error - only one of the values, valuesURL, or valuesLookup options can be set on the same editor"):console.warn("list editor config error - either the values, valuesURL, or valuesLookup option must be set"),e.autocomplete?e.multiselect&&(e.multiselect=!1,console.warn("list editor config error - multiselect option is not available when autocomplete is enabled")):(e.freetext&&(e.freetext=!1,console.warn("list editor config error - freetext option is only available when autocomplete is enabled")),e.filterFunc&&(e.filterFunc=!1,console.warn("list editor config error - filterFunc option is only available when autocomplete is enabled")),e.filterRemote&&(e.filterRemote=!1,console.warn("list editor config error - filterRemote option is only available when autocomplete is enabled")),e.mask&&(e.mask=!1,console.warn("list editor config error - mask option is only available when autocomplete is enabled")),e.allowEmpty&&(e.allowEmpty=!1,console.warn("list editor config error - allowEmpty option is only available when autocomplete is enabled")),e.listOnEmpty&&(e.listOnEmpty=!1,console.warn("list editor config error - listOnEmpty option is only available when autocomplete is enabled"))),e.filterRemote&&!(typeof e.valuesLookup=="function"||e.valuesURL)&&(e.filterRemote=!1,console.warn("list editor config error - filterRemote option should only be used when values list is populated from a remote source")),e}_bindInputEvents(e){e.addEventListener("focus",this._inputFocus.bind(this)),e.addEventListener("click",this._inputClick.bind(this)),e.addEventListener("blur",this._inputBlur.bind(this)),e.addEventListener("keydown",this._inputKeyDown.bind(this)),e.addEventListener("search",this._inputSearch.bind(this)),this.params.autocomplete&&e.addEventListener("keyup",this._inputKeyUp.bind(this))}_inputFocus(e){this.rebuildOptionsList()}_filter(){this.params.filterRemote?(clearTimeout(this.filterTimeout),this.filterTimeout=setTimeout(()=>{this.rebuildOptionsList()},this.params.filterDelay)):this._filterList()}_inputClick(e){e.stopPropagation()}_inputBlur(e){this.blurable&&(this.popup?this.popup.hide():this._resolveValue(!0))}_inputSearch(){this._clearChoices()}_inputKeyDown(e){switch(e.key){case"ArrowUp":this._keyUp(e);break;case"ArrowDown":this._keyDown(e);break;case"ArrowLeft":case"ArrowRight":this._keySide(e);break;case"Enter":this._keyEnter();break;case"Escape":this._keyEsc();break;case"Home":case"End":this._keyHomeEnd(e);break;case"Tab":this._keyTab(e);break;default:this._keySelectLetter(e)}}_inputKeyUp(e){switch(e.key){case"ArrowUp":case"ArrowLeft":case"ArrowRight":case"ArrowDown":case"Enter":case"Escape":break;default:this._keyAutoCompLetter(e)}}_preventPopupBlur(){this.popup&&this.popup.blockHide(),setTimeout(()=>{this.popup&&this.popup.restoreHide()},10)}_preventBlur(){this.blurable=!1,setTimeout(()=>{this.blurable=!0},10)}_keyTab(e){this.params.autocomplete&&this.lastAction==="typing"?this._resolveValue(!0):this.focusedItem&&this._chooseItem(this.focusedItem,!0)}_keyUp(e){var t=this.displayItems.indexOf(this.focusedItem);(this.params.verticalNavigation=="editor"||this.params.verticalNavigation=="hybrid"&&t)&&(e.stopImmediatePropagation(),e.stopPropagation(),e.preventDefault(),t>0&&this._focusItem(this.displayItems[t-1]))}_keyDown(e){var t=this.displayItems.indexOf(this.focusedItem);(this.params.verticalNavigation=="editor"||this.params.verticalNavigation=="hybrid"&&t<this.displayItems.length-1)&&(e.stopImmediatePropagation(),e.stopPropagation(),e.preventDefault(),t<this.displayItems.length-1&&(t==-1?this._focusItem(this.displayItems[0]):this._focusItem(this.displayItems[t+1])))}_keySide(e){this.params.autocomplete||(e.stopImmediatePropagation(),e.stopPropagation(),e.preventDefault())}_keyEnter(e){this.params.autocomplete&&this.lastAction==="typing"?this._resolveValue(!0):this.focusedItem&&this._chooseItem(this.focusedItem)}_keyEsc(e){this._cancel()}_keyHomeEnd(e){this.params.autocomplete&&e.stopImmediatePropagation()}_keySelectLetter(e){this.params.autocomplete||(e.preventDefault(),e.key.length===1&&this._scrollToValue(e.key.toUpperCase().charCodeAt(0)))}_keyAutoCompLetter(e){this._filter(),this.lastAction="typing",this.typing=!0}_scrollToValue(e){clearTimeout(this.filterTimeout);var t=String.fromCharCode(e).toLowerCase();this.filterTerm+=t.toLowerCase();var s=this.displayItems.find(a=>typeof a.label<"u"&&a.label.toLowerCase().startsWith(this.filterTerm));s&&this._focusItem(s),this.filterTimeout=setTimeout(()=>{this.filterTerm=""},800)}_focusItem(e){this.lastAction="focus",this.focusedItem&&this.focusedItem.element&&this.focusedItem.element.classList.remove("focused"),this.focusedItem=e,e&&e.element&&(e.element.classList.add("focused"),e.element.scrollIntoView({behavior:"smooth",block:"nearest",inline:"start"}))}headerFilterInitialListGen(){this._generateOptions(!0)}rebuildOptionsList(){this._generateOptions().then(this._sortOptions.bind(this)).then(this._buildList.bind(this)).then(this._showList.bind(this)).catch(e=>{Number.isInteger(e)||console.error("List generation error",e)})}_filterList(){this._buildList(this._filterOptions()),this._showList()}_generateOptions(e){var t=[],s=++this.listIteration;return this.filtered=!1,this.params.values?t=this.params.values:this.params.valuesURL?t=this._ajaxRequest(this.params.valuesURL,this.input.value):typeof this.params.valuesLookup=="function"?t=this.params.valuesLookup(this.cell,this.input.value):this.params.valuesLookup&&(t=this._uniqueColumnValues(this.params.valuesLookupField)),t instanceof Promise?(e||this._addPlaceholder(this.params.placeholderLoading),t.then().then(a=>this.listIteration===s?this._parseList(a):Promise.reject(s))):Promise.resolve(this._parseList(t))}_addPlaceholder(e){var t=document.createElement("div");typeof e=="function"&&(e=e(this.cell.getComponent(),this.listEl)),e&&(this._clearList(),e instanceof HTMLElement?t=e:(t.classList.add("tabulator-edit-list-placeholder"),t.innerHTML=e),this.listEl.appendChild(t),this._showList())}_ajaxRequest(e,t){var s=this.params.filterRemote?{term:t}:{};return e=Ot(e,{},s),fetch(e).then(a=>a.ok?a.json().catch(i=>(console.warn("List Ajax Load Error - Invalid JSON returned",i),Promise.reject(i))):(console.error("List Ajax Load Error - Connection Error: "+a.status,a.statusText),Promise.reject(a))).catch(a=>(console.error("List Ajax Load Error - Connection Error: ",a),Promise.reject(a)))}_uniqueColumnValues(e){var t={},s=this.table.getData(this.params.valuesLookup),a;return e?a=this.table.columnManager.getColumnByField(e):a=this.cell.getColumn()._getSelf(),a?s.forEach(i=>{var n=a.getFieldValue(i);this._emptyValueCheck(n)||(this.params.multiselect&&Array.isArray(n)?n.forEach(r=>{this._emptyValueCheck(r)||(t[r]=!0)}):t[n]=!0)}):(console.warn("unable to find matching column to create select lookup list:",e),t=[]),Object.keys(t)}_emptyValueCheck(e){return e===null||typeof e>"u"||e===""}_parseList(e){var t=[];return Array.isArray(e)||(e=Object.entries(e).map(([s,a])=>({label:a,value:s}))),e.forEach(s=>{typeof s!="object"&&(s={label:s,value:s}),this._parseListItem(s,t,0)}),!this.currentItems.length&&this.params.freetext&&(this.input.value=this.initialValues,this.typing=!0,this.lastAction="typing"),this.data=t,t}_parseListItem(e,t,s){var a={};e.options?a=this._parseListGroup(e,s+1):(a={label:e.label,value:e.value,itemParams:e.itemParams,elementAttributes:e.elementAttributes,element:!1,selected:!1,visible:!0,level:s,original:e},this.initialValues&&this.initialValues.indexOf(e.value)>-1&&this._chooseItem(a,!0)),t.push(a)}_parseListGroup(e,t){var s={label:e.label,group:!0,itemParams:e.itemParams,elementAttributes:e.elementAttributes,element:!1,visible:!0,level:t,options:[],original:e};return e.options.forEach(a=>{this._parseListItem(a,s.options,t)}),s}_sortOptions(e){var t;return this.params.sort&&(t=typeof this.params.sort=="function"?this.params.sort:this._defaultSortFunction.bind(this),this._sortGroup(t,e)),e}_sortGroup(e,t){t.sort((s,a)=>e(s.label,a.label,s.value,a.value,s.original,a.original)),t.forEach(s=>{s.group&&this._sortGroup(e,s.options)})}_defaultSortFunction(e,t){var s,a,i,n,r=0,o,l=/(\d+)|(\D+)/g,c=/\d/,d=0;if(this.params.sort==="desc"&&([e,t]=[t,e]),!e&&e!==0)d=!t&&t!==0?0:-1;else if(!t&&t!==0)d=1;else{if(isFinite(e)&&isFinite(t))return e-t;if(s=String(e).toLowerCase(),a=String(t).toLowerCase(),s===a)return 0;if(!(c.test(s)&&c.test(a)))return s>a?1:-1;for(s=s.match(l),a=a.match(l),o=s.length>a.length?a.length:s.length;r<o;)if(i=s[r],n=a[r++],i!==n)return isFinite(i)&&isFinite(n)?(i.charAt(0)==="0"&&(i="."+i),n.charAt(0)==="0"&&(n="."+n),i-n):i>n?1:-1;return s.length>a.length}return d}_filterOptions(){var e=this.params.filterFunc||this._defaultFilterFunc,t=this.input.value;return t?(this.filtered=!0,this.data.forEach(s=>{this._filterItem(e,t,s)})):this.filtered=!1,this.data}_filterItem(e,t,s){var a=!1;return s.group?(s.options.forEach(i=>{this._filterItem(e,t,i)&&(a=!0)}),s.visible=a):s.visible=e(t,s.label,s.value,s.original),s.visible}_defaultFilterFunc(e,t,s,a){return e=String(e).toLowerCase(),t!==null&&typeof t<"u"&&(String(t).toLowerCase().indexOf(e)>-1||String(s).toLowerCase().indexOf(e)>-1)}_clearList(){for(;this.listEl.firstChild;)this.listEl.removeChild(this.listEl.firstChild);this.displayItems=[]}_buildList(e){this._clearList(),e.forEach(t=>{this._buildItem(t)}),this.displayItems.length||this._addPlaceholder(this.params.placeholderEmpty)}_buildItem(e){var t=e.element,s;if(!this.filtered||e.visible){if(!t){if(t=document.createElement("div"),t.tabIndex=0,s=this.params.itemFormatter?this.params.itemFormatter(e.label,e.value,e.original,t):e.label,s instanceof HTMLElement?t.appendChild(s):t.innerHTML=s,e.group?t.classList.add("tabulator-edit-list-group"):t.classList.add("tabulator-edit-list-item"),t.classList.add("tabulator-edit-list-group-level-"+e.level),e.elementAttributes&&typeof e.elementAttributes=="object")for(let a in e.elementAttributes)a.charAt(0)=="+"?(a=a.slice(1),t.setAttribute(a,this.input.getAttribute(a)+e.elementAttributes["+"+a])):t.setAttribute(a,e.elementAttributes[a]);e.group?t.addEventListener("click",this._groupClick.bind(this,e)):t.addEventListener("click",this._itemClick.bind(this,e)),t.addEventListener("mousedown",this._preventBlur.bind(this)),e.element=t}this._styleItem(e),this.listEl.appendChild(t),e.group?e.options.forEach(a=>{this._buildItem(a)}):this.displayItems.push(e)}}_showList(){var e=this.popup&&this.popup.isVisible();if(this.input.parentNode){if(this.params.autocomplete&&this.input.value===""&&!this.params.listOnEmpty){this.popup&&this.popup.hide(!0);return}this._setListWidth(),this.popup||(this.popup=this.edit.popup(this.listEl)),this.popup.show(this.cell.getElement(),"bottom"),e||setTimeout(()=>{this.popup.hideOnBlur(this._resolveValue.bind(this,!0))},10)}}_styleItem(e){e&&e.element&&(e.selected?e.element.classList.add("active"):e.element.classList.remove("active"))}_itemClick(e,t){t.stopPropagation(),this._chooseItem(e)}_groupClick(e,t){t.stopPropagation()}_cancel(){this.popup.hide(!0),this.actions.cancel()}_clearChoices(){this.typing=!0,this.currentItems.forEach(e=>{e.selected=!1,this._styleItem(e)}),this.currentItems=[],this.focusedItem=null}_chooseItem(e,t){var s;this.typing=!1,this.params.multiselect?(s=this.currentItems.indexOf(e),s>-1?(this.currentItems.splice(s,1),e.selected=!1):(this.currentItems.push(e),e.selected=!0),this.input.value=this.currentItems.map(a=>a.label).join(","),this._styleItem(e)):(this.currentItems=[e],e.selected=!0,this.input.value=e.label,this._styleItem(e),t||this._resolveValue()),this._focusItem(e)}_resolveValue(e){var t,s;if(this.popup&&this.popup.hide(!0),this.params.multiselect)t=this.currentItems.map(a=>a.value);else if(e&&this.params.autocomplete&&this.typing)if(this.params.freetext||this.params.allowEmpty&&this.input.value==="")t=this.input.value;else{this.actions.cancel();return}else this.currentItems[0]?t=this.currentItems[0].value:(s=Array.isArray(this.initialValues)?this.initialValues[0]:this.initialValues,s===null||typeof s>"u"||s===""?t=s:t=this.params.emptyValue);t===""&&(t=this.params.emptyValue),this.actions.success(t),this.isFilter&&(this.initialValues=t&&!Array.isArray(t)?[t]:t,this.currentItems=[])}};function ei(p,e,t,s,a){var i=new Xa(this,p,e,t,s,a);return i.input}function ti(p,e,t,s,a){var i=this,n=p.getElement(),r=p.getValue(),o=n.getElementsByTagName("svg").length||5,l=n.getElementsByTagName("svg")[0]?n.getElementsByTagName("svg")[0].getAttribute("width"):14,c=[],d=document.createElement("div"),h=document.createElementNS("http://www.w3.org/2000/svg","svg");function u(v){c.forEach(function(y,$){$<v?(i.table.browser=="ie"?y.setAttribute("class","tabulator-star-active"):y.classList.replace("tabulator-star-inactive","tabulator-star-active"),y.innerHTML='<polygon fill="#488CE9" stroke="#014AAE" stroke-width="37.6152" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 "/>'):(i.table.browser=="ie"?y.setAttribute("class","tabulator-star-inactive"):y.classList.replace("tabulator-star-active","tabulator-star-inactive"),y.innerHTML='<polygon fill="#010155" stroke="#686868" stroke-width="37.6152" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 "/>')})}function f(v){var y=document.createElement("span"),$=h.cloneNode(!0);c.push($),y.addEventListener("mouseenter",function(w){w.stopPropagation(),w.stopImmediatePropagation(),u(v)}),y.addEventListener("mousemove",function(w){w.stopPropagation(),w.stopImmediatePropagation()}),y.addEventListener("click",function(w){w.stopPropagation(),w.stopImmediatePropagation(),t(v),n.blur()}),y.appendChild($),d.appendChild(y)}function m(v){r=v,u(v)}if(n.style.whiteSpace="nowrap",n.style.overflow="hidden",n.style.textOverflow="ellipsis",d.style.verticalAlign="middle",d.style.display="inline-block",d.style.padding="4px",h.setAttribute("width",l),h.setAttribute("height",l),h.setAttribute("viewBox","0 0 512 512"),h.setAttribute("xml:space","preserve"),h.style.padding="0 1px",a.elementAttributes&&typeof a.elementAttributes=="object")for(let v in a.elementAttributes)v.charAt(0)=="+"?(v=v.slice(1),d.setAttribute(v,d.getAttribute(v)+a.elementAttributes["+"+v])):d.setAttribute(v,a.elementAttributes[v]);for(var b=1;b<=o;b++)f(b);return r=Math.min(parseInt(r),o),u(r),d.addEventListener("mousemove",function(v){u(0)}),d.addEventListener("click",function(v){t(0)}),n.addEventListener("blur",function(v){s()}),n.addEventListener("keydown",function(v){switch(v.key){case"ArrowRight":m(r+1);break;case"ArrowLeft":m(r-1);break;case"Enter":t(r);break;case"Escape":s();break}}),d}function si(p,e,t,s,a){var i=p.getElement(),n=typeof a.max>"u"?i.getElementsByTagName("div")[0]&&i.getElementsByTagName("div")[0].getAttribute("max")||100:a.max,r=typeof a.min>"u"?i.getElementsByTagName("div")[0]&&i.getElementsByTagName("div")[0].getAttribute("min")||0:a.min,o=(n-r)/100,l=p.getValue()||0,c=document.createElement("div"),d=document.createElement("div"),h,u;function f(){var m=window.getComputedStyle(i,null),b=o*Math.round(d.offsetWidth/((i.clientWidth-parseInt(m.getPropertyValue("padding-left"))-parseInt(m.getPropertyValue("padding-right")))/100))+r;t(b),i.setAttribute("aria-valuenow",b),i.setAttribute("aria-label",l)}if(c.style.position="absolute",c.style.right="0",c.style.top="0",c.style.bottom="0",c.style.width="5px",c.classList.add("tabulator-progress-handle"),d.style.display="inline-block",d.style.position="relative",d.style.height="100%",d.style.backgroundColor="#488CE9",d.style.maxWidth="100%",d.style.minWidth="0%",a.elementAttributes&&typeof a.elementAttributes=="object")for(let m in a.elementAttributes)m.charAt(0)=="+"?(m=m.slice(1),d.setAttribute(m,d.getAttribute(m)+a.elementAttributes["+"+m])):d.setAttribute(m,a.elementAttributes[m]);return i.style.padding="4px 4px",l=Math.min(parseFloat(l),n),l=Math.max(parseFloat(l),r),l=Math.round((l-r)/o),d.style.width=l+"%",i.setAttribute("aria-valuemin",r),i.setAttribute("aria-valuemax",n),d.appendChild(c),c.addEventListener("mousedown",function(m){h=m.screenX,u=d.offsetWidth}),c.addEventListener("mouseover",function(){c.style.cursor="ew-resize"}),i.addEventListener("mousemove",function(m){h&&(d.style.width=u+m.screenX-h+"px")}),i.addEventListener("mouseup",function(m){h&&(m.stopPropagation(),m.stopImmediatePropagation(),h=!1,u=!1,f())}),i.addEventListener("keydown",function(m){switch(m.key){case"ArrowRight":m.preventDefault(),d.style.width=d.clientWidth+i.clientWidth/100+"px";break;case"ArrowLeft":m.preventDefault(),d.style.width=d.clientWidth-i.clientWidth/100+"px";break;case"Tab":case"Enter":f();break;case"Escape":s();break}}),i.addEventListener("blur",function(){s()}),d}function ai(p,e,t,s,a){var i=p.getValue(),n=document.createElement("input"),r=a.tristate,o=typeof a.indeterminateValue>"u"?null:a.indeterminateValue,l=!1,c=Object.keys(a).includes("trueValue"),d=Object.keys(a).includes("falseValue");if(n.setAttribute("type","checkbox"),n.style.marginTop="5px",n.style.boxSizing="border-box",a.elementAttributes&&typeof a.elementAttributes=="object")for(let u in a.elementAttributes)u.charAt(0)=="+"?(u=u.slice(1),n.setAttribute(u,n.getAttribute(u)+a.elementAttributes["+"+u])):n.setAttribute(u,a.elementAttributes[u]);n.value=i,r&&(typeof i>"u"||i===o||i==="")&&(l=!0,n.indeterminate=!0),this.table.browser!="firefox"&&this.table.browser!="safari"&&e(function(){p.getType()==="cell"&&n.focus({preventScroll:!0})}),n.checked=c?i===a.trueValue:i===!0||i==="true"||i==="True"||i===1;function h(u){var f=n.checked;return c&&f?f=a.trueValue:d&&!f&&(f=a.falseValue),r?u?l?o:f:n.checked&&!l?(n.checked=!1,n.indeterminate=!0,l=!0,o):(l=!1,f):f}return n.addEventListener("change",function(u){t(h())}),n.addEventListener("blur",function(u){t(h(!0))}),n.addEventListener("keydown",function(u){u.key=="Enter"&&t(h()),u.key=="Escape"&&s()}),n}function ii(p,e,t,s,a){var i=p._getSelf().column,n,r,o;function l(c){var d=c.getValue(),h="input";switch(typeof d){case"number":h="number";break;case"boolean":h="tickCross";break;case"string":d.includes(`
`)&&(h="textarea");break}return h}return n=a.editorLookup?a.editorLookup(p):l(p),a.paramsLookup&&(o=typeof a.paramsLookup=="function"?a.paramsLookup(n,p):a.paramsLookup[n]),r=this.table.modules.edit.lookupEditor(n,i),r.call(this,p,e,t,s,o||{})}var ni={input:Ua,textarea:Ga,number:Ka,range:Ja,date:Ya,time:Qa,datetime:Za,list:ei,star:ti,progress:si,tickCross:ai,adaptable:ii};const _e=class _e extends I{constructor(e){super(e),this.currentCell=!1,this.mouseClick=!1,this.recursionBlock=!1,this.invalidEdit=!1,this.editedCells=[],this.convertEmptyValues=!1,this.editors=_e.editors,this.registerTableOption("editTriggerEvent","focus"),this.registerTableOption("editorEmptyValue"),this.registerTableOption("editorEmptyValueFunc",this.emptyValueCheck.bind(this)),this.registerColumnOption("editable"),this.registerColumnOption("editor"),this.registerColumnOption("editorParams"),this.registerColumnOption("editorEmptyValue"),this.registerColumnOption("editorEmptyValueFunc"),this.registerColumnOption("cellEditing"),this.registerColumnOption("cellEdited"),this.registerColumnOption("cellEditCancelled"),this.registerTableFunction("getEditedCells",this.getEditedCells.bind(this)),this.registerTableFunction("clearCellEdited",this.clearCellEdited.bind(this)),this.registerTableFunction("navigatePrev",this.navigatePrev.bind(this)),this.registerTableFunction("navigateNext",this.navigateNext.bind(this)),this.registerTableFunction("navigateLeft",this.navigateLeft.bind(this)),this.registerTableFunction("navigateRight",this.navigateRight.bind(this)),this.registerTableFunction("navigateUp",this.navigateUp.bind(this)),this.registerTableFunction("navigateDown",this.navigateDown.bind(this)),this.registerComponentFunction("cell","isEdited",this.cellIsEdited.bind(this)),this.registerComponentFunction("cell","clearEdited",this.clearEdited.bind(this)),this.registerComponentFunction("cell","edit",this.editCell.bind(this)),this.registerComponentFunction("cell","cancelEdit",this.cellCancelEdit.bind(this)),this.registerComponentFunction("cell","navigatePrev",this.navigatePrev.bind(this)),this.registerComponentFunction("cell","navigateNext",this.navigateNext.bind(this)),this.registerComponentFunction("cell","navigateLeft",this.navigateLeft.bind(this)),this.registerComponentFunction("cell","navigateRight",this.navigateRight.bind(this)),this.registerComponentFunction("cell","navigateUp",this.navigateUp.bind(this)),this.registerComponentFunction("cell","navigateDown",this.navigateDown.bind(this))}initialize(){this.subscribe("cell-init",this.bindEditor.bind(this)),this.subscribe("cell-delete",this.clearEdited.bind(this)),this.subscribe("cell-value-changed",this.updateCellClass.bind(this)),this.subscribe("column-layout",this.initializeColumnCheck.bind(this)),this.subscribe("column-delete",this.columnDeleteCheck.bind(this)),this.subscribe("row-deleting",this.rowDeleteCheck.bind(this)),this.subscribe("row-layout",this.rowEditableCheck.bind(this)),this.subscribe("data-refreshing",this.cancelEdit.bind(this)),this.subscribe("clipboard-paste",this.pasteBlocker.bind(this)),this.confirm("edit-nav-disabled")||(this.subscribe("keybinding-nav-prev",this.navigatePrev.bind(this,void 0)),this.subscribe("keybinding-nav-next",this.keybindingNavigateNext.bind(this)),this.subscribe("keybinding-nav-up",this.navigateUp.bind(this,void 0)),this.subscribe("keybinding-nav-down",this.navigateDown.bind(this,void 0))),this.subscribe("edit-check-editing",this.checkEditing.bind(this)),this.subscribe("edit-cancel-cell",this.cancelEditEvent.bind(this)),Object.keys(this.table.options).includes("editorEmptyValue")&&(this.convertEmptyValues=!0)}pasteBlocker(e){if(this.currentCell)return!0}keybindingNavigateNext(e){var t=this.currentCell,s=this.options("tabEndNewRow");t&&(this.navigateNext(t,e)||s&&(t.getElement().firstChild.blur(),this.invalidEdit||(s===!0?s=this.table.addRow({}):typeof s=="function"?s=this.table.addRow(s(t.row.getComponent())):s=this.table.addRow(Object.assign({},s)),s.then(()=>{setTimeout(()=>{t.getComponent().navigateNext()})}))))}cellIsEdited(e){return!!e.modules.edit&&e.modules.edit.edited}cellCancelEdit(e){e===this.currentCell?this.table.modules.edit.cancelEdit():console.warn("Cancel Editor Error - This cell is not currently being edited ")}updateCellClass(e){this.allowEdit(e)?e.getElement().classList.add("tabulator-editable"):e.getElement().classList.remove("tabulator-editable")}clearCellEdited(e){e||(e=this.table.modules.edit.getEditedCells()),Array.isArray(e)||(e=[e]),e.forEach(t=>{this.table.modules.edit.clearEdited(t._getSelf())})}navigatePrev(e=this.currentCell,t){var s,a;if(e){if(t&&t.preventDefault(),s=this.navigateLeft(),s)return!0;if(a=this.table.rowManager.prevDisplayRow(e.row,!0),a&&(s=this.findPrevEditableCell(a,a.cells.length),s))return s.getComponent().edit(),!0}return!1}navigateNext(e=this.currentCell,t){var s,a;if(e){if(t&&t.preventDefault(),s=this.navigateRight(),s)return!0;if(a=this.table.rowManager.nextDisplayRow(e.row,!0),a&&(s=this.findNextEditableCell(a,-1),s))return s.getComponent().edit(),!0}return!1}navigateLeft(e=this.currentCell,t){var s,a;return e&&(t&&t.preventDefault(),s=e.getIndex(),a=this.findPrevEditableCell(e.row,s),a)?(a.getComponent().edit(),!0):!1}navigateRight(e=this.currentCell,t){var s,a;return e&&(t&&t.preventDefault(),s=e.getIndex(),a=this.findNextEditableCell(e.row,s),a)?(a.getComponent().edit(),!0):!1}navigateUp(e=this.currentCell,t){var s,a;return e&&(t&&t.preventDefault(),s=e.getIndex(),a=this.table.rowManager.prevDisplayRow(e.row,!0),a)?(a.cells[s].getComponent().edit(),!0):!1}navigateDown(e=this.currentCell,t){var s,a;return e&&(t&&t.preventDefault(),s=e.getIndex(),a=this.table.rowManager.nextDisplayRow(e.row,!0),a)?(a.cells[s].getComponent().edit(),!0):!1}findNextEditableCell(e,t){var s=!1;if(t<e.cells.length-1)for(var a=t+1;a<e.cells.length;a++){let i=e.cells[a];if(i.column.modules.edit&&B.elVisible(i.getElement())&&this.allowEdit(i)){s=i;break}}return s}findPrevEditableCell(e,t){var s=!1;if(t>0)for(var a=t-1;a>=0;a--){let i=e.cells[a];if(i.column.modules.edit&&B.elVisible(i.getElement())&&this.allowEdit(i)){s=i;break}}return s}initializeColumnCheck(e){typeof e.definition.editor<"u"&&this.initializeColumn(e)}columnDeleteCheck(e){this.currentCell&&this.currentCell.column===e&&this.cancelEdit()}rowDeleteCheck(e){this.currentCell&&this.currentCell.row===e&&this.cancelEdit()}rowEditableCheck(e){e.getCells().forEach(t=>{t.column.modules.edit&&typeof t.column.modules.edit.check=="function"&&this.updateCellClass(t)})}initializeColumn(e){var t=Object.keys(e.definition).includes("editorEmptyValue"),s={editor:!1,blocked:!1,check:e.definition.editable,params:e.definition.editorParams||{},convertEmptyValues:t,editorEmptyValue:e.definition.editorEmptyValue,editorEmptyValueFunc:e.definition.editorEmptyValueFunc};s.editor=this.lookupEditor(e.definition.editor,e),s.editor&&(e.modules.edit=s)}lookupEditor(e,t){var s;switch(typeof e){case"string":this.editors[e]?s=this.editors[e]:console.warn("Editor Error - No such editor found: ",e);break;case"function":s=e;break;case"boolean":e===!0&&(typeof t.definition.formatter!="function"?this.editors[t.definition.formatter]?s=this.editors[t.definition.formatter]:s=this.editors.input:console.warn("Editor Error - Cannot auto lookup editor for a custom formatter: ",t.definition.formatter));break}return s}getCurrentCell(){return this.currentCell?this.currentCell.getComponent():!1}checkEditing(){return!!this.currentCell}cancelEditEvent(){return this.currentCell?(this.cancelEdit(),!0):!1}clearEditor(e){var t=this.currentCell,s;if(this.invalidEdit=!1,t){for(this.currentCell=!1,s=t.getElement(),this.dispatch("edit-editor-clear",t,e),s.classList.remove("tabulator-editing");s.firstChild;)s.removeChild(s.firstChild);t.row.getElement().classList.remove("tabulator-editing"),t.table.element.classList.remove("tabulator-editing")}}cancelEdit(){if(this.currentCell){var e=this.currentCell,t=this.currentCell.getComponent();this.clearEditor(!0),e.setValueActual(e.getValue()),e.cellRendered(),(e.column.definition.editor=="textarea"||e.column.definition.variableHeight)&&e.row.normalizeHeight(!0),e.column.definition.cellEditCancelled&&e.column.definition.cellEditCancelled.call(this.table,t),this.dispatch("edit-cancelled",e),this.dispatchExternal("cellEditCancelled",t)}}bindEditor(e){if(e.column.modules.edit){var t=this,s=e.getElement(!0);this.updateCellClass(e),s.setAttribute("tabindex",0),s.addEventListener("mousedown",function(a){a.button===2?a.preventDefault():t.mouseClick=!0}),this.options("editTriggerEvent")==="dblclick"&&s.addEventListener("dblclick",function(a){s.classList.contains("tabulator-editing")||(s.focus({preventScroll:!0}),t.edit(e,a,!1))}),(this.options("editTriggerEvent")==="focus"||this.options("editTriggerEvent")==="click")&&s.addEventListener("click",function(a){s.classList.contains("tabulator-editing")||(s.focus({preventScroll:!0}),t.edit(e,a,!1))}),this.options("editTriggerEvent")==="focus"&&s.addEventListener("focus",function(a){t.recursionBlock||t.edit(e,a,!1)})}}focusCellNoEvent(e,t){this.recursionBlock=!0,t&&this.table.browser==="ie"||e.getElement().focus({preventScroll:!0}),this.recursionBlock=!1}editCell(e,t){this.focusCellNoEvent(e),this.edit(e,!1,t)}focusScrollAdjust(e){if(this.table.rowManager.getRenderMode()=="virtual"){var t=this.table.rowManager.element.scrollTop,s=this.table.rowManager.element.clientHeight+this.table.rowManager.element.scrollTop,a=e.row.getElement();a.offsetTop<t?this.table.rowManager.element.scrollTop-=t-a.offsetTop:a.offsetTop+a.offsetHeight>s&&(this.table.rowManager.element.scrollTop+=a.offsetTop+a.offsetHeight-s);var i=this.table.rowManager.element.scrollLeft,n=this.table.rowManager.element.clientWidth+this.table.rowManager.element.scrollLeft,r=e.getElement();this.table.modExists("frozenColumns")&&(i+=parseInt(this.table.modules.frozenColumns.leftMargin||0),n-=parseInt(this.table.modules.frozenColumns.rightMargin||0)),this.table.options.renderHorizontal==="virtual"&&(i-=parseInt(this.table.columnManager.renderer.vDomPadLeft),n-=parseInt(this.table.columnManager.renderer.vDomPadLeft)),r.offsetLeft<i?this.table.rowManager.element.scrollLeft-=i-r.offsetLeft:r.offsetLeft+r.offsetWidth>n&&(this.table.rowManager.element.scrollLeft+=r.offsetLeft+r.offsetWidth-n)}}allowEdit(e){var t=!!e.column.modules.edit;if(e.column.modules.edit)switch(typeof e.column.modules.edit.check){case"function":e.row.initialized&&(t=e.column.modules.edit.check(e.getComponent()));break;case"string":t=!!e.row.data[e.column.modules.edit.check];break;case"boolean":t=e.column.modules.edit.check;break}return t}edit(e,t,s){var a=this,i=!0,n=function(){},r=e.getElement(),o=!1,l,c,d;if(this.currentCell){!this.invalidEdit&&this.currentCell!==e&&this.cancelEdit();return}function h(v){if(a.currentCell===e&&!o){var y=a.chain("edit-success",[e,v],!0,!0);return y===!0||a.table.options.validationMode==="highlight"?(o=!0,a.clearEditor(),e.modules.edit||(e.modules.edit={}),e.modules.edit.edited=!0,a.editedCells.indexOf(e)==-1&&a.editedCells.push(e),v=a.transformEmptyValues(v,e),e.setValue(v,!0),y===!0):(o=!0,a.invalidEdit=!0,a.focusCellNoEvent(e,!0),n(),setTimeout(()=>{o=!1},10),!1)}}function u(){a.currentCell===e&&!o&&a.cancelEdit()}function f(v){n=v}if(e.column.modules.edit.blocked)return this.mouseClick=!1,this.blur(r),!1;if(t&&t.stopPropagation(),i=this.allowEdit(e),i||s){if(a.cancelEdit(),a.currentCell=e,this.focusScrollAdjust(e),c=e.getComponent(),this.mouseClick&&(this.mouseClick=!1,e.column.definition.cellClick&&e.column.definition.cellClick.call(this.table,t,c)),e.column.definition.cellEditing&&e.column.definition.cellEditing.call(this.table,c),this.dispatch("cell-editing",e),this.dispatchExternal("cellEditing",c),d=typeof e.column.modules.edit.params=="function"?e.column.modules.edit.params(c):e.column.modules.edit.params,l=e.column.modules.edit.editor.call(a,c,f,h,u,d),this.currentCell&&l!==!1)if(l instanceof Node){for(r.classList.add("tabulator-editing"),e.row.getElement().classList.add("tabulator-editing"),e.table.element.classList.add("tabulator-editing");r.firstChild;)r.removeChild(r.firstChild);r.appendChild(l),n();for(var m=r.children,b=0;b<m.length;b++)m[b].addEventListener("click",function(v){v.stopPropagation()})}else return console.warn("Edit Error - Editor should return an instance of Node, the editor returned:",l),this.blur(r),!1;else return this.blur(r),!1;return!0}else return this.mouseClick=!1,this.blur(r),!1}emptyValueCheck(e){return e===""||e===null||typeof e>"u"}transformEmptyValues(e,t){var s=t.column.modules.edit,a=s.convertEmptyValues||this.convertEmptyValues,i;return a&&(i=s.editorEmptyValueFunc||this.options("editorEmptyValueFunc"),i&&i(e)&&(e=s.convertEmptyValues?s.editorEmptyValue:this.options("editorEmptyValue"))),e}blur(e){this.confirm("edit-blur",[e])||e.blur()}getEditedCells(){var e=[];return this.editedCells.forEach(t=>{e.push(t.getComponent())}),e}clearEdited(e){var t;e.modules.edit&&e.modules.edit.edited&&(e.modules.edit.edited=!1,this.dispatch("edit-edited-clear",e)),t=this.editedCells.indexOf(e),t>-1&&this.editedCells.splice(t,1)}};g(_e,"moduleName","edit"),g(_e,"editors",ni);let Ye=_e;var ri={"=":function(p,e,t,s){return e==p},"<":function(p,e,t,s){return e<p},"<=":function(p,e,t,s){return e<=p},">":function(p,e,t,s){return e>p},">=":function(p,e,t,s){return e>=p},"!=":function(p,e,t,s){return e!=p},regex:function(p,e,t,s){return typeof p=="string"&&(p=new RegExp(p)),p.test(e)},like:function(p,e,t,s){return p===null||typeof p>"u"?e===p:typeof e<"u"&&e!==null?String(e).toLowerCase().indexOf(p.toLowerCase())>-1:!1},keywords:function(p,e,t,s){var a=p.toLowerCase().split(typeof s.separator>"u"?" ":s.separator),i=String(e===null||typeof e>"u"?"":e).toLowerCase(),n=[];return a.forEach(r=>{i.includes(r)&&n.push(!0)}),s.matchAll?n.length===a.length:!!n.length},starts:function(p,e,t,s){return p===null||typeof p>"u"?e===p:typeof e<"u"&&e!==null?String(e).toLowerCase().startsWith(p.toLowerCase()):!1},ends:function(p,e,t,s){return p===null||typeof p>"u"?e===p:typeof e<"u"&&e!==null?String(e).toLowerCase().endsWith(p.toLowerCase()):!1},in:function(p,e,t,s){return Array.isArray(p)?p.length?p.indexOf(e)>-1:!0:(console.warn("Filter Error - filter value is not an array:",p),!1)}};const N=class N extends I{constructor(e){super(e),this.filterList=[],this.headerFilters={},this.headerFilterColumns=[],this.prevHeaderFilterChangeCheck="",this.prevHeaderFilterChangeCheck="{}",this.changed=!1,this.tableInitialized=!1,this.registerTableOption("filterMode","local"),this.registerTableOption("initialFilter",!1),this.registerTableOption("initialHeaderFilter",!1),this.registerTableOption("headerFilterLiveFilterDelay",300),this.registerTableOption("placeholderHeaderFilter",!1),this.registerColumnOption("headerFilter"),this.registerColumnOption("headerFilterPlaceholder"),this.registerColumnOption("headerFilterParams"),this.registerColumnOption("headerFilterEmptyCheck"),this.registerColumnOption("headerFilterFunc"),this.registerColumnOption("headerFilterFuncParams"),this.registerColumnOption("headerFilterLiveFilter"),this.registerTableFunction("searchRows",this.searchRows.bind(this)),this.registerTableFunction("searchData",this.searchData.bind(this)),this.registerTableFunction("setFilter",this.userSetFilter.bind(this)),this.registerTableFunction("refreshFilter",this.userRefreshFilter.bind(this)),this.registerTableFunction("addFilter",this.userAddFilter.bind(this)),this.registerTableFunction("getFilters",this.getFilters.bind(this)),this.registerTableFunction("setHeaderFilterFocus",this.userSetHeaderFilterFocus.bind(this)),this.registerTableFunction("getHeaderFilterValue",this.userGetHeaderFilterValue.bind(this)),this.registerTableFunction("setHeaderFilterValue",this.userSetHeaderFilterValue.bind(this)),this.registerTableFunction("getHeaderFilters",this.getHeaderFilters.bind(this)),this.registerTableFunction("removeFilter",this.userRemoveFilter.bind(this)),this.registerTableFunction("clearFilter",this.userClearFilter.bind(this)),this.registerTableFunction("clearHeaderFilter",this.userClearHeaderFilter.bind(this)),this.registerComponentFunction("column","headerFilterFocus",this.setHeaderFilterFocus.bind(this)),this.registerComponentFunction("column","reloadHeaderFilter",this.reloadHeaderFilter.bind(this)),this.registerComponentFunction("column","getHeaderFilterValue",this.getHeaderFilterValue.bind(this)),this.registerComponentFunction("column","setHeaderFilterValue",this.setHeaderFilterValue.bind(this))}initialize(){this.subscribe("column-init",this.initializeColumnHeaderFilter.bind(this)),this.subscribe("column-width-fit-before",this.hideHeaderFilterElements.bind(this)),this.subscribe("column-width-fit-after",this.showHeaderFilterElements.bind(this)),this.subscribe("table-built",this.tableBuilt.bind(this)),this.subscribe("placeholder",this.generatePlaceholder.bind(this)),this.table.options.filterMode==="remote"&&this.subscribe("data-params",this.remoteFilterParams.bind(this)),this.registerDataHandler(this.filter.bind(this),10)}tableBuilt(){this.table.options.initialFilter&&this.setFilter(this.table.options.initialFilter),this.table.options.initialHeaderFilter&&this.table.options.initialHeaderFilter.forEach(e=>{var t=this.table.columnManager.findColumn(e.field);if(t)this.setHeaderFilterValue(t,e.value);else return console.warn("Column Filter Error - No matching column found:",e.field),!1}),this.tableInitialized=!0}remoteFilterParams(e,t,s,a){return a.filter=this.getFilters(!0,!0),a}generatePlaceholder(e){if(this.table.options.placeholderHeaderFilter&&Object.keys(this.headerFilters).length)return this.table.options.placeholderHeaderFilter}userSetFilter(e,t,s,a){this.setFilter(e,t,s,a),this.refreshFilter()}userRefreshFilter(){this.refreshFilter()}userAddFilter(e,t,s,a){this.addFilter(e,t,s,a),this.refreshFilter()}userSetHeaderFilterFocus(e){var t=this.table.columnManager.findColumn(e);if(t)this.setHeaderFilterFocus(t);else return console.warn("Column Filter Focus Error - No matching column found:",e),!1}userGetHeaderFilterValue(e){var t=this.table.columnManager.findColumn(e);if(t)return this.getHeaderFilterValue(t);console.warn("Column Filter Error - No matching column found:",e)}userSetHeaderFilterValue(e,t){var s=this.table.columnManager.findColumn(e);if(s)this.setHeaderFilterValue(s,t);else return console.warn("Column Filter Error - No matching column found:",e),!1}userRemoveFilter(e,t,s){this.removeFilter(e,t,s),this.refreshFilter()}userClearFilter(e){this.clearFilter(e),this.refreshFilter()}userClearHeaderFilter(){this.clearHeaderFilter(),this.refreshFilter()}searchRows(e,t,s){return this.search("rows",e,t,s)}searchData(e,t,s){return this.search("data",e,t,s)}initializeColumnHeaderFilter(e){var t=e.definition;t.headerFilter&&this.initializeColumn(e)}initializeColumn(e,t){var s=this,a=e.getField();function i(n){var r=e.modules.filter.tagType=="input"&&e.modules.filter.attrType=="text"||e.modules.filter.tagType=="textarea"?"partial":"match",o="",l="",c;if(typeof e.modules.filter.prevSuccess>"u"||e.modules.filter.prevSuccess!==n){if(e.modules.filter.prevSuccess=n,e.modules.filter.emptyFunc(n))delete s.headerFilters[a];else{switch(e.modules.filter.value=n,typeof e.definition.headerFilterFunc){case"string":N.filters[e.definition.headerFilterFunc]?(o=e.definition.headerFilterFunc,c=function(d){var h=e.definition.headerFilterFuncParams||{},u=e.getFieldValue(d);return h=typeof h=="function"?h(n,u,d):h,N.filters[e.definition.headerFilterFunc](n,u,d,h)}):console.warn("Header Filter Error - Matching filter function not found: ",e.definition.headerFilterFunc);break;case"function":c=function(d){var h=e.definition.headerFilterFuncParams||{},u=e.getFieldValue(d);return h=typeof h=="function"?h(n,u,d):h,e.definition.headerFilterFunc(n,u,d,h)},o=c;break}if(!c)switch(r){case"partial":c=function(d){var h=e.getFieldValue(d);return typeof h<"u"&&h!==null?String(h).toLowerCase().indexOf(String(n).toLowerCase())>-1:!1},o="like";break;default:c=function(d){return e.getFieldValue(d)==n},o="="}s.headerFilters[a]={value:n,func:c,type:o}}e.modules.filter.value=n,l=JSON.stringify(s.headerFilters),s.prevHeaderFilterChangeCheck!==l&&(s.prevHeaderFilterChangeCheck=l,s.trackChanges(),s.refreshFilter())}return!0}e.modules.filter={success:i,attrType:!1,tagType:!1,emptyFunc:!1},this.generateHeaderFilterElement(e)}generateHeaderFilterElement(e,t,s){var a=this,i=e.modules.filter.success,n=e.getField(),r,o,l,c,d,h,u,f;e.modules.filter.value=t;function m(){}function b(v){f=v}if(e.modules.filter.headerElement&&e.modules.filter.headerElement.parentNode&&e.contentElement.removeChild(e.modules.filter.headerElement.parentNode),n){switch(e.modules.filter.emptyFunc=e.definition.headerFilterEmptyCheck||function(v){return!v&&v!==0},r=document.createElement("div"),r.classList.add("tabulator-header-filter"),typeof e.definition.headerFilter){case"string":a.table.modules.edit.editors[e.definition.headerFilter]?(o=a.table.modules.edit.editors[e.definition.headerFilter],(e.definition.headerFilter==="tick"||e.definition.headerFilter==="tickCross")&&!e.definition.headerFilterEmptyCheck&&(e.modules.filter.emptyFunc=function(v){return v!==!0&&v!==!1})):console.warn("Filter Error - Cannot build header filter, No such editor found: ",e.definition.editor);break;case"function":o=e.definition.headerFilter;break;case"boolean":e.modules.edit&&e.modules.edit.editor?o=e.modules.edit.editor:e.definition.formatter&&a.table.modules.edit.editors[e.definition.formatter]?(o=a.table.modules.edit.editors[e.definition.formatter],(e.definition.formatter==="tick"||e.definition.formatter==="tickCross")&&!e.definition.headerFilterEmptyCheck&&(e.modules.filter.emptyFunc=function(v){return v!==!0&&v!==!1})):o=a.table.modules.edit.editors.input;break}if(o){if(c={getValue:function(){return typeof t<"u"?t:""},getField:function(){return e.definition.field},getElement:function(){return r},getColumn:function(){return e.getComponent()},getTable:()=>this.table,getType:()=>"header",getRow:function(){return{normalizeHeight:function(){}}}},u=e.definition.headerFilterParams||{},u=typeof u=="function"?u.call(a.table,c):u,l=o.call(this.table.modules.edit,c,b,i,m,u),!l){console.warn("Filter Error - Cannot add filter to "+n+" column, editor returned a value of false");return}if(!(l instanceof Node)){console.warn("Filter Error - Cannot add filter to "+n+" column, editor should return an instance of Node, the editor returned:",l);return}a.langBind("headerFilters|columns|"+e.definition.field,function(v){l.setAttribute("placeholder",typeof v<"u"&&v?v:e.definition.headerFilterPlaceholder||a.langText("headerFilters|default"))}),l.addEventListener("click",function(v){v.stopPropagation(),l.focus()}),l.addEventListener("focus",v=>{var y=this.table.columnManager.contentsElement.scrollLeft,$=this.table.rowManager.element.scrollLeft;y!==$&&(this.table.rowManager.scrollHorizontal(y),this.table.columnManager.scrollHorizontal(y))}),d=!1,h=function(v){d&&clearTimeout(d),d=setTimeout(function(){i(l.value)},a.table.options.headerFilterLiveFilterDelay)},e.modules.filter.headerElement=l,e.modules.filter.attrType=l.hasAttribute("type")?l.getAttribute("type").toLowerCase():"",e.modules.filter.tagType=l.tagName.toLowerCase(),e.definition.headerFilterLiveFilter!==!1&&(e.definition.headerFilter==="autocomplete"||e.definition.headerFilter==="tickCross"||(e.definition.editor==="autocomplete"||e.definition.editor==="tickCross")&&e.definition.headerFilter===!0||(l.addEventListener("keyup",h),l.addEventListener("search",h),e.modules.filter.attrType=="number"&&l.addEventListener("change",function(v){i(l.value)}),e.modules.filter.attrType=="text"&&this.table.browser!=="ie"&&l.setAttribute("type","search")),(e.modules.filter.tagType=="input"||e.modules.filter.tagType=="select"||e.modules.filter.tagType=="textarea")&&l.addEventListener("mousedown",function(v){v.stopPropagation()})),r.appendChild(l),e.contentElement.appendChild(r),s||a.headerFilterColumns.push(e),f&&f()}}else console.warn("Filter Error - Cannot add header filter, column has no field set:",e.definition.title)}hideHeaderFilterElements(){this.headerFilterColumns.forEach(function(e){e.modules.filter&&e.modules.filter.headerElement&&(e.modules.filter.headerElement.style.display="none")})}showHeaderFilterElements(){this.headerFilterColumns.forEach(function(e){e.modules.filter&&e.modules.filter.headerElement&&(e.modules.filter.headerElement.style.display="")})}setHeaderFilterFocus(e){e.modules.filter&&e.modules.filter.headerElement?e.modules.filter.headerElement.focus():console.warn("Column Filter Focus Error - No header filter set on column:",e.getField())}getHeaderFilterValue(e){if(e.modules.filter&&e.modules.filter.headerElement)return e.modules.filter.value;console.warn("Column Filter Error - No header filter set on column:",e.getField())}setHeaderFilterValue(e,t){e&&(e.modules.filter&&e.modules.filter.headerElement?(this.generateHeaderFilterElement(e,t,!0),e.modules.filter.success(t)):console.warn("Column Filter Error - No header filter set on column:",e.getField()))}reloadHeaderFilter(e){e&&(e.modules.filter&&e.modules.filter.headerElement?this.generateHeaderFilterElement(e,e.modules.filter.value,!0):console.warn("Column Filter Error - No header filter set on column:",e.getField()))}refreshFilter(){this.tableInitialized&&(this.table.options.filterMode==="remote"?this.reloadData(null,!1,!1):this.refreshData(!0))}trackChanges(){this.changed=!0,this.dispatch("filter-changed")}hasChanged(){var e=this.changed;return this.changed=!1,e}setFilter(e,t,s,a){this.filterList=[],Array.isArray(e)||(e=[{field:e,type:t,value:s,params:a}]),this.addFilter(e)}addFilter(e,t,s,a){var i=!1;Array.isArray(e)||(e=[{field:e,type:t,value:s,params:a}]),e.forEach(n=>{n=this.findFilter(n),n&&(this.filterList.push(n),i=!0)}),i&&this.trackChanges()}findFilter(e){var t;if(Array.isArray(e))return this.findSubFilters(e);var s=!1;return typeof e.field=="function"?s=function(a){return e.field(a,e.type||{})}:N.filters[e.type]?(t=this.table.columnManager.getColumnByField(e.field),t?s=function(a){return N.filters[e.type](e.value,t.getFieldValue(a),a,e.params||{})}:s=function(a){return N.filters[e.type](e.value,a[e.field],a,e.params||{})}):console.warn("Filter Error - No such filter type found, ignoring: ",e.type),e.func=s,e.func?e:!1}findSubFilters(e){var t=[];return e.forEach(s=>{s=this.findFilter(s),s&&t.push(s)}),t.length?t:!1}getFilters(e,t){var s=[];return e&&(s=this.getHeaderFilters()),t&&s.forEach(function(a){typeof a.type=="function"&&(a.type="function")}),s=s.concat(this.filtersToArray(this.filterList,t)),s}filtersToArray(e,t){var s=[];return e.forEach(a=>{var i;Array.isArray(a)?s.push(this.filtersToArray(a,t)):(i={field:a.field,type:a.type,value:a.value},t&&typeof i.type=="function"&&(i.type="function"),s.push(i))}),s}getHeaderFilters(){var e=[];for(var t in this.headerFilters)e.push({field:t,type:this.headerFilters[t].type,value:this.headerFilters[t].value});return e}removeFilter(e,t,s){Array.isArray(e)||(e=[{field:e,type:t,value:s}]),e.forEach(a=>{var i=-1;typeof a.field=="object"?i=this.filterList.findIndex(n=>a===n):i=this.filterList.findIndex(n=>a.field===n.field&&a.type===n.type&&a.value===n.value),i>-1?this.filterList.splice(i,1):console.warn("Filter Error - No matching filter type found, ignoring: ",a.type)}),this.trackChanges()}clearFilter(e){this.filterList=[],e&&this.clearHeaderFilter(),this.trackChanges()}clearHeaderFilter(){this.headerFilters={},this.prevHeaderFilterChangeCheck="{}",this.headerFilterColumns.forEach(e=>{typeof e.modules.filter.value<"u"&&delete e.modules.filter.value,e.modules.filter.prevSuccess=void 0,this.reloadHeaderFilter(e)}),this.trackChanges()}search(e,t,s,a){var i=[],n=[];return Array.isArray(t)||(t=[{field:t,type:s,value:a}]),t.forEach(r=>{r=this.findFilter(r),r&&n.push(r)}),this.table.rowManager.rows.forEach(r=>{var o=!0;n.forEach(l=>{this.filterRecurse(l,r.getData())||(o=!1)}),o&&i.push(e==="data"?r.getData("data"):r.getComponent())}),i}filter(e,t){var s=[],a=[];return this.subscribedExternal("dataFiltering")&&this.dispatchExternal("dataFiltering",this.getFilters(!0)),this.table.options.filterMode!=="remote"&&(this.filterList.length||Object.keys(this.headerFilters).length)?e.forEach(i=>{this.filterRow(i)&&s.push(i)}):s=e.slice(0),this.subscribedExternal("dataFiltered")&&(s.forEach(i=>{a.push(i.getComponent())}),this.dispatchExternal("dataFiltered",this.getFilters(!0),a)),s}filterRow(e,t){var s=!0,a=e.getData();this.filterList.forEach(n=>{this.filterRecurse(n,a)||(s=!1)});for(var i in this.headerFilters)this.headerFilters[i].func(a)||(s=!1);return s}filterRecurse(e,t){var s=!1;return Array.isArray(e)?e.forEach(a=>{this.filterRecurse(a,t)&&(s=!0)}):s=e.func(t),s}};g(N,"moduleName","filter"),g(N,"filters",ri);let Ce=N;function oi(p,e,t){return this.emptyToSpace(this.sanitizeHTML(p.getValue()))}function li(p,e,t){return p.getValue()}function ci(p,e,t){return p.getElement().style.whiteSpace="pre-wrap",this.emptyToSpace(this.sanitizeHTML(p.getValue()))}function di(p,e,t){var s=parseFloat(p.getValue()),a="",i,n,r,o,l,c=e.decimal||".",d=e.thousand||",",h=e.negativeSign||"-",u=e.symbol||"",f=!!e.symbolAfter,m=typeof e.precision<"u"?e.precision:2;if(isNaN(s))return this.emptyToSpace(this.sanitizeHTML(p.getValue()));if(s<0&&(s=Math.abs(s),a=h),i=m!==!1?s.toFixed(m):s,i=String(i).split("."),n=i[0],r=i.length>1?c+i[1]:"",e.thousand!==!1)for(o=/(\d+)(\d{3})/;o.test(n);)n=n.replace(o,"$1"+d+"$2");return l=n+r,a===!0?(l="("+l+")",f?l+u:u+l):f?a+l+u:a+u+l}function pi(p,e,t){var s=p.getValue(),a=e.urlPrefix||"",i=e.download,n=s,r=document.createElement("a"),o;function l(c,d){var h=c.shift(),u=d[h];return c.length&&typeof u=="object"?l(c,u):u}if(e.labelField&&(o=p.getData(),n=l(e.labelField.split(this.table.options.nestedFieldSeparator),o)),e.label)switch(typeof e.label){case"string":n=e.label;break;case"function":n=e.label(p);break}if(n){if(e.urlField&&(o=p.getData(),s=B.retrieveNestedData(this.table.options.nestedFieldSeparator,e.urlField,o)),e.url)switch(typeof e.url){case"string":s=e.url;break;case"function":s=e.url(p);break}return r.setAttribute("href",a+s),e.target&&r.setAttribute("target",e.target),e.download&&(typeof i=="function"?i=i(p):i=i===!0?"":i,r.setAttribute("download",i)),r.innerHTML=this.emptyToSpace(this.sanitizeHTML(n)),r}else return"&nbsp;"}function hi(p,e,t){var s=document.createElement("img"),a=p.getValue();switch(e.urlPrefix&&(a=e.urlPrefix+p.getValue()),e.urlSuffix&&(a=a+e.urlSuffix),s.setAttribute("src",a),typeof e.height){case"number":s.style.height=e.height+"px";break;case"string":s.style.height=e.height;break}switch(typeof e.width){case"number":s.style.width=e.width+"px";break;case"string":s.style.width=e.width;break}return s.addEventListener("load",function(){p.getRow().normalizeHeight()}),s}function ui(p,e,t){var s=p.getValue(),a=p.getElement(),i=e.allowEmpty,n=e.allowTruthy,r=Object.keys(e).includes("trueValue"),o=typeof e.tickElement<"u"?e.tickElement:'<svg enable-background="new 0 0 24 24" height="14" width="14" viewBox="0 0 24 24" xml:space="preserve" ><path fill="#2DC214" clip-rule="evenodd" d="M21.652,3.211c-0.293-0.295-0.77-0.295-1.061,0L9.41,14.34  c-0.293,0.297-0.771,0.297-1.062,0L3.449,9.351C3.304,9.203,3.114,9.13,2.923,9.129C2.73,9.128,2.534,9.201,2.387,9.351  l-2.165,1.946C0.078,11.445,0,11.63,0,11.823c0,0.194,0.078,0.397,0.223,0.544l4.94,5.184c0.292,0.296,0.771,0.776,1.062,1.07  l2.124,2.141c0.292,0.293,0.769,0.293,1.062,0l14.366-14.34c0.293-0.294,0.293-0.777,0-1.071L21.652,3.211z" fill-rule="evenodd"/></svg>',l=typeof e.crossElement<"u"?e.crossElement:'<svg enable-background="new 0 0 24 24" height="14" width="14"  viewBox="0 0 24 24" xml:space="preserve" ><path fill="#CE1515" d="M22.245,4.015c0.313,0.313,0.313,0.826,0,1.139l-6.276,6.27c-0.313,0.312-0.313,0.826,0,1.14l6.273,6.272  c0.313,0.313,0.313,0.826,0,1.14l-2.285,2.277c-0.314,0.312-0.828,0.312-1.142,0l-6.271-6.271c-0.313-0.313-0.828-0.313-1.141,0  l-6.276,6.267c-0.313,0.313-0.828,0.313-1.141,0l-2.282-2.28c-0.313-0.313-0.313-0.826,0-1.14l6.278-6.269  c0.313-0.312,0.313-0.826,0-1.14L1.709,5.147c-0.314-0.313-0.314-0.827,0-1.14l2.284-2.278C4.308,1.417,4.821,1.417,5.135,1.73  L11.405,8c0.314,0.314,0.828,0.314,1.141,0.001l6.276-6.267c0.312-0.312,0.826-0.312,1.141,0L22.245,4.015z"/></svg>';return r&&s===e.trueValue||!r&&(n&&s||s===!0||s==="true"||s==="True"||s===1||s==="1")?(a.setAttribute("aria-checked",!0),o||""):i&&(s==="null"||s===""||s===null||typeof s>"u")?(a.setAttribute("aria-checked","mixed"),""):(a.setAttribute("aria-checked",!1),l||"")}function fi(p,e,t){var s=this.table.dependencyRegistry.lookup(["luxon","DateTime"],"DateTime"),a=e.inputFormat||"yyyy-MM-dd HH:mm:ss",i=e.outputFormat||"dd/MM/yyyy HH:mm:ss",n=typeof e.invalidPlaceholder<"u"?e.invalidPlaceholder:"",r=p.getValue();if(typeof s<"u"){var o;return s.isDateTime(r)?o=r:a==="iso"?o=s.fromISO(String(r)):o=s.fromFormat(String(r),a),o.isValid?(e.timezone&&(o=o.setZone(e.timezone)),o.toFormat(i)):n===!0||!r?r:typeof n=="function"?n(r):n}else console.error("Format Error - 'datetime' formatter is dependant on luxon.js")}function mi(p,e,t){var s=this.table.dependencyRegistry.lookup(["luxon","DateTime"],"DateTime"),a=e.inputFormat||"yyyy-MM-dd HH:mm:ss",i=typeof e.invalidPlaceholder<"u"?e.invalidPlaceholder:"",n=typeof e.suffix<"u"?e.suffix:!1,r=typeof e.unit<"u"?e.unit:"days",o=typeof e.humanize<"u"?e.humanize:!1,l=typeof e.date<"u"?e.date:s.now(),c=p.getValue();if(typeof s<"u"){var d;return s.isDateTime(c)?d=c:a==="iso"?d=s.fromISO(String(c)):d=s.fromFormat(String(c),a),d.isValid?o?d.diff(l,r).toHuman()+(n?" "+n:""):parseInt(d.diff(l,r)[r])+(n?" "+n:""):i===!0?c:typeof i=="function"?i(c):i}else console.error("Format Error - 'datetimediff' formatter is dependant on luxon.js")}function vi(p,e,t){var s=p.getValue();return typeof e[s]>"u"?(console.warn("Missing display value for "+s),s):e[s]}function bi(p,e,t){var s=p.getValue(),a=p.getElement(),i=e&&e.stars?e.stars:5,n=document.createElement("span"),r=document.createElementNS("http://www.w3.org/2000/svg","svg"),o='<polygon fill="#FFEA00" stroke="#C1AB60" stroke-width="37.6152" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 "/>',l='<polygon fill="#D2D2D2" stroke="#686868" stroke-width="37.6152" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" points="259.216,29.942 330.27,173.919 489.16,197.007 374.185,309.08 401.33,467.31 259.216,392.612 117.104,467.31 144.25,309.08 29.274,197.007 188.165,173.919 "/>';n.style.verticalAlign="middle",r.setAttribute("width","14"),r.setAttribute("height","14"),r.setAttribute("viewBox","0 0 512 512"),r.setAttribute("xml:space","preserve"),r.style.padding="0 1px",s=s&&!isNaN(s)?parseInt(s):0,s=Math.max(0,Math.min(s,i));for(var c=1;c<=i;c++){var d=r.cloneNode(!0);d.innerHTML=c<=s?o:l,n.appendChild(d)}return a.style.whiteSpace="nowrap",a.style.overflow="hidden",a.style.textOverflow="ellipsis",a.setAttribute("aria-label",s),n}function gi(p,e,t){var s=this.sanitizeHTML(p.getValue())||0,a=document.createElement("span"),i=e&&e.max?e.max:100,n=e&&e.min?e.min:0,r=e&&typeof e.color<"u"?e.color:["red","orange","green"],o="#666666",l,c;if(!(isNaN(s)||typeof p.getValue()>"u")){switch(a.classList.add("tabulator-traffic-light"),c=parseFloat(s)<=i?parseFloat(s):i,c=parseFloat(c)>=n?parseFloat(c):n,l=(i-n)/100,c=Math.round((c-n)/l),typeof r){case"string":o=r;break;case"function":o=r(s);break;case"object":if(Array.isArray(r)){var d=100/r.length,h=Math.floor(c/d);h=Math.min(h,r.length-1),h=Math.max(h,0),o=r[h];break}}return a.style.backgroundColor=o,a}}function yi(p,e={},t){var s=this.sanitizeHTML(p.getValue())||0,a=p.getElement(),i=e.max?e.max:100,n=e.min?e.min:0,r=e.legendAlign?e.legendAlign:"center",o,l,c,d,h;switch(l=parseFloat(s)<=i?parseFloat(s):i,l=parseFloat(l)>=n?parseFloat(l):n,o=(i-n)/100,l=Math.round((l-n)/o),typeof e.color){case"string":c=e.color;break;case"function":c=e.color(s);break;case"object":if(Array.isArray(e.color)){let b=100/e.color.length,v=Math.floor(l/b);v=Math.min(v,e.color.length-1),v=Math.max(v,0),c=e.color[v];break}default:c="#2DC214"}switch(typeof e.legend){case"string":d=e.legend;break;case"function":d=e.legend(s);break;case"boolean":d=s;break;default:d=!1}switch(typeof e.legendColor){case"string":h=e.legendColor;break;case"function":h=e.legendColor(s);break;case"object":if(Array.isArray(e.legendColor)){let b=100/e.legendColor.length,v=Math.floor(l/b);v=Math.min(v,e.legendColor.length-1),v=Math.max(v,0),h=e.legendColor[v]}break;default:h="#000"}a.style.minWidth="30px",a.style.position="relative",a.setAttribute("aria-label",l);var u=document.createElement("div");u.style.display="inline-block",u.style.width=l+"%",u.style.backgroundColor=c,u.style.height="100%",u.setAttribute("data-max",i),u.setAttribute("data-min",n);var f=document.createElement("div");if(f.style.position="relative",f.style.width="100%",f.style.height="100%",d){var m=document.createElement("div");m.style.position="absolute",m.style.top=0,m.style.left=0,m.style.textAlign=r,m.style.width="100%",m.style.color=h,m.innerHTML=d}return t(function(){if(!(p instanceof Nt)){var b=document.createElement("div");b.style.position="absolute",b.style.top="4px",b.style.bottom="4px",b.style.left="4px",b.style.right="4px",a.appendChild(b),a=b}a.appendChild(f),f.appendChild(u),d&&f.appendChild(m)}),""}function _i(p,e,t){return p.getElement().style.backgroundColor=this.sanitizeHTML(p.getValue()),""}function xi(p,e,t){return'<svg enable-background="new 0 0 24 24" height="14" width="14" viewBox="0 0 24 24" xml:space="preserve" ><path fill="#2DC214" clip-rule="evenodd" d="M21.652,3.211c-0.293-0.295-0.77-0.295-1.061,0L9.41,14.34  c-0.293,0.297-0.771,0.297-1.062,0L3.449,9.351C3.304,9.203,3.114,9.13,2.923,9.129C2.73,9.128,2.534,9.201,2.387,9.351  l-2.165,1.946C0.078,11.445,0,11.63,0,11.823c0,0.194,0.078,0.397,0.223,0.544l4.94,5.184c0.292,0.296,0.771,0.776,1.062,1.07  l2.124,2.141c0.292,0.293,0.769,0.293,1.062,0l14.366-14.34c0.293-0.294,0.293-0.777,0-1.071L21.652,3.211z" fill-rule="evenodd"/></svg>'}function wi(p,e,t){return'<svg enable-background="new 0 0 24 24" height="14" width="14" viewBox="0 0 24 24" xml:space="preserve" ><path fill="#CE1515" d="M22.245,4.015c0.313,0.313,0.313,0.826,0,1.139l-6.276,6.27c-0.313,0.312-0.313,0.826,0,1.14l6.273,6.272  c0.313,0.313,0.313,0.826,0,1.14l-2.285,2.277c-0.314,0.312-0.828,0.312-1.142,0l-6.271-6.271c-0.313-0.313-0.828-0.313-1.141,0  l-6.276,6.267c-0.313,0.313-0.828,0.313-1.141,0l-2.282-2.28c-0.313-0.313-0.313-0.826,0-1.14l6.278-6.269  c0.313-0.312,0.313-0.826,0-1.14L1.709,5.147c-0.314-0.313-0.314-0.827,0-1.14l2.284-2.278C4.308,1.417,4.821,1.417,5.135,1.73  L11.405,8c0.314,0.314,0.828,0.314,1.141,0.001l6.276-6.267c0.312-0.312,0.826-0.312,1.141,0L22.245,4.015z"/></svg>'}function $i(p,e,t){var s=p.getValue(),a=e.size||15,i=a+"px",n,r,o=e.hasOwnProperty("onValue")?e.onValue:!0,l=e.hasOwnProperty("offValue")?e.offValue:!1,c=e.onTruthy?s:s===o;return n=document.createElement("div"),n.classList.add("tabulator-toggle"),c?(n.classList.add("tabulator-toggle-on"),n.style.flexDirection="row-reverse",e.onColor&&(n.style.background=e.onColor)):e.offColor&&(n.style.background=e.offColor),n.style.width=2.5*a+"px",n.style.borderRadius=i,e.clickable&&n.addEventListener("click",d=>{p.setValue(c?l:o)}),r=document.createElement("div"),r.classList.add("tabulator-toggle-switch"),r.style.height=i,r.style.width=i,r.style.borderRadius=i,n.appendChild(r),n}function ki(p,e,t){var s=document.createElement("span"),a=p.getRow(),i=p.getTable();return a.watchPosition(n=>{e.relativeToPage&&(n+=i.modules.page.getPageSize()*(i.modules.page.getPage()-1)),s.innerText=n}),s}function Ei(p,e,t){return p.getElement().classList.add("tabulator-row-handle"),"<div class='tabulator-row-handle-box'><div class='tabulator-row-handle-bar'></div><div class='tabulator-row-handle-bar'></div><div class='tabulator-row-handle-bar'></div></div>"}function Li(p,e,t){var s,a,i;function n(r){var o=r.getValue(),l="plaintext";switch(typeof o){case"boolean":l="tickCross";break;case"string":o.includes(`
`)&&(l="textarea");break}return l}return s=e.formatterLookup?e.formatterLookup(p):n(p),e.paramsLookup&&(i=typeof e.paramsLookup=="function"?e.paramsLookup(s,p):e.paramsLookup[s]),a=this.table.modules.format.lookupFormatter(s),a.call(this,p,i||{},t)}function Si(p,e,t){var s=e.delimiter||",",a=p.getValue(),i=this.table,n;return e.valueMap&&(typeof e.valueMap=="string"?n=function(r){return r.map(o=>B.retrieveNestedData(i.options.nestedFieldSeparator,e.valueMap,o))}:n=e.valueMap),Array.isArray(a)?(n&&(a=n(a)),a.join(s)):a}function Ci(p,e,t){var s=e.indent||"	",a=typeof e.multiline>"u"?!0:e.multiline,i=e.replacer||null,n=p.getValue();return a&&(p.getElement().style.whiteSpace="pre-wrap"),JSON.stringify(n,i,s)}var Ti={plaintext:oi,html:li,textarea:ci,money:di,link:pi,image:hi,tickCross:ui,datetime:fi,datetimediff:mi,lookup:vi,star:bi,traffic:gi,progress:yi,color:_i,buttonTick:xi,buttonCross:wi,toggle:$i,rownum:ki,handle:Ei,adaptable:Li,array:Si,json:Ci};const K=class K extends I{constructor(e){super(e),this.registerColumnOption("formatter"),this.registerColumnOption("formatterParams"),this.registerColumnOption("formatterPrint"),this.registerColumnOption("formatterPrintParams"),this.registerColumnOption("formatterClipboard"),this.registerColumnOption("formatterClipboardParams"),this.registerColumnOption("formatterHtmlOutput"),this.registerColumnOption("formatterHtmlOutputParams"),this.registerColumnOption("titleFormatter"),this.registerColumnOption("titleFormatterParams")}initialize(){this.subscribe("cell-format",this.formatValue.bind(this)),this.subscribe("cell-rendered",this.cellRendered.bind(this)),this.subscribe("column-layout",this.initializeColumn.bind(this)),this.subscribe("column-format",this.formatHeader.bind(this))}initializeColumn(e){e.modules.format=this.lookupTypeFormatter(e,""),typeof e.definition.formatterPrint<"u"&&(e.modules.format.print=this.lookupTypeFormatter(e,"Print")),typeof e.definition.formatterClipboard<"u"&&(e.modules.format.clipboard=this.lookupTypeFormatter(e,"Clipboard")),typeof e.definition.formatterHtmlOutput<"u"&&(e.modules.format.htmlOutput=this.lookupTypeFormatter(e,"HtmlOutput"))}lookupTypeFormatter(e,t){var s={params:e.definition["formatter"+t+"Params"]||{}},a=e.definition["formatter"+t];return s.formatter=this.lookupFormatter(a),s}lookupFormatter(e){var t;switch(typeof e){case"string":K.formatters[e]?t=K.formatters[e]:(console.warn("Formatter Error - No such formatter found: ",e),t=K.formatters.plaintext);break;case"function":t=e;break;default:t=K.formatters.plaintext;break}return t}cellRendered(e){e.modules.format&&e.modules.format.renderedCallback&&!e.modules.format.rendered&&(e.modules.format.renderedCallback(),e.modules.format.rendered=!0)}formatHeader(e,t,s){var a,i,n,r;return e.definition.titleFormatter?(a=this.lookupFormatter(e.definition.titleFormatter),n=o=>{e.titleFormatterRendered=o},r={getValue:function(){return t},getElement:function(){return s},getType:function(){return"header"},getColumn:function(){return e.getComponent()},getTable:()=>this.table},i=e.definition.titleFormatterParams||{},i=typeof i=="function"?i():i,a.call(this,r,i,n)):t}formatValue(e){var t=e.getComponent(),s=typeof e.column.modules.format.params=="function"?e.column.modules.format.params(t):e.column.modules.format.params;function a(i){e.modules.format||(e.modules.format={}),e.modules.format.renderedCallback=i,e.modules.format.rendered=!1}return e.column.modules.format.formatter.call(this,t,s,a)}formatExportValue(e,t){var s=e.column.modules.format[t],a;if(s){let i=function(n){e.modules.format||(e.modules.format={}),e.modules.format.renderedCallback=n,e.modules.format.rendered=!1};return a=typeof s.params=="function"?s.params(e.getComponent()):s.params,s.formatter.call(this,e.getComponent(),a,i)}else return this.formatValue(e)}sanitizeHTML(e){if(e){var t={"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#39;","/":"&#x2F;","`":"&#x60;","=":"&#x3D;"};return String(e).replace(/[&<>"'`=/]/g,function(s){return t[s]})}else return e}emptyToSpace(e){return e===null||typeof e>"u"||e===""?"&nbsp;":e}};g(K,"moduleName","format"),g(K,"formatters",Ti);let Te=K;class Qe extends I{constructor(e){super(e),this.eventMap={rowClick:"row-click",rowDblClick:"row-dblclick",rowContext:"row-contextmenu",rowMouseEnter:"row-mouseenter",rowMouseLeave:"row-mouseleave",rowMouseOver:"row-mouseover",rowMouseOut:"row-mouseout",rowMouseMove:"row-mousemove",rowMouseDown:"row-mousedown",rowMouseUp:"row-mouseup",rowTap:"row",rowDblTap:"row",rowTapHold:"row",cellClick:"cell-click",cellDblClick:"cell-dblclick",cellContext:"cell-contextmenu",cellMouseEnter:"cell-mouseenter",cellMouseLeave:"cell-mouseleave",cellMouseOver:"cell-mouseover",cellMouseOut:"cell-mouseout",cellMouseMove:"cell-mousemove",cellMouseDown:"cell-mousedown",cellMouseUp:"cell-mouseup",cellTap:"cell",cellDblTap:"cell",cellTapHold:"cell",headerClick:"column-click",headerDblClick:"column-dblclick",headerContext:"column-contextmenu",headerMouseEnter:"column-mouseenter",headerMouseLeave:"column-mouseleave",headerMouseOver:"column-mouseover",headerMouseOut:"column-mouseout",headerMouseMove:"column-mousemove",headerMouseDown:"column-mousedown",headerMouseUp:"column-mouseup",headerTap:"column",headerDblTap:"column",headerTapHold:"column",groupClick:"group-click",groupDblClick:"group-dblclick",groupContext:"group-contextmenu",groupMouseEnter:"group-mouseenter",groupMouseLeave:"group-mouseleave",groupMouseOver:"group-mouseover",groupMouseOut:"group-mouseout",groupMouseMove:"group-mousemove",groupMouseDown:"group-mousedown",groupMouseUp:"group-mouseup",groupTap:"group",groupDblTap:"group",groupTapHold:"group"},this.subscribers={},this.touchSubscribers={},this.columnSubscribers={},this.touchWatchers={row:{tap:null,tapDbl:null,tapHold:null},cell:{tap:null,tapDbl:null,tapHold:null},column:{tap:null,tapDbl:null,tapHold:null},group:{tap:null,tapDbl:null,tapHold:null}},this.registerColumnOption("headerClick"),this.registerColumnOption("headerDblClick"),this.registerColumnOption("headerContext"),this.registerColumnOption("headerMouseEnter"),this.registerColumnOption("headerMouseLeave"),this.registerColumnOption("headerMouseOver"),this.registerColumnOption("headerMouseOut"),this.registerColumnOption("headerMouseMove"),this.registerColumnOption("headerMouseDown"),this.registerColumnOption("headerMouseUp"),this.registerColumnOption("headerTap"),this.registerColumnOption("headerDblTap"),this.registerColumnOption("headerTapHold"),this.registerColumnOption("cellClick"),this.registerColumnOption("cellDblClick"),this.registerColumnOption("cellContext"),this.registerColumnOption("cellMouseEnter"),this.registerColumnOption("cellMouseLeave"),this.registerColumnOption("cellMouseOver"),this.registerColumnOption("cellMouseOut"),this.registerColumnOption("cellMouseMove"),this.registerColumnOption("cellMouseDown"),this.registerColumnOption("cellMouseUp"),this.registerColumnOption("cellTap"),this.registerColumnOption("cellDblTap"),this.registerColumnOption("cellTapHold")}initialize(){this.initializeExternalEvents(),this.subscribe("column-init",this.initializeColumn.bind(this)),this.subscribe("cell-dblclick",this.cellContentsSelectionFixer.bind(this)),this.subscribe("scroll-horizontal",this.clearTouchWatchers.bind(this)),this.subscribe("scroll-vertical",this.clearTouchWatchers.bind(this))}clearTouchWatchers(){var e=Object.values(this.touchWatchers);e.forEach(t=>{for(let s in t)t[s]=null})}cellContentsSelectionFixer(e,t){var s;if(!(this.table.modExists("edit")&&this.table.modules.edit.currentCell===t)){e.preventDefault();try{document.selection?(s=document.body.createTextRange(),s.moveToElementText(t.getElement()),s.select()):window.getSelection&&(s=document.createRange(),s.selectNode(t.getElement()),window.getSelection().removeAllRanges(),window.getSelection().addRange(s))}catch{}}}initializeExternalEvents(){for(let e in this.eventMap)this.subscriptionChangeExternal(e,this.subscriptionChanged.bind(this,e))}subscriptionChanged(e,t){t?this.subscribers[e]||(this.eventMap[e].includes("-")?(this.subscribers[e]=this.handle.bind(this,e),this.subscribe(this.eventMap[e],this.subscribers[e])):this.subscribeTouchEvents(e)):this.eventMap[e].includes("-")?this.subscribers[e]&&!this.columnSubscribers[e]&&!this.subscribedExternal(e)&&(this.unsubscribe(this.eventMap[e],this.subscribers[e]),delete this.subscribers[e]):this.unsubscribeTouchEvents(e)}subscribeTouchEvents(e){var t=this.eventMap[e];this.touchSubscribers[t+"-touchstart"]||(this.touchSubscribers[t+"-touchstart"]=this.handleTouch.bind(this,t,"start"),this.touchSubscribers[t+"-touchend"]=this.handleTouch.bind(this,t,"end"),this.subscribe(t+"-touchstart",this.touchSubscribers[t+"-touchstart"]),this.subscribe(t+"-touchend",this.touchSubscribers[t+"-touchend"])),this.subscribers[e]=!0}unsubscribeTouchEvents(e){var t=!0,s=this.eventMap[e];if(this.subscribers[e]&&!this.subscribedExternal(e)){delete this.subscribers[e];for(let a in this.eventMap)this.eventMap[a]===s&&this.subscribers[a]&&(t=!1);t&&(this.unsubscribe(s+"-touchstart",this.touchSubscribers[s+"-touchstart"]),this.unsubscribe(s+"-touchend",this.touchSubscribers[s+"-touchend"]),delete this.touchSubscribers[s+"-touchstart"],delete this.touchSubscribers[s+"-touchend"])}}initializeColumn(e){var t=e.definition;for(let s in this.eventMap)t[s]&&(this.subscriptionChanged(s,!0),this.columnSubscribers[s]||(this.columnSubscribers[s]=[]),this.columnSubscribers[s].push(e))}handle(e,t,s){this.dispatchEvent(e,t,s)}handleTouch(e,t,s,a){var i=this.touchWatchers[e];switch(e==="column"&&(e="header"),t){case"start":i.tap=!0,clearTimeout(i.tapHold),i.tapHold=setTimeout(()=>{clearTimeout(i.tapHold),i.tapHold=null,i.tap=null,clearTimeout(i.tapDbl),i.tapDbl=null,this.dispatchEvent(e+"TapHold",s,a)},1e3);break;case"end":i.tap&&(i.tap=null,this.dispatchEvent(e+"Tap",s,a)),i.tapDbl?(clearTimeout(i.tapDbl),i.tapDbl=null,this.dispatchEvent(e+"DblTap",s,a)):i.tapDbl=setTimeout(()=>{clearTimeout(i.tapDbl),i.tapDbl=null},300),clearTimeout(i.tapHold),i.tapHold=null;break}}dispatchEvent(e,t,s){var a=s.getComponent(),i;this.columnSubscribers[e]&&(s instanceof Vt?i=s.column.definition[e]:s instanceof te&&(i=s.definition[e]),i&&i(t,a)),this.dispatchExternal(e,t,a)}}g(Qe,"moduleName","interaction");function Mi(p,e,t,s,a){var i=document.createElement("span"),n=document.createElement("span"),r=document.createElement("span"),o=document.createElement("span"),l=document.createElement("span"),c=document.createElement("span");return this.table.modules.localize.langBind("pagination|counter|showing",d=>{n.innerHTML=d}),this.table.modules.localize.langBind("pagination|counter|of",d=>{o.innerHTML=d}),this.table.modules.localize.langBind("pagination|counter|rows",d=>{c.innerHTML=d}),s?(r.innerHTML=" "+e+"-"+Math.min(e+p-1,s)+" ",l.innerHTML=" "+s+" ",i.appendChild(n),i.appendChild(r),i.appendChild(o),i.appendChild(l),i.appendChild(c)):(r.innerHTML=" 0 ",i.appendChild(n),i.appendChild(r),i.appendChild(c)),i}function Ri(p,e,t,s,a){var i=document.createElement("span"),n=document.createElement("span"),r=document.createElement("span"),o=document.createElement("span"),l=document.createElement("span"),c=document.createElement("span");return this.table.modules.localize.langBind("pagination|counter|showing",d=>{n.innerHTML=d}),r.innerHTML=" "+t+" ",this.table.modules.localize.langBind("pagination|counter|of",d=>{o.innerHTML=d}),l.innerHTML=" "+a+" ",this.table.modules.localize.langBind("pagination|counter|pages",d=>{c.innerHTML=d}),i.appendChild(n),i.appendChild(r),i.appendChild(o),i.appendChild(l),i.appendChild(c),i}var qi={rows:Mi,pages:Ri};const xe=class xe extends I{constructor(e){super(e),this.mode="local",this.progressiveLoad=!1,this.element=null,this.pageCounterElement=null,this.pageCounter=null,this.size=0,this.page=1,this.count=5,this.max=1,this.remoteRowCountEstimate=null,this.initialLoad=!0,this.dataChanging=!1,this.pageSizes=[],this.registerTableOption("pagination",!1),this.registerTableOption("paginationMode","local"),this.registerTableOption("paginationSize",!1),this.registerTableOption("paginationInitialPage",1),this.registerTableOption("paginationCounter",!1),this.registerTableOption("paginationCounterElement",!1),this.registerTableOption("paginationButtonCount",5),this.registerTableOption("paginationSizeSelector",!1),this.registerTableOption("paginationElement",!1),this.registerTableOption("paginationAddRow","page"),this.registerTableOption("paginationOutOfRange",!1),this.registerTableOption("progressiveLoad",!1),this.registerTableOption("progressiveLoadDelay",0),this.registerTableOption("progressiveLoadScrollMargin",0),this.registerTableFunction("setMaxPage",this.setMaxPage.bind(this)),this.registerTableFunction("setPage",this.setPage.bind(this)),this.registerTableFunction("setPageToRow",this.userSetPageToRow.bind(this)),this.registerTableFunction("setPageSize",this.userSetPageSize.bind(this)),this.registerTableFunction("getPageSize",this.getPageSize.bind(this)),this.registerTableFunction("previousPage",this.previousPage.bind(this)),this.registerTableFunction("nextPage",this.nextPage.bind(this)),this.registerTableFunction("getPage",this.getPage.bind(this)),this.registerTableFunction("getPageMax",this.getPageMax.bind(this)),this.registerComponentFunction("row","pageTo",this.setPageToRow.bind(this))}initialize(){this.table.options.pagination?(this.subscribe("row-deleted",this.rowsUpdated.bind(this)),this.subscribe("row-added",this.rowsUpdated.bind(this)),this.subscribe("data-processed",this.initialLoadComplete.bind(this)),this.subscribe("table-built",this.calculatePageSizes.bind(this)),this.subscribe("footer-redraw",this.footerRedraw.bind(this)),this.table.options.paginationAddRow=="page"&&this.subscribe("row-adding-position",this.rowAddingPosition.bind(this)),this.table.options.paginationMode==="remote"&&(this.subscribe("data-params",this.remotePageParams.bind(this)),this.subscribe("data-loaded",this._parseRemoteData.bind(this))),this.table.options.progressiveLoad&&console.error("Progressive Load Error - Pagination and progressive load cannot be used at the same time"),this.registerDisplayHandler(this.restOnRenderBefore.bind(this),40),this.registerDisplayHandler(this.getRows.bind(this),50),this.createElements(),this.initializePageCounter(),this.initializePaginator()):this.table.options.progressiveLoad&&(this.subscribe("data-params",this.remotePageParams.bind(this)),this.subscribe("data-loaded",this._parseRemoteData.bind(this)),this.subscribe("table-built",this.calculatePageSizes.bind(this)),this.subscribe("data-processed",this.initialLoadComplete.bind(this)),this.initializeProgressive(this.table.options.progressiveLoad),this.table.options.progressiveLoad==="scroll"&&this.subscribe("scroll-vertical",this.scrollVertical.bind(this)))}rowAddingPosition(e,t){var s=this.table.rowManager,a=s.getDisplayRows(),i;return t?a.length?i=a[0]:s.activeRows.length&&(i=s.activeRows[s.activeRows.length-1],t=!1):a.length&&(i=a[a.length-1],t=!(a.length<this.size)),{index:i,top:t}}calculatePageSizes(){var e,t;this.table.options.paginationSize?this.size=this.table.options.paginationSize:(e=document.createElement("div"),e.classList.add("tabulator-row"),e.style.visibility="hidden",t=document.createElement("div"),t.classList.add("tabulator-cell"),t.innerHTML="Page Row Test",e.appendChild(t),this.table.rowManager.getTableElement().appendChild(e),this.size=Math.floor(this.table.rowManager.getElement().clientHeight/e.offsetHeight),this.table.rowManager.getTableElement().removeChild(e)),this.dispatchExternal("pageSizeChanged",this.size),this.generatePageSizeSelectList()}initialLoadComplete(){this.initialLoad=!1}remotePageParams(e,t,s,a){return this.initialLoad||(this.progressiveLoad&&!s||!this.progressiveLoad&&!this.dataChanging)&&this.reset(!0),a.page=this.page,this.size&&(a.size=this.size),a}userSetPageToRow(e){return this.table.options.pagination&&(e=this.table.rowManager.findRow(e),e)?this.setPageToRow(e):Promise.reject()}userSetPageSize(e){return this.table.options.pagination?(this.setPageSize(e),this.setPage(1)):!1}scrollVertical(e,t){var s,a,i;!t&&!this.table.dataLoader.loading&&(s=this.table.rowManager.getElement(),a=s.scrollHeight-s.clientHeight-e,i=this.table.options.progressiveLoadScrollMargin||s.clientHeight*2,a<i&&this.nextPage().catch(()=>{}))}restOnRenderBefore(e,t){return t||this.mode==="local"&&this.reset(),e}rowsUpdated(){this.refreshData(!0,"all")}createElements(){var e;this.element=document.createElement("span"),this.element.classList.add("tabulator-paginator"),this.pagesElement=document.createElement("span"),this.pagesElement.classList.add("tabulator-pages"),e=document.createElement("button"),e.classList.add("tabulator-page"),e.setAttribute("type","button"),e.setAttribute("role","button"),e.setAttribute("aria-label",""),e.setAttribute("title",""),this.firstBut=e.cloneNode(!0),this.firstBut.setAttribute("data-page","first"),this.prevBut=e.cloneNode(!0),this.prevBut.setAttribute("data-page","prev"),this.nextBut=e.cloneNode(!0),this.nextBut.setAttribute("data-page","next"),this.lastBut=e.cloneNode(!0),this.lastBut.setAttribute("data-page","last"),this.table.options.paginationSizeSelector&&(this.pageSizeSelect=document.createElement("select"),this.pageSizeSelect.classList.add("tabulator-page-size"))}generatePageSizeSelectList(){var e=[];if(this.pageSizeSelect){if(Array.isArray(this.table.options.paginationSizeSelector))e=this.table.options.paginationSizeSelector,this.pageSizes=e,this.pageSizes.indexOf(this.size)==-1&&e.unshift(this.size);else if(this.pageSizes.indexOf(this.size)==-1){e=[];for(let t=1;t<5;t++)e.push(this.size*t);this.pageSizes=e}else e=this.pageSizes;for(;this.pageSizeSelect.firstChild;)this.pageSizeSelect.removeChild(this.pageSizeSelect.firstChild);e.forEach(t=>{var s=document.createElement("option");s.value=t,t===!0?this.langBind("pagination|all",function(a){s.innerHTML=a}):s.innerHTML=t,this.pageSizeSelect.appendChild(s)}),this.pageSizeSelect.value=this.size}}initializePageCounter(){var e=this.table.options.paginationCounter,t=null;e&&(typeof e=="function"?t=e:t=xe.pageCounters[e],t?(this.pageCounter=t,this.pageCounterElement=document.createElement("span"),this.pageCounterElement.classList.add("tabulator-page-counter")):console.warn("Pagination Error - No such page counter found: ",e))}initializePaginator(e){var t,s;e||(this.langBind("pagination|first",a=>{this.firstBut.innerHTML=a}),this.langBind("pagination|first_title",a=>{this.firstBut.setAttribute("aria-label",a),this.firstBut.setAttribute("title",a)}),this.langBind("pagination|prev",a=>{this.prevBut.innerHTML=a}),this.langBind("pagination|prev_title",a=>{this.prevBut.setAttribute("aria-label",a),this.prevBut.setAttribute("title",a)}),this.langBind("pagination|next",a=>{this.nextBut.innerHTML=a}),this.langBind("pagination|next_title",a=>{this.nextBut.setAttribute("aria-label",a),this.nextBut.setAttribute("title",a)}),this.langBind("pagination|last",a=>{this.lastBut.innerHTML=a}),this.langBind("pagination|last_title",a=>{this.lastBut.setAttribute("aria-label",a),this.lastBut.setAttribute("title",a)}),this.firstBut.addEventListener("click",()=>{this.setPage(1)}),this.prevBut.addEventListener("click",()=>{this.previousPage()}),this.nextBut.addEventListener("click",()=>{this.nextPage()}),this.lastBut.addEventListener("click",()=>{this.setPage(this.max)}),this.table.options.paginationElement&&(this.element=this.table.options.paginationElement),this.pageSizeSelect&&(t=document.createElement("label"),this.langBind("pagination|page_size",a=>{this.pageSizeSelect.setAttribute("aria-label",a),this.pageSizeSelect.setAttribute("title",a),t.innerHTML=a}),this.element.appendChild(t),this.element.appendChild(this.pageSizeSelect),this.pageSizeSelect.addEventListener("change",a=>{this.setPageSize(this.pageSizeSelect.value=="true"?!0:this.pageSizeSelect.value),this.setPage(1)})),this.element.appendChild(this.firstBut),this.element.appendChild(this.prevBut),this.element.appendChild(this.pagesElement),this.element.appendChild(this.nextBut),this.element.appendChild(this.lastBut),this.table.options.paginationElement||(this.table.options.paginationCounter&&(this.table.options.paginationCounterElement?this.table.options.paginationCounterElement instanceof HTMLElement?this.table.options.paginationCounterElement.appendChild(this.pageCounterElement):typeof this.table.options.paginationCounterElement=="string"&&(s=document.querySelector(this.table.options.paginationCounterElement),s?s.appendChild(this.pageCounterElement):console.warn("Pagination Error - Unable to find element matching paginationCounterElement selector:",this.table.options.paginationCounterElement)):this.footerAppend(this.pageCounterElement)),this.footerAppend(this.element)),this.page=this.table.options.paginationInitialPage,this.count=this.table.options.paginationButtonCount),this.mode=this.table.options.paginationMode}initializeProgressive(e){this.initializePaginator(!0),this.mode="progressive_"+e,this.progressiveLoad=!0}trackChanges(){this.dispatch("page-changed")}setMaxRows(e){e?this.max=this.size===!0?1:Math.ceil(e/this.size):this.max=1,this.page>this.max&&(this.page=this.max)}reset(e){this.initialLoad||(this.mode=="local"||e)&&(this.page=1,this.trackChanges())}setMaxPage(e){e=parseInt(e),this.max=e||1,this.page>this.max&&(this.page=this.max,this.trigger())}setPage(e){switch(e){case"first":return this.setPage(1);case"prev":return this.previousPage();case"next":return this.nextPage();case"last":return this.setPage(this.max)}return e=parseInt(e),e>0&&e<=this.max||this.mode!=="local"?(this.page=e,this.trackChanges(),this.trigger()):(console.warn("Pagination Error - Requested page is out of range of 1 - "+this.max+":",e),Promise.reject())}setPageToRow(e){var t=this.displayRows(-1),s=t.indexOf(e);if(s>-1){var a=this.size===!0?1:Math.ceil((s+1)/this.size);return this.setPage(a)}else return console.warn("Pagination Error - Requested row is not visible"),Promise.reject()}setPageSize(e){e!==!0&&(e=parseInt(e)),e>0&&(this.size=e,this.dispatchExternal("pageSizeChanged",e)),this.pageSizeSelect&&this.generatePageSizeSelectList(),this.trackChanges()}_setPageCounter(e,t,s){var a;if(this.pageCounter)switch(this.mode==="remote"&&(t=this.size,s=(this.page-1)*this.size+1,e=this.remoteRowCountEstimate),a=this.pageCounter.call(this,t,s,this.page,e,this.max),typeof a){case"object":if(a instanceof Node){for(;this.pageCounterElement.firstChild;)this.pageCounterElement.removeChild(this.pageCounterElement.firstChild);this.pageCounterElement.appendChild(a)}else this.pageCounterElement.innerHTML="",a!=null&&console.warn("Page Counter Error - Page Counter has returned a type of object, the only valid page counter object return is an instance of Node, the page counter returned:",a);break;case"undefined":this.pageCounterElement.innerHTML="";break;default:this.pageCounterElement.innerHTML=a}}_setPageButtons(){let e=Math.floor((this.count-1)/2),t=Math.ceil((this.count-1)/2),s=this.max-this.page+e+1<this.count?this.max-this.count+1:Math.max(this.page-e,1),a=this.page<=t?Math.min(this.count,this.max):Math.min(this.page+t,this.max);for(;this.pagesElement.firstChild;)this.pagesElement.removeChild(this.pagesElement.firstChild);this.page==1?(this.firstBut.disabled=!0,this.prevBut.disabled=!0):(this.firstBut.disabled=!1,this.prevBut.disabled=!1),this.page==this.max?(this.lastBut.disabled=!0,this.nextBut.disabled=!0):(this.lastBut.disabled=!1,this.nextBut.disabled=!1);for(let i=s;i<=a;i++)i>0&&i<=this.max&&this.pagesElement.appendChild(this._generatePageButton(i));this.footerRedraw()}_generatePageButton(e){var t=document.createElement("button");return t.classList.add("tabulator-page"),e==this.page&&t.classList.add("active"),t.setAttribute("type","button"),t.setAttribute("role","button"),this.langBind("pagination|page_title",s=>{t.setAttribute("aria-label",s+" "+e),t.setAttribute("title",s+" "+e)}),t.setAttribute("data-page",e),t.textContent=e,t.addEventListener("click",s=>{this.setPage(e)}),t}previousPage(){return this.page>1?(this.page--,this.trackChanges(),this.trigger()):(console.warn("Pagination Error - Previous page would be less than page 1:",0),Promise.reject())}nextPage(){return this.page<this.max?(this.page++,this.trackChanges(),this.trigger()):(this.progressiveLoad||console.warn("Pagination Error - Next page would be greater than maximum page of "+this.max+":",this.max+1),Promise.reject())}getPage(){return this.page}getPageMax(){return this.max}getPageSize(e){return this.size}getMode(){return this.mode}getRows(e){var t=0,s,a,i,n,r=e.filter(o=>o.type==="row");if(this.mode=="local"){s=[],this.setMaxRows(e.length),this.size===!0?(a=0,i=e.length):(a=this.size*(this.page-1),i=a+parseInt(this.size)),this._setPageButtons();for(let o=a;o<i;o++){let l=e[o];l&&(s.push(l),l.type==="row"&&(n||(n=l),t++))}return this._setPageCounter(r.length,t,n?r.indexOf(n)+1:0),s}else return this._setPageButtons(),this._setPageCounter(r.length),e.slice(0)}trigger(){var e;switch(this.mode){case"local":return e=this.table.rowManager.scrollLeft,this.refreshData(),this.table.rowManager.scrollHorizontal(e),this.dispatchExternal("pageLoaded",this.getPage()),Promise.resolve();case"remote":return this.dataChanging=!0,this.reloadData(null).finally(()=>{this.dataChanging=!1});case"progressive_load":case"progressive_scroll":return this.reloadData(null,!0);default:return console.warn("Pagination Error - no such pagination mode:",this.mode),Promise.reject()}}_parseRemoteData(e){var t,s;if(typeof e.last_page>"u"&&console.warn("Remote Pagination Error - Server response missing '"+(this.options("dataReceiveParams").last_page||"last_page")+"' property"),e.data)if(this.max=parseInt(e.last_page)||1,this.remoteRowCountEstimate=typeof e.last_row<"u"?e.last_row:e.last_page*this.size-(this.page==e.last_page?this.size-e.data.length:0),this.progressiveLoad){switch(this.mode){case"progressive_load":this.page==1?this.table.rowManager.setData(e.data,!1,this.page==1):this.table.rowManager.addRows(e.data),this.page<this.max&&setTimeout(()=>{this.nextPage()},this.table.options.progressiveLoadDelay);break;case"progressive_scroll":e=this.page===1?e.data:this.table.rowManager.getData().concat(e.data),this.table.rowManager.setData(e,this.page!==1,this.page==1),t=this.table.options.progressiveLoadScrollMargin||this.table.rowManager.element.clientHeight*2,this.table.rowManager.element.scrollHeight<=this.table.rowManager.element.clientHeight+t&&this.page<this.max&&setTimeout(()=>{this.nextPage()});break}return!1}else{if(this.page>this.max&&(console.warn("Remote Pagination Error - Server returned last page value lower than the current page"),s=this.options("paginationOutOfRange"),s))return this.setPage(typeof s=="function"?s.call(this,this.page,this.max):s);this.dispatchExternal("pageLoaded",this.getPage())}else console.warn("Remote Pagination Error - Server response missing '"+(this.options("dataReceiveParams").data||"data")+"' property");return e.data}footerRedraw(){var e=this.table.footerManager.containerElement;Math.ceil(e.clientWidth)-e.scrollWidth<0?this.pagesElement.style.display="none":(this.pagesElement.style.display="",Math.ceil(e.clientWidth)-e.scrollWidth<0&&(this.pagesElement.style.display="none"))}};g(xe,"moduleName","page"),g(xe,"pageCounters",qi);let Me=xe;function Hi(p,e,t){var s=document.createElement("input"),a=!1;if(s.type="checkbox",s.setAttribute("aria-label","Select Row"),this.table.modExists("selectRow",!0))if(s.addEventListener("click",n=>{n.stopPropagation()}),typeof p.getRow=="function"){var i=p.getRow();i instanceof Je?(s.addEventListener("change",n=>{this.table.options.selectableRowsRangeMode==="click"&&a?a=!1:i.toggleSelect()}),this.table.options.selectableRowsRangeMode==="click"&&s.addEventListener("click",n=>{a=!0,this.table.modules.selectRow.handleComplexRowClick(i._row,n)}),s.checked=i.isSelected&&i.isSelected(),this.table.modules.selectRow.registerRowSelectCheckbox(i,s)):s=""}else s.addEventListener("change",n=>{this.table.modules.selectRow.selectedRows.length?this.table.deselectRow():this.table.selectRow(e.rowRange)}),this.table.modules.selectRow.registerHeaderSelectCheckbox(s);return s}var Bi={format:{formatters:{rowSelection:Hi}}};class Ze extends I{constructor(e){super(e),this.selecting=!1,this.lastClickedRow=!1,this.selectPrev=[],this.selectedRows=[],this.headerCheckboxElement=null,this.registerTableOption("selectableRows","highlight"),this.registerTableOption("selectableRowsRangeMode","drag"),this.registerTableOption("selectableRowsRollingSelection",!0),this.registerTableOption("selectableRowsPersistence",!0),this.registerTableOption("selectableRowsCheck",function(t,s){return!0}),this.registerTableFunction("selectRow",this.selectRows.bind(this)),this.registerTableFunction("deselectRow",this.deselectRows.bind(this)),this.registerTableFunction("toggleSelectRow",this.toggleRow.bind(this)),this.registerTableFunction("getSelectedRows",this.getSelectedRows.bind(this)),this.registerTableFunction("getSelectedData",this.getSelectedData.bind(this)),this.registerComponentFunction("row","select",this.selectRows.bind(this)),this.registerComponentFunction("row","deselect",this.deselectRows.bind(this)),this.registerComponentFunction("row","toggleSelect",this.toggleRow.bind(this)),this.registerComponentFunction("row","isSelected",this.isRowSelected.bind(this))}initialize(){this.deprecatedOptionsCheck(),this.table.options.selectableRows==="highlight"&&this.table.options.selectableRange&&(this.table.options.selectableRows=!1),this.table.options.selectableRows!==!1&&(this.subscribe("row-init",this.initializeRow.bind(this)),this.subscribe("row-deleting",this.rowDeleted.bind(this)),this.subscribe("rows-wipe",this.clearSelectionData.bind(this)),this.subscribe("rows-retrieve",this.rowRetrieve.bind(this)),this.table.options.selectableRows&&!this.table.options.selectableRowsPersistence&&this.subscribe("data-refreshing",this.deselectRows.bind(this)))}deprecatedOptionsCheck(){}rowRetrieve(e,t){return e==="selected"?this.selectedRows:t}rowDeleted(e){this._deselectRow(e,!0)}clearSelectionData(e){var t=this.selectedRows.length;this.selecting=!1,this.lastClickedRow=!1,this.selectPrev=[],this.selectedRows=[],t&&e!==!0&&this._rowSelectionChanged()}initializeRow(e){var t=this,s=t.checkRowSelectability(e),a=e.getElement(),i=function(){setTimeout(function(){t.selecting=!1},50),document.body.removeEventListener("mouseup",i)};e.modules.select={selected:!1},a.classList.toggle("tabulator-selectable",s),a.classList.toggle("tabulator-unselectable",!s),t.checkRowSelectability(e)&&t.table.options.selectableRows&&t.table.options.selectableRows!="highlight"&&(t.table.options.selectableRowsRangeMode==="click"?a.addEventListener("click",this.handleComplexRowClick.bind(this,e)):(a.addEventListener("click",function(n){(!t.table.modExists("edit")||!t.table.modules.edit.getCurrentCell())&&t.table._clearSelection(),t.selecting||t.toggleRow(e)}),a.addEventListener("mousedown",function(n){if(n.shiftKey)return t.table._clearSelection(),t.selecting=!0,t.selectPrev=[],document.body.addEventListener("mouseup",i),document.body.addEventListener("keyup",i),t.toggleRow(e),!1}),a.addEventListener("mouseenter",function(n){t.selecting&&(t.table._clearSelection(),t.toggleRow(e),t.selectPrev[1]==e&&t.toggleRow(t.selectPrev[0]))}),a.addEventListener("mouseout",function(n){t.selecting&&(t.table._clearSelection(),t.selectPrev.unshift(e))})))}handleComplexRowClick(e,t){if(t.shiftKey){this.table._clearSelection(),this.lastClickedRow=this.lastClickedRow||e;var s=this.table.rowManager.getDisplayRowIndex(this.lastClickedRow),a=this.table.rowManager.getDisplayRowIndex(e),i=s<=a?s:a,n=s>=a?s:a,r=this.table.rowManager.getDisplayRows().slice(0),o=r.splice(i,n-i+1);t.ctrlKey||t.metaKey?(o.forEach(l=>{l!==this.lastClickedRow&&(this.table.options.selectableRows!==!0&&!this.isRowSelected(e)?this.selectedRows.length<this.table.options.selectableRows&&this.toggleRow(l):this.toggleRow(l))}),this.lastClickedRow=e):(this.deselectRows(void 0,!0),this.table.options.selectableRows!==!0&&o.length>this.table.options.selectableRows&&(o=o.slice(0,this.table.options.selectableRows)),this.selectRows(o)),this.table._clearSelection()}else t.ctrlKey||t.metaKey?(this.toggleRow(e),this.lastClickedRow=e):(this.deselectRows(void 0,!0),this.selectRows(e),this.lastClickedRow=e)}checkRowSelectability(e){return e&&e.type==="row"?this.table.options.selectableRowsCheck.call(this.table,e.getComponent()):!1}toggleRow(e){this.checkRowSelectability(e)&&(e.modules.select&&e.modules.select.selected?this._deselectRow(e):this._selectRow(e))}selectRows(e){var t=[],s,a;switch(typeof e){case"undefined":s=this.table.rowManager.rows;break;case"number":s=this.table.rowManager.findRow(e);break;case"string":s=this.table.rowManager.findRow(e),s||(s=this.table.rowManager.getRows(e));break;default:s=e;break}Array.isArray(s)?s.length&&(s.forEach(i=>{a=this._selectRow(i,!0,!0),a&&t.push(a)}),this._rowSelectionChanged(!1,t)):s&&this._selectRow(s,!1,!0)}_selectRow(e,t,s){if(!isNaN(this.table.options.selectableRows)&&this.table.options.selectableRows!==!0&&!s&&this.selectedRows.length>=this.table.options.selectableRows)if(this.table.options.selectableRowsRollingSelection)this._deselectRow(this.selectedRows[0]);else return!1;var a=this.table.rowManager.findRow(e);if(a){if(this.selectedRows.indexOf(a)==-1)return a.getElement().classList.add("tabulator-selected"),a.modules.select||(a.modules.select={}),a.modules.select.selected=!0,a.modules.select.checkboxEl&&(a.modules.select.checkboxEl.checked=!0),this.selectedRows.push(a),this.table.options.dataTreeSelectPropagate&&this.childRowSelection(a,!0),this.dispatchExternal("rowSelected",a.getComponent()),this._rowSelectionChanged(t,a),a}else t||console.warn("Selection Error - No such row found, ignoring selection:"+e)}isRowSelected(e){return this.selectedRows.indexOf(e)!==-1}deselectRows(e,t){var s=[],a,i;switch(typeof e){case"undefined":a=Object.assign([],this.selectedRows);break;case"number":a=this.table.rowManager.findRow(e);break;case"string":a=this.table.rowManager.findRow(e),a||(a=this.table.rowManager.getRows(e));break;default:a=e;break}Array.isArray(a)?a.length&&(a.forEach(n=>{i=this._deselectRow(n,!0,!0),i&&s.push(i)}),this._rowSelectionChanged(t,[],s)):a&&this._deselectRow(a,t,!0)}_deselectRow(e,t){var s=this,a=s.table.rowManager.findRow(e),i,n;if(a){if(i=s.selectedRows.findIndex(function(r){return r==a}),i>-1)return n=a.getElement(),n&&n.classList.remove("tabulator-selected"),a.modules.select||(a.modules.select={}),a.modules.select.selected=!1,a.modules.select.checkboxEl&&(a.modules.select.checkboxEl.checked=!1),s.selectedRows.splice(i,1),this.table.options.dataTreeSelectPropagate&&this.childRowSelection(a,!1),this.dispatchExternal("rowDeselected",a.getComponent()),s._rowSelectionChanged(t,void 0,a),a}else t||console.warn("Deselection Error - No such row found, ignoring selection:"+e)}getSelectedData(){var e=[];return this.selectedRows.forEach(function(t){e.push(t.getData())}),e}getSelectedRows(){var e=[];return this.selectedRows.forEach(function(t){e.push(t.getComponent())}),e}_rowSelectionChanged(e,t=[],s=[]){this.headerCheckboxElement&&(this.selectedRows.length===0?(this.headerCheckboxElement.checked=!1,this.headerCheckboxElement.indeterminate=!1):this.table.rowManager.rows.length===this.selectedRows.length?(this.headerCheckboxElement.checked=!0,this.headerCheckboxElement.indeterminate=!1):(this.headerCheckboxElement.indeterminate=!0,this.headerCheckboxElement.checked=!1)),e||(Array.isArray(t)||(t=[t]),t=t.map(a=>a.getComponent()),Array.isArray(s)||(s=[s]),s=s.map(a=>a.getComponent()),this.dispatchExternal("rowSelectionChanged",this.getSelectedData(),this.getSelectedRows(),t,s))}registerRowSelectCheckbox(e,t){e._row.modules.select||(e._row.modules.select={}),e._row.modules.select.checkboxEl=t}registerHeaderSelectCheckbox(e){this.headerCheckboxElement=e}childRowSelection(e,t){var s=this.table.modules.dataTree.getChildren(e,!0,!0);if(t)for(let a of s)this._selectRow(a,!0);else for(let a of s)this._deselectRow(a,!0)}}g(Ze,"moduleName","selectRow"),g(Ze,"moduleExtensions",Bi);function zi(p,e,t,s,a,i,n){var r=n.alignEmptyValues,o=n.decimalSeparator,l=n.thousandSeparator,c=0;if(p=String(p),e=String(e),l&&(p=p.split(l).join(""),e=e.split(l).join("")),o&&(p=p.split(o).join("."),e=e.split(o).join(".")),p=parseFloat(p),e=parseFloat(e),isNaN(p))c=isNaN(e)?0:-1;else if(isNaN(e))c=1;else return p-e;return(r==="top"&&i==="desc"||r==="bottom"&&i==="asc")&&(c*=-1),c}function ji(p,e,t,s,a,i,n){var r=n.alignEmptyValues,o=0,l;if(!p)o=e?-1:0;else if(!e)o=1;else{switch(typeof n.locale){case"boolean":n.locale&&(l=this.langLocale());break;case"string":l=n.locale;break}return String(p).toLowerCase().localeCompare(String(e).toLowerCase(),l)}return(r==="top"&&i==="desc"||r==="bottom"&&i==="asc")&&(o*=-1),o}function Xe(p,e,t,s,a,i,n){var r=this.table.dependencyRegistry.lookup(["luxon","DateTime"],"DateTime"),o=n.format||"dd/MM/yyyy HH:mm:ss",l=n.alignEmptyValues,c=0;if(typeof r<"u"){if(r.isDateTime(p)||(o==="iso"?p=r.fromISO(String(p)):p=r.fromFormat(String(p),o)),r.isDateTime(e)||(o==="iso"?e=r.fromISO(String(e)):e=r.fromFormat(String(e),o)),!p.isValid)c=e.isValid?-1:0;else if(!e.isValid)c=1;else return p-e;return(l==="top"&&i==="desc"||l==="bottom"&&i==="asc")&&(c*=-1),c}else console.error("Sort Error - 'datetime' sorter is dependant on luxon.js")}function Ai(p,e,t,s,a,i,n){return n.format||(n.format="dd/MM/yyyy"),Xe.call(this,p,e,t,s,a,i,n)}function Fi(p,e,t,s,a,i,n){return n.format||(n.format="HH:mm"),Xe.call(this,p,e,t,s,a,i,n)}function Ii(p,e,t,s,a,i,n){var r=p===!0||p==="true"||p==="True"||p===1?1:0,o=e===!0||e==="true"||e==="True"||e===1?1:0;return r-o}function Di(p,e,t,s,a,i,n){var r=n.type||"length",o=n.alignEmptyValues,l=0,c=this.table,d;n.valueMap&&(typeof n.valueMap=="string"?d=function(u){return u.map(f=>B.retrieveNestedData(c.options.nestedFieldSeparator,n.valueMap,f))}:d=n.valueMap);function h(u){var f;switch(d&&(u=d(u)),r){case"length":f=u.length;break;case"sum":f=u.reduce(function(m,b){return m+b});break;case"max":f=Math.max.apply(null,u);break;case"min":f=Math.min.apply(null,u);break;case"avg":f=u.reduce(function(m,b){return m+b})/u.length;break;case"string":f=u.join("");break}return f}if(!Array.isArray(p))l=Array.isArray(e)?-1:0;else if(!Array.isArray(e))l=1;else return r==="string"?String(h(p)).toLowerCase().localeCompare(String(h(e)).toLowerCase()):h(e)-h(p);return(o==="top"&&i==="desc"||o==="bottom"&&i==="asc")&&(l*=-1),l}function Pi(p,e,t,s,a,i,n){var r=typeof p>"u"?0:1,o=typeof e>"u"?0:1;return r-o}function Oi(p,e,t,s,a,i,n){var r,o,l,c,d=0,h,u=/(\d+)|(\D+)/g,f=/\d/,m=n.alignEmptyValues,b=0;if(!p&&p!==0)b=!e&&e!==0?0:-1;else if(!e&&e!==0)b=1;else{if(isFinite(p)&&isFinite(e))return p-e;if(r=String(p).toLowerCase(),o=String(e).toLowerCase(),r===o)return 0;if(!(f.test(r)&&f.test(o)))return r>o?1:-1;for(r=r.match(u),o=o.match(u),h=r.length>o.length?o.length:r.length;d<h;)if(l=r[d],c=o[d++],l!==c)return isFinite(l)&&isFinite(c)?(l.charAt(0)==="0"&&(l="."+l),c.charAt(0)==="0"&&(c="."+c),l-c):l>c?1:-1;return r.length>o.length}return(m==="top"&&i==="desc"||m==="bottom"&&i==="asc")&&(b*=-1),b}var Ni={number:zi,string:ji,date:Ai,time:Fi,datetime:Xe,boolean:Ii,array:Di,exists:Pi,alphanum:Oi};const X=class X extends I{constructor(e){super(e),this.sortList=[],this.changed=!1,this.registerTableOption("sortMode","local"),this.registerTableOption("initialSort",!1),this.registerTableOption("columnHeaderSortMulti",!0),this.registerTableOption("sortOrderReverse",!1),this.registerTableOption("headerSortElement","<div class='tabulator-arrow'></div>"),this.registerTableOption("headerSortClickElement","header"),this.registerColumnOption("sorter"),this.registerColumnOption("sorterParams"),this.registerColumnOption("headerSort",!0),this.registerColumnOption("headerSortStartingDir"),this.registerColumnOption("headerSortTristate")}initialize(){this.subscribe("column-layout",this.initializeColumn.bind(this)),this.subscribe("table-built",this.tableBuilt.bind(this)),this.registerDataHandler(this.sort.bind(this),20),this.registerTableFunction("setSort",this.userSetSort.bind(this)),this.registerTableFunction("getSorters",this.getSort.bind(this)),this.registerTableFunction("clearSort",this.clearSort.bind(this)),this.table.options.sortMode==="remote"&&this.subscribe("data-params",this.remoteSortParams.bind(this))}tableBuilt(){this.table.options.initialSort&&this.setSort(this.table.options.initialSort)}remoteSortParams(e,t,s,a){var i=this.getSort();return i.forEach(n=>{delete n.column}),a.sort=i,a}userSetSort(e,t){this.setSort(e,t),this.refreshSort()}clearSort(){this.clear(),this.refreshSort()}initializeColumn(e){var t=!1,s,a;switch(typeof e.definition.sorter){case"string":X.sorters[e.definition.sorter]?t=X.sorters[e.definition.sorter]:console.warn("Sort Error - No such sorter found: ",e.definition.sorter);break;case"function":t=e.definition.sorter;break}if(e.modules.sort={sorter:t,dir:"none",params:e.definition.sorterParams||{},startingDir:e.definition.headerSortStartingDir||"asc",tristate:e.definition.headerSortTristate},e.definition.headerSort!==!1){switch(s=e.getElement(),s.classList.add("tabulator-sortable"),a=document.createElement("div"),a.classList.add("tabulator-col-sorter"),this.table.options.headerSortClickElement){case"icon":a.classList.add("tabulator-col-sorter-element");break;case"header":s.classList.add("tabulator-col-sorter-element");break;default:s.classList.add("tabulator-col-sorter-element");break}switch(this.table.options.headerSortElement){case"function":break;case"object":a.appendChild(this.table.options.headerSortElement);break;default:a.innerHTML=this.table.options.headerSortElement}e.titleHolderElement.appendChild(a),e.modules.sort.element=a,this.setColumnHeaderSortIcon(e,"none"),this.table.options.headerSortClickElement==="icon"&&a.addEventListener("mousedown",i=>{i.stopPropagation()}),(this.table.options.headerSortClickElement==="icon"?a:s).addEventListener("click",i=>{var n="",r=[],o=!1;if(e.modules.sort){if(e.modules.sort.tristate)e.modules.sort.dir=="none"?n=e.modules.sort.startingDir:e.modules.sort.dir==e.modules.sort.startingDir?n=e.modules.sort.dir=="asc"?"desc":"asc":n="none";else switch(e.modules.sort.dir){case"asc":n="desc";break;case"desc":n="asc";break;default:n=e.modules.sort.startingDir}this.table.options.columnHeaderSortMulti&&(i.shiftKey||i.ctrlKey)?(r=this.getSort(),o=r.findIndex(l=>l.field===e.getField()),o>-1?(r[o].dir=n,o=r.splice(o,1)[0],n!="none"&&r.push(o)):n!="none"&&r.push({column:e,dir:n}),this.setSort(r)):n=="none"?this.clear():this.setSort(e,n),this.refreshSort()}})}}refreshSort(){this.table.options.sortMode==="remote"?this.reloadData(null,!1,!1):this.refreshData(!0)}hasChanged(){var e=this.changed;return this.changed=!1,e}getSort(){var e=this,t=[];return e.sortList.forEach(function(s){s.column&&t.push({column:s.column.getComponent(),field:s.column.getField(),dir:s.dir})}),t}setSort(e,t){var s=this,a=[];Array.isArray(e)||(e=[{column:e,dir:t}]),e.forEach(function(i){var n;n=s.table.columnManager.findColumn(i.column),n?(i.column=n,a.push(i),s.changed=!0):console.warn("Sort Warning - Sort field does not exist and is being ignored: ",i.column)}),s.sortList=a,this.dispatch("sort-changed")}clear(){this.setSort([])}findSorter(e){var t=this.table.rowManager.activeRows[0],s="string",a,i;if(t&&(t=t.getData(),a=e.getField(),a))switch(i=e.getFieldValue(t),typeof i){case"undefined":s="string";break;case"boolean":s="boolean";break;default:!isNaN(i)&&i!==""?s="number":i.match(/((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+$/i)&&(s="alphanum");break}return X.sorters[s]}sort(e,t){var s=this,a=this.table.options.sortOrderReverse?s.sortList.slice().reverse():s.sortList,i=[],n=[];return this.subscribedExternal("dataSorting")&&this.dispatchExternal("dataSorting",s.getSort()),t||s.clearColumnHeaders(),this.table.options.sortMode!=="remote"?(a.forEach(function(r,o){var l;r.column&&(l=r.column.modules.sort,l&&(l.sorter||(l.sorter=s.findSorter(r.column)),r.params=typeof l.params=="function"?l.params(r.column.getComponent(),r.dir):l.params,i.push(r)),t||s.setColumnHeader(r.column,r.dir))}),i.length&&s._sortItems(e,i)):t||a.forEach(function(r,o){s.setColumnHeader(r.column,r.dir)}),this.subscribedExternal("dataSorted")&&(e.forEach(r=>{n.push(r.getComponent())}),this.dispatchExternal("dataSorted",s.getSort(),n)),e}clearColumnHeaders(){this.table.columnManager.getRealColumns().forEach(e=>{e.modules.sort&&(e.modules.sort.dir="none",e.getElement().setAttribute("aria-sort","none"),this.setColumnHeaderSortIcon(e,"none"))})}setColumnHeader(e,t){e.modules.sort.dir=t,e.getElement().setAttribute("aria-sort",t==="asc"?"ascending":"descending"),this.setColumnHeaderSortIcon(e,t)}setColumnHeaderSortIcon(e,t){var s=e.modules.sort.element,a;if(e.definition.headerSort&&typeof this.table.options.headerSortElement=="function"){for(;s.firstChild;)s.removeChild(s.firstChild);a=this.table.options.headerSortElement.call(this.table,e.getComponent(),t),typeof a=="object"?s.appendChild(a):s.innerHTML=a}}_sortItems(e,t){var s=t.length-1;e.sort((a,i)=>{for(var n,r=s;r>=0;r--){let o=t[r];if(n=this._sortRow(a,i,o.column,o.dir,o.params),n!==0)break}return n})}_sortRow(e,t,s,a,i){var n,r,o=a=="asc"?e:t,l=a=="asc"?t:e;return e=s.getFieldValue(o.getData()),t=s.getFieldValue(l.getData()),e=typeof e<"u"?e:"",t=typeof t<"u"?t:"",n=o.getComponent(),r=l.getComponent(),s.modules.sort.sorter.call(this,e,t,n,r,s.getComponent(),a,i)}};g(X,"moduleName","sort"),g(X,"sorters",Ni);let Re=X;var Vi={debugEventsExternal:!1,debugEventsInternal:!1,debugInvalidOptions:!0,debugInvalidComponentFuncs:!0,debugInitialization:!0,debugDeprecation:!0,height:!1,minHeight:!1,maxHeight:!1,columnHeaderVertAlign:"top",popupContainer:!1,columns:[],columnDefaults:{},rowHeader:!1,data:!1,autoColumns:!1,autoColumnsDefinitions:!1,nestedFieldSeparator:".",footerElement:!1,index:"id",textDirection:"auto",addRowPos:"bottom",headerVisible:!0,renderVertical:"virtual",renderHorizontal:"basic",renderVerticalBuffer:0,scrollToRowPosition:"top",scrollToRowIfVisible:!0,scrollToColumnPosition:"left",scrollToColumnIfVisible:!0,rowFormatter:!1,rowFormatterPrint:null,rowFormatterClipboard:null,rowFormatterHtmlOutput:null,rowHeight:null,placeholder:!1,dataLoader:!0,dataLoaderLoading:!1,dataLoaderError:!1,dataLoaderErrorTimeout:3e3,dataSendParams:{},dataReceiveParams:{},dependencies:{}};class Gt{constructor(e,t,s={}){this.table=e,this.msgType=t,this.registeredDefaults=Object.assign({},s)}register(e,t){this.registeredDefaults[e]=t}generate(e,t={}){var s=Object.assign({},this.registeredDefaults),a=this.table.options.debugInvalidOptions||t.debugInvalidOptions===!0;Object.assign(s,e);for(let i in t)s.hasOwnProperty(i)||(a&&console.warn("Invalid "+this.msgType+" option:",i),s[i]=t.key);for(let i in s)i in t?s[i]=t[i]:Array.isArray(s[i])?s[i]=Object.assign([],s[i]):typeof s[i]=="object"&&s[i]!==null?s[i]=Object.assign({},s[i]):typeof s[i]>"u"&&delete s[i];return s}}class qe extends j{constructor(e){super(e),this.elementVertical=e.rowManager.element,this.elementHorizontal=e.columnManager.element,this.tableElement=e.rowManager.tableElement,this.verticalFillMode="fit"}initialize(){}clearRows(){}clearColumns(){}reinitializeColumnWidths(e){}renderRows(){}renderColumns(){}rerenderRows(e){e&&e()}rerenderColumns(e,t){}renderRowCells(e){}rerenderRowCells(e,t){}scrollColumns(e,t){}scrollRows(e,t){}resize(){}scrollToRow(e){}scrollToRowNearestTop(e){}visibleRows(e){return[]}rows(){return this.table.rowManager.getDisplayRows()}styleRow(e,t){var s=e.getElement();t%2?(s.classList.add("tabulator-row-even"),s.classList.remove("tabulator-row-odd")):(s.classList.add("tabulator-row-odd"),s.classList.remove("tabulator-row-even"))}clear(){this.clearRows(),this.clearColumns()}render(){this.renderRows(),this.renderColumns()}rerender(e){this.rerenderRows(),this.rerenderColumns()}scrollToRowPosition(e,t,s){var a=this.rows().indexOf(e),i=e.getElement(),n=0;return new Promise((r,o)=>{if(a>-1){if(typeof s>"u"&&(s=this.table.options.scrollToRowIfVisible),!s&&B.elVisible(i)&&(n=B.elOffset(i).top-B.elOffset(this.elementVertical).top,n>0&&n<this.elementVertical.clientHeight-i.offsetHeight))return r(),!1;switch(typeof t>"u"&&(t=this.table.options.scrollToRowPosition),t==="nearest"&&(t=this.scrollToRowNearestTop(e)?"top":"bottom"),this.scrollToRow(e),t){case"middle":case"center":this.elementVertical.scrollHeight-this.elementVertical.scrollTop==this.elementVertical.clientHeight?this.elementVertical.scrollTop=this.elementVertical.scrollTop+(i.offsetTop-this.elementVertical.scrollTop)-(this.elementVertical.scrollHeight-i.offsetTop)/2:this.elementVertical.scrollTop=this.elementVertical.scrollTop-this.elementVertical.clientHeight/2;break;case"bottom":this.elementVertical.scrollHeight-this.elementVertical.scrollTop==this.elementVertical.clientHeight?this.elementVertical.scrollTop=this.elementVertical.scrollTop-(this.elementVertical.scrollHeight-i.offsetTop)+i.offsetHeight:this.elementVertical.scrollTop=this.elementVertical.scrollTop-this.elementVertical.clientHeight+i.offsetHeight;break;case"top":this.elementVertical.scrollTop=i.offsetTop;break}r()}else console.warn("Scroll Error - Row not visible"),o("Scroll Error - Row not visible")})}}class Wi extends qe{constructor(e){super(e)}renderRowCells(e,t){const s=document.createDocumentFragment();e.cells.forEach(a=>{s.appendChild(a.getElement())}),e.element.appendChild(s),t||e.cells.forEach(a=>{a.cellRendered()})}reinitializeColumnWidths(e){e.forEach(function(t){t.reinitializeWidth()})}}class Ui extends qe{constructor(e){super(e),this.leftCol=0,this.rightCol=0,this.scrollLeft=0,this.vDomScrollPosLeft=0,this.vDomScrollPosRight=0,this.vDomPadLeft=0,this.vDomPadRight=0,this.fitDataColAvg=0,this.windowBuffer=200,this.visibleRows=null,this.initialized=!1,this.isFitData=!1,this.columns=[]}initialize(){this.compatibilityCheck(),this.layoutCheck(),this.vertScrollListen()}compatibilityCheck(){this.options("layout")=="fitDataTable"&&console.warn("Horizontal Virtual DOM is not compatible with fitDataTable layout mode"),this.options("responsiveLayout")&&console.warn("Horizontal Virtual DOM is not compatible with responsive columns"),this.options("rtl")&&console.warn("Horizontal Virtual DOM is not currently compatible with RTL text direction")}layoutCheck(){this.isFitData=this.options("layout").startsWith("fitData")}vertScrollListen(){this.subscribe("scroll-vertical",this.clearVisRowCache.bind(this)),this.subscribe("data-refreshed",this.clearVisRowCache.bind(this))}clearVisRowCache(){this.visibleRows=null}renderColumns(e,t){this.dataChange()}scrollColumns(e,t){this.scrollLeft!=e&&(this.scrollLeft=e,this.scroll(e-(this.vDomScrollPosLeft+this.windowBuffer)))}calcWindowBuffer(){var e=this.elementVertical.clientWidth;this.table.columnManager.columnsByIndex.forEach(t=>{if(t.visible){var s=t.getWidth();s>e&&(e=s)}}),this.windowBuffer=e*2}rerenderColumns(e,t){var s={cols:this.columns,leftCol:this.leftCol,rightCol:this.rightCol},a=0;e&&!this.initialized||(this.clear(),this.calcWindowBuffer(),this.scrollLeft=this.elementVertical.scrollLeft,this.vDomScrollPosLeft=this.scrollLeft-this.windowBuffer,this.vDomScrollPosRight=this.scrollLeft+this.elementVertical.clientWidth+this.windowBuffer,this.table.columnManager.columnsByIndex.forEach(i=>{var n={},r;i.visible&&(i.modules.frozen||(r=i.getWidth(),n.leftPos=a,n.rightPos=a+r,n.width=r,this.isFitData&&(n.fitDataCheck=i.modules.vdomHoz?i.modules.vdomHoz.fitDataCheck:!0),a+r>this.vDomScrollPosLeft&&a<this.vDomScrollPosRight?(this.leftCol==-1&&(this.leftCol=this.columns.length,this.vDomPadLeft=a),this.rightCol=this.columns.length):this.leftCol!==-1&&(this.vDomPadRight+=r),this.columns.push(i),i.modules.vdomHoz=n,a+=r))}),this.tableElement.style.paddingLeft=this.vDomPadLeft+"px",this.tableElement.style.paddingRight=this.vDomPadRight+"px",this.initialized=!0,t||(!e||this.reinitChanged(s))&&this.reinitializeRows(),this.elementVertical.scrollLeft=this.scrollLeft)}renderRowCells(e){if(this.initialized)this.initializeRow(e);else{const t=document.createDocumentFragment();e.cells.forEach(s=>{t.appendChild(s.getElement())}),e.element.appendChild(t),e.cells.forEach(s=>{s.cellRendered()})}}rerenderRowCells(e,t){this.reinitializeRow(e,t)}reinitializeColumnWidths(e){for(let t=this.leftCol;t<=this.rightCol;t++){let s=this.columns[t];s&&s.reinitializeWidth()}}deinitialize(){this.initialized=!1}clear(){this.columns=[],this.leftCol=-1,this.rightCol=0,this.vDomScrollPosLeft=0,this.vDomScrollPosRight=0,this.vDomPadLeft=0,this.vDomPadRight=0}dataChange(){var e=!1,t,s;if(this.isFitData){if(this.table.columnManager.columnsByIndex.forEach(a=>{!a.definition.width&&a.visible&&(e=!0)}),e&&this.table.rowManager.getDisplayRows().length&&(this.vDomScrollPosRight=this.scrollLeft+this.elementVertical.clientWidth+this.windowBuffer,t=this.chain("rows-sample",[1],[],()=>this.table.rowManager.getDisplayRows())[0],t)){s=t.getElement(),t.generateCells(),this.tableElement.appendChild(s);for(let a=0;a<t.cells.length;a++){let i=t.cells[a];s.appendChild(i.getElement()),i.column.reinitializeWidth()}s.parentNode.removeChild(s),this.rerenderColumns(!1,!0)}}else this.options("layout")==="fitColumns"&&(this.layoutRefresh(),this.rerenderColumns(!1,!0))}reinitChanged(e){var t=!0;return e.cols.length!==this.columns.length||e.leftCol!==this.leftCol||e.rightCol!==this.rightCol?!0:(e.cols.forEach((s,a)=>{s!==this.columns[a]&&(t=!1)}),!t)}reinitializeRows(){var e=this.getVisibleRows(),t=this.table.rowManager.getRows().filter(s=>!e.includes(s));e.forEach(s=>{this.reinitializeRow(s,!0)}),t.forEach(s=>{s.deinitialize()})}getVisibleRows(){return this.visibleRows||(this.visibleRows=this.table.rowManager.getVisibleRows()),this.visibleRows}scroll(e){this.vDomScrollPosLeft+=e,this.vDomScrollPosRight+=e,Math.abs(e)>this.windowBuffer/2?this.rerenderColumns():e>0?(this.addColRight(),this.removeColLeft()):(this.addColLeft(),this.removeColRight())}colPositionAdjust(e,t,s){for(let a=e;a<t;a++){let i=this.columns[a];i.modules.vdomHoz.leftPos+=s,i.modules.vdomHoz.rightPos+=s}}addColRight(){for(var e=!1,t=!0;t;){let s=this.columns[this.rightCol+1];s&&s.modules.vdomHoz.leftPos<=this.vDomScrollPosRight?(e=!0,this.getVisibleRows().forEach(a=>{if(a.type!=="group"){var i=a.getCell(s);a.getElement().insertBefore(i.getElement(),a.getCell(this.columns[this.rightCol]).getElement().nextSibling),i.cellRendered()}}),this.fitDataColActualWidthCheck(s),this.rightCol++,this.getVisibleRows().forEach(a=>{a.type!=="group"&&(a.modules.vdomHoz.rightCol=this.rightCol)}),this.rightCol>=this.columns.length-1?this.vDomPadRight=0:this.vDomPadRight-=s.getWidth()):t=!1}e&&(this.tableElement.style.paddingRight=this.vDomPadRight+"px")}addColLeft(){for(var e=!1,t=!0;t;){let s=this.columns[this.leftCol-1];if(s)if(s.modules.vdomHoz.rightPos>=this.vDomScrollPosLeft){e=!0,this.getVisibleRows().forEach(i=>{if(i.type!=="group"){var n=i.getCell(s);i.getElement().insertBefore(n.getElement(),i.getCell(this.columns[this.leftCol]).getElement()),n.cellRendered()}}),this.leftCol--,this.getVisibleRows().forEach(i=>{i.type!=="group"&&(i.modules.vdomHoz.leftCol=this.leftCol)}),this.leftCol<=0?this.vDomPadLeft=0:this.vDomPadLeft-=s.getWidth();let a=this.fitDataColActualWidthCheck(s);a&&(this.scrollLeft=this.elementVertical.scrollLeft=this.elementVertical.scrollLeft+a,this.vDomPadRight-=a)}else t=!1;else t=!1}e&&(this.tableElement.style.paddingLeft=this.vDomPadLeft+"px")}removeColRight(){for(var e=!1,t=!0;t;){let s=this.columns[this.rightCol];s&&s.modules.vdomHoz.leftPos>this.vDomScrollPosRight?(e=!0,this.getVisibleRows().forEach(a=>{if(a.type!=="group"){var i=a.getCell(s);try{a.getElement().removeChild(i.getElement())}catch(n){console.warn("Could not removeColRight",n.message)}}}),this.vDomPadRight+=s.getWidth(),this.rightCol--,this.getVisibleRows().forEach(a=>{a.type!=="group"&&(a.modules.vdomHoz.rightCol=this.rightCol)})):t=!1}e&&(this.tableElement.style.paddingRight=this.vDomPadRight+"px")}removeColLeft(){for(var e=!1,t=!0;t;){let s=this.columns[this.leftCol];s&&s.modules.vdomHoz.rightPos<this.vDomScrollPosLeft?(e=!0,this.getVisibleRows().forEach(a=>{if(a.type!=="group"){var i=a.getCell(s);try{a.getElement().removeChild(i.getElement())}catch(n){console.warn("Could not removeColLeft",n.message)}}}),this.vDomPadLeft+=s.getWidth(),this.leftCol++,this.getVisibleRows().forEach(a=>{a.type!=="group"&&(a.modules.vdomHoz.leftCol=this.leftCol)})):t=!1}e&&(this.tableElement.style.paddingLeft=this.vDomPadLeft+"px")}fitDataColActualWidthCheck(e){var t,s;return e.modules.vdomHoz.fitDataCheck&&(e.reinitializeWidth(),t=e.getWidth(),s=t-e.modules.vdomHoz.width,s&&(e.modules.vdomHoz.rightPos+=s,e.modules.vdomHoz.width=t,this.colPositionAdjust(this.columns.indexOf(e)+1,this.columns.length,s)),e.modules.vdomHoz.fitDataCheck=!1),s}initializeRow(e){if(e.type!=="group"){e.modules.vdomHoz={leftCol:this.leftCol,rightCol:this.rightCol},this.table.modules.frozenColumns&&this.table.modules.frozenColumns.leftColumns.forEach(t=>{this.appendCell(e,t)});for(let t=this.leftCol;t<=this.rightCol;t++)this.appendCell(e,this.columns[t]);this.table.modules.frozenColumns&&this.table.modules.frozenColumns.rightColumns.forEach(t=>{this.appendCell(e,t)})}}appendCell(e,t){if(t&&t.visible){let s=e.getCell(t);e.getElement().appendChild(s.getElement()),s.cellRendered()}}reinitializeRow(e,t){if(e.type!=="group"&&(t||!e.modules.vdomHoz||e.modules.vdomHoz.leftCol!==this.leftCol||e.modules.vdomHoz.rightCol!==this.rightCol)){for(var s=e.getElement();s.firstChild;)s.removeChild(s.firstChild);this.initializeRow(e)}}}class Gi extends j{constructor(e){super(e),this.blockHozScrollEvent=!1,this.headersElement=null,this.contentsElement=null,this.rowHeader=null,this.element=null,this.columns=[],this.columnsByIndex=[],this.columnsByField={},this.scrollLeft=0,this.optionsList=new Gt(this.table,"column definition",Ut),this.redrawBlock=!1,this.redrawBlockUpdate=null,this.renderer=null}initialize(){this.initializeRenderer(),this.headersElement=this.createHeadersElement(),this.contentsElement=this.createHeaderContentsElement(),this.element=this.createHeaderElement(),this.contentsElement.insertBefore(this.headersElement,this.contentsElement.firstChild),this.element.insertBefore(this.contentsElement,this.element.firstChild),this.initializeScrollWheelWatcher(),this.subscribe("scroll-horizontal",this.scrollHorizontal.bind(this)),this.subscribe("scrollbar-vertical",this.padVerticalScrollbar.bind(this))}padVerticalScrollbar(e){this.table.rtl?this.headersElement.style.marginLeft=e+"px":this.headersElement.style.marginRight=e+"px"}initializeRenderer(){var e,t={virtual:Ui,basic:Wi};typeof this.table.options.renderHorizontal=="string"?e=t[this.table.options.renderHorizontal]:e=this.table.options.renderHorizontal,e?(this.renderer=new e(this.table,this.element,this.tableElement),this.renderer.initialize()):console.error("Unable to find matching renderer:",this.table.options.renderHorizontal)}createHeadersElement(){var e=document.createElement("div");return e.classList.add("tabulator-headers"),e.setAttribute("role","row"),e}createHeaderContentsElement(){var e=document.createElement("div");return e.classList.add("tabulator-header-contents"),e}createHeaderElement(){var e=document.createElement("div");return e.classList.add("tabulator-header"),e.setAttribute("role","rowgroup"),this.table.options.headerVisible||e.classList.add("tabulator-header-hidden"),e}getElement(){return this.element}getContentsElement(){return this.contentsElement}getHeadersElement(){return this.headersElement}scrollHorizontal(e){this.contentsElement.scrollLeft=e,this.scrollLeft=e,this.renderer.scrollColumns(e)}initializeScrollWheelWatcher(){this.contentsElement.addEventListener("wheel",e=>{var t;e.deltaX&&(t=this.contentsElement.scrollLeft+e.deltaX,this.table.rowManager.scrollHorizontal(t),this.table.columnManager.scrollHorizontal(t))})}generateColumnsFromRowData(e){var t=[],s={},a=this.table.options.autoColumns==="full"?e:[e[0]],i=this.table.options.autoColumnsDefinitions;if(e&&e.length){if(a.forEach(n=>{Object.keys(n).forEach((r,o)=>{let l=n[r],c;s[r]?s[r]!==!0&&typeof l<"u"&&(s[r].sorter=this.calculateSorterFromValue(l),s[r]=!0):(c={field:r,title:r,sorter:this.calculateSorterFromValue(l)},t.splice(o,0,c),s[r]=typeof l>"u"?c:!0)})}),i)switch(typeof i){case"function":this.table.options.columns=i.call(this.table,t);break;case"object":Array.isArray(i)?t.forEach(n=>{var r=i.find(o=>o.field===n.field);r&&Object.assign(n,r)}):t.forEach(n=>{i[n.field]&&Object.assign(n,i[n.field])}),this.table.options.columns=t;break}else this.table.options.columns=t;this.setColumns(this.table.options.columns)}}calculateSorterFromValue(e){var t;switch(typeof e){case"undefined":t="string";break;case"boolean":t="boolean";break;case"number":t="number";break;case"object":Array.isArray(e)?t="array":t="string";break;default:!isNaN(e)&&e!==""?t="number":e.match(/((^[0-9]+[a-z]+)|(^[a-z]+[0-9]+))+$/i)?t="alphanum":t="string";break}return t}setColumns(e,t){for(;this.headersElement.firstChild;)this.headersElement.removeChild(this.headersElement.firstChild);this.columns=[],this.columnsByIndex=[],this.columnsByField={},this.dispatch("columns-loading"),this.dispatchExternal("columnsLoading"),this.table.options.rowHeader&&(this.rowHeader=new te(this.table.options.rowHeader===!0?{}:this.table.options.rowHeader,this,!0),this.columns.push(this.rowHeader),this.headersElement.appendChild(this.rowHeader.getElement()),this.rowHeader.columnRendered()),e.forEach((s,a)=>{this._addColumn(s)}),this._reIndexColumns(),this.dispatch("columns-loaded"),this.subscribedExternal("columnsLoaded")&&this.dispatchExternal("columnsLoaded",this.getComponents()),this.rerenderColumns(!1,!0),this.redraw(!0)}_addColumn(e,t,s){var a=new te(e,this),i=a.getElement(),n=s&&this.findColumnIndex(s);if(t&&this.rowHeader&&(!s||s===this.rowHeader)&&(t=!1,s=this.rowHeader,n=0),s&&n>-1){var r=s.getTopColumn(),o=this.columns.indexOf(r),l=r.getElement();t?(this.columns.splice(o,0,a),l.parentNode.insertBefore(i,l)):(this.columns.splice(o+1,0,a),l.parentNode.insertBefore(i,l.nextSibling))}else t?(this.columns.unshift(a),this.headersElement.insertBefore(a.getElement(),this.headersElement.firstChild)):(this.columns.push(a),this.headersElement.appendChild(a.getElement()));return a.columnRendered(),a}registerColumnField(e){e.definition.field&&(this.columnsByField[e.definition.field]=e)}registerColumnPosition(e){this.columnsByIndex.push(e)}_reIndexColumns(){this.columnsByIndex=[],this.columns.forEach(function(e){e.reRegisterPosition()})}verticalAlignHeaders(){var e=0;this.redrawBlock||(this.headersElement.style.height="",this.columns.forEach(t=>{t.clearVerticalAlign()}),this.columns.forEach(t=>{var s=t.getHeight();s>e&&(e=s)}),this.headersElement.style.height=e+"px",this.columns.forEach(t=>{t.verticalAlign(this.table.options.columnHeaderVertAlign,e)}),this.table.rowManager.adjustTableSize())}findColumn(e){var t;if(typeof e=="object"){if(e instanceof te)return e;if(e instanceof Wt)return e._getSelf()||!1;if(typeof HTMLElement<"u"&&e instanceof HTMLElement)return t=[],this.columns.forEach(a=>{t.push(a),t=t.concat(a.getColumns(!0))}),t.find(a=>a.element===e)||!1}else return this.columnsByField[e]||!1;return!1}getColumnByField(e){return this.columnsByField[e]}getColumnsByFieldRoot(e){var t=[];return Object.keys(this.columnsByField).forEach(s=>{var a=this.table.options.nestedFieldSeparator?s.split(this.table.options.nestedFieldSeparator)[0]:s;a===e&&t.push(this.columnsByField[s])}),t}getColumnByIndex(e){return this.columnsByIndex[e]}getFirstVisibleColumn(){var e=this.columnsByIndex.findIndex(t=>t.visible);return e>-1?this.columnsByIndex[e]:!1}getVisibleColumnsByIndex(){return this.columnsByIndex.filter(e=>e.visible)}getColumns(){return this.columns}findColumnIndex(e){return this.columnsByIndex.findIndex(t=>e===t)}getRealColumns(){return this.columnsByIndex}traverse(e){this.columnsByIndex.forEach((t,s)=>{e(t,s)})}getDefinitions(e){var t=[];return this.columnsByIndex.forEach(s=>{(!e||e&&s.visible)&&t.push(s.getDefinition())}),t}getDefinitionTree(){var e=[];return this.columns.forEach(t=>{e.push(t.getDefinition(!0))}),e}getComponents(e){var t=[],s=e?this.columns:this.columnsByIndex;return s.forEach(a=>{t.push(a.getComponent())}),t}getWidth(){var e=0;return this.columnsByIndex.forEach(t=>{t.visible&&(e+=t.getWidth())}),e}moveColumn(e,t,s){t.element.parentNode.insertBefore(e.element,t.element),s&&t.element.parentNode.insertBefore(t.element,e.element),this.moveColumnActual(e,t,s),this.verticalAlignHeaders(),this.table.rowManager.reinitialize()}moveColumnActual(e,t,s){e.parent.isGroup?this._moveColumnInArray(e.parent.columns,e,t,s):this._moveColumnInArray(this.columns,e,t,s),this._moveColumnInArray(this.columnsByIndex,e,t,s,!0),this.rerenderColumns(!0),this.dispatch("column-moved",e,t,s),this.subscribedExternal("columnMoved")&&this.dispatchExternal("columnMoved",e.getComponent(),this.table.columnManager.getComponents())}_moveColumnInArray(e,t,s,a,i){var n=e.indexOf(t),r,o=[];n>-1&&(e.splice(n,1),r=e.indexOf(s),r>-1?a&&(r=r+1):r=n,e.splice(r,0,t),i&&(o=this.chain("column-moving-rows",[t,s,a],null,[])||[],o=o.concat(this.table.rowManager.rows),o.forEach(function(l){if(l.cells.length){var c=l.cells.splice(n,1)[0];l.cells.splice(r,0,c)}})))}scrollToColumn(e,t,s){var a=0,i=e.getLeftOffset(),n=0,r=e.getElement();return new Promise((o,l)=>{if(typeof t>"u"&&(t=this.table.options.scrollToColumnPosition),typeof s>"u"&&(s=this.table.options.scrollToColumnIfVisible),e.visible){switch(t){case"middle":case"center":n=-this.element.clientWidth/2;break;case"right":n=r.clientWidth-this.headersElement.clientWidth;break}if(!s&&i>0&&i+r.offsetWidth<this.element.clientWidth)return!1;a=i+n,a=Math.max(Math.min(a,this.table.rowManager.element.scrollWidth-this.table.rowManager.element.clientWidth),0),this.table.rowManager.scrollHorizontal(a),this.scrollHorizontal(a),o()}else console.warn("Scroll Error - Column not visible"),l("Scroll Error - Column not visible")})}generateCells(e){var t=[];return this.columnsByIndex.forEach(s=>{t.push(s.generateCell(e))}),t}getFlexBaseWidth(){var e=this.table.element.clientWidth,t=0;return this.table.rowManager.element.scrollHeight>this.table.rowManager.element.clientHeight&&(e-=this.table.rowManager.element.offsetWidth-this.table.rowManager.element.clientWidth),this.columnsByIndex.forEach(function(s){var a,i,n;s.visible&&(a=s.definition.width||0,i=parseInt(s.minWidth),typeof a=="string"?a.indexOf("%")>-1?n=e/100*parseInt(a):n=parseInt(a):n=a,t+=n>i?n:i)}),t}addColumn(e,t,s){return new Promise((a,i)=>{var n=this._addColumn(e,t,s);this._reIndexColumns(),this.dispatch("column-add",e,t,s),this.layoutMode()!="fitColumns"&&n.reinitializeWidth(),this.redraw(!0),this.table.rowManager.reinitialize(),this.rerenderColumns(),a(n)})}deregisterColumn(e){var t=e.getField(),s;t&&delete this.columnsByField[t],s=this.columnsByIndex.indexOf(e),s>-1&&this.columnsByIndex.splice(s,1),s=this.columns.indexOf(e),s>-1&&this.columns.splice(s,1),this.verticalAlignHeaders(),this.redraw()}rerenderColumns(e,t){this.redrawBlock?(e===!1||e===!0&&this.redrawBlockUpdate===null)&&(this.redrawBlockUpdate=e):this.renderer.rerenderColumns(e,t)}blockRedraw(){this.redrawBlock=!0,this.redrawBlockUpdate=null}restoreRedraw(){this.redrawBlock=!1,this.verticalAlignHeaders(),this.renderer.rerenderColumns(this.redrawBlockUpdate)}redraw(e){B.elVisible(this.element)&&this.verticalAlignHeaders(),e&&(this.table.rowManager.resetScroll(),this.table.rowManager.reinitialize()),this.confirm("table-redrawing",e)||this.layoutRefresh(e),this.dispatch("table-redraw",e),this.table.footerManager.redraw()}}class Ki extends qe{constructor(e){super(e),this.verticalFillMode="fill",this.scrollTop=0,this.scrollLeft=0,this.scrollTop=0,this.scrollLeft=0}clearRows(){for(var e=this.tableElement;e.firstChild;)e.removeChild(e.firstChild);e.scrollTop=0,e.scrollLeft=0,e.style.minWidth="",e.style.minHeight="",e.style.display="",e.style.visibility=""}renderRows(){var e=this.tableElement,t=!0,s=document.createDocumentFragment(),a=this.rows();a.forEach((i,n)=>{this.styleRow(i,n),i.initialize(!1,!0),i.type!=="group"&&(t=!1),s.appendChild(i.getElement())}),e.appendChild(s),a.forEach(i=>{i.rendered(),i.heightInitialized||i.calcHeight(!0)}),a.forEach(i=>{i.heightInitialized||i.setCellHeight()}),t?e.style.minWidth=this.table.columnManager.getWidth()+"px":e.style.minWidth=""}rerenderRows(e){this.clearRows(),e&&e(),this.renderRows(),this.rows().length||this.table.rowManager.tableEmpty()}scrollToRowNearestTop(e){var t=B.elOffset(e.getElement()).top;return!(Math.abs(this.elementVertical.scrollTop-t)>Math.abs(this.elementVertical.scrollTop+this.elementVertical.clientHeight-t))}scrollToRow(e){var t=e.getElement();this.elementVertical.scrollTop=B.elOffset(t).top-B.elOffset(this.elementVertical).top+this.elementVertical.scrollTop}visibleRows(e){return this.rows()}}class Ji extends qe{constructor(e){super(e),this.verticalFillMode="fill",this.scrollTop=0,this.scrollLeft=0,this.vDomRowHeight=20,this.vDomTop=0,this.vDomBottom=0,this.vDomScrollPosTop=0,this.vDomScrollPosBottom=0,this.vDomTopPad=0,this.vDomBottomPad=0,this.vDomMaxRenderChain=90,this.vDomWindowBuffer=0,this.vDomWindowMinTotalRows=20,this.vDomWindowMinMarginRows=5,this.vDomTopNewRows=[],this.vDomBottomNewRows=[]}clearRows(){for(var e=this.tableElement;e.firstChild;)e.removeChild(e.firstChild);e.style.paddingTop="",e.style.paddingBottom="",e.style.minHeight="",e.style.display="",e.style.visibility="",this.elementVertical.scrollTop=0,this.elementVertical.scrollLeft=0,this.scrollTop=0,this.scrollLeft=0,this.vDomTop=0,this.vDomBottom=0,this.vDomTopPad=0,this.vDomBottomPad=0,this.vDomScrollPosTop=0,this.vDomScrollPosBottom=0}renderRows(){this._virtualRenderFill()}rerenderRows(e){for(var t=this.elementVertical.scrollTop,s=!1,a=!1,i=this.table.rowManager.scrollLeft,n=this.rows(),r=this.vDomTop;r<=this.vDomBottom;r++)if(n[r]){var o=t-n[r].getElement().offsetTop;if(a===!1||Math.abs(o)<a)a=o,s=r;else break}n.forEach(l=>{l.deinitializeHeight()}),e&&e(),this.rows().length?this._virtualRenderFill(s===!1?this.rows.length-1:s,!0,a||0):(this.clear(),this.table.rowManager.tableEmpty()),this.scrollColumns(i)}scrollColumns(e){this.table.rowManager.scrollHorizontal(e)}scrollRows(e,t){var s=e-this.vDomScrollPosTop,a=e-this.vDomScrollPosBottom,i=this.vDomWindowBuffer*2,n=this.rows();if(this.scrollTop=e,-s>i||a>i){var r=this.table.rowManager.scrollLeft;this._virtualRenderFill(Math.floor(this.elementVertical.scrollTop/this.elementVertical.scrollHeight*n.length)),this.scrollColumns(r)}else t?(s<0&&this._addTopRow(n,-s),a<0&&(this.vDomScrollHeight-this.scrollTop>this.vDomWindowBuffer?this._removeBottomRow(n,-a):this.vDomScrollPosBottom=this.scrollTop)):(a>=0&&this._addBottomRow(n,a),s>=0&&(this.scrollTop>this.vDomWindowBuffer?this._removeTopRow(n,s):this.vDomScrollPosTop=this.scrollTop))}resize(){this.vDomWindowBuffer=this.table.options.renderVerticalBuffer||this.elementVertical.clientHeight}scrollToRowNearestTop(e){var t=this.rows().indexOf(e);return!(Math.abs(this.vDomTop-t)>Math.abs(this.vDomBottom-t))}scrollToRow(e){var t=this.rows().indexOf(e);t>-1&&this._virtualRenderFill(t,!0)}visibleRows(e){var t=this.elementVertical.scrollTop,s=this.elementVertical.clientHeight+t,a=!1,i=0,n=0,r=this.rows();if(e)i=this.vDomTop,n=this.vDomBottom;else for(var o=this.vDomTop;o<=this.vDomBottom;o++)if(r[o])if(a)if(s-r[o].getElement().offsetTop>=0)n=o;else break;else if(t-r[o].getElement().offsetTop>=0)i=o;else if(a=!0,s-r[o].getElement().offsetTop>=0)n=o;else break;return r.slice(i,n+1)}_virtualRenderFill(e,t,s){var a=this.tableElement,i=this.elementVertical,n=0,r=0,o=0,l=0,c=0,d=0,h=this.rows(),u=h.length,f=0,m,b,v=[],y=0,$=0,w=this.table.rowManager.fixedHeight,_=this.elementVertical.clientHeight,k=this.table.options.rowHeight,R=!0;if(e=e||0,s=s||0,!e)this.clear();else{for(;a.firstChild;)a.removeChild(a.firstChild);l=(u-e+1)*this.vDomRowHeight,l<_&&(e-=Math.ceil((_-l)/this.vDomRowHeight),e<0&&(e=0)),n=Math.min(Math.max(Math.floor(this.vDomWindowBuffer/this.vDomRowHeight),this.vDomWindowMinMarginRows),e),e-=n}if(u&&B.elVisible(this.elementVertical)){for(this.vDomTop=e,this.vDomBottom=e-1,w||this.table.options.maxHeight?(k&&($=_/k+this.vDomWindowBuffer/k),$=Math.max(this.vDomWindowMinTotalRows,Math.ceil($))):$=u;($==u||r<=_+this.vDomWindowBuffer||y<this.vDomWindowMinTotalRows)&&this.vDomBottom<u-1;){for(v=[],b=document.createDocumentFragment(),d=0;d<$&&this.vDomBottom<u-1;)f=this.vDomBottom+1,m=h[f],this.styleRow(m,f),m.initialize(!1,!0),!m.heightInitialized&&!this.table.options.rowHeight&&m.clearCellHeight(),b.appendChild(m.getElement()),v.push(m),this.vDomBottom++,d++;if(!v.length)break;a.appendChild(b),v.forEach(q=>{q.rendered()});const H=[];v.forEach(q=>{q.heightInitialized||(q.calcHeight(!0),H.push(q))}),H.forEach(q=>{q.setCellHeight()}),v.forEach(q=>{o=q.getHeight(),y<n?c+=o:r+=o,o>this.vDomWindowBuffer&&(this.vDomWindowBuffer=o*2),y++}),R=this.table.rowManager.adjustTableSize(),_=this.elementVertical.clientHeight,R&&(w||this.table.options.maxHeight)&&(k=r/y,$=Math.max(this.vDomWindowMinTotalRows,Math.ceil(_/k+this.vDomWindowBuffer/k)))}e?(this.vDomTopPad=t?this.vDomRowHeight*this.vDomTop+s:this.scrollTop-c,this.vDomBottomPad=this.vDomBottom==u-1?0:Math.max(this.vDomScrollHeight-this.vDomTopPad-r-c,0)):(this.vDomTopPad=0,this.vDomRowHeight=Math.floor((r+c)/y),this.vDomBottomPad=this.vDomRowHeight*(u-this.vDomBottom-1),this.vDomScrollHeight=c+r+this.vDomBottomPad-_),a.style.paddingTop=this.vDomTopPad+"px",a.style.paddingBottom=this.vDomBottomPad+"px",t&&(this.scrollTop=this.vDomTopPad+c+s-(this.elementVertical.scrollWidth>this.elementVertical.clientWidth?this.elementVertical.offsetHeight-_:0)),this.scrollTop=Math.min(this.scrollTop,this.elementVertical.scrollHeight-_),this.elementVertical.scrollWidth>this.elementVertical.clientWidth&&t&&(this.scrollTop+=this.elementVertical.offsetHeight-_),this.vDomScrollPosTop=this.scrollTop,this.vDomScrollPosBottom=this.scrollTop,i.scrollTop=this.scrollTop,this.dispatch("render-virtual-fill")}}_addTopRow(e,t){for(var s=this.tableElement,a=[],i=0,n=this.vDomTop-1,r=0,o=!0;o;)if(this.vDomTop){let l=e[n],c,d;l&&r<this.vDomMaxRenderChain?(c=l.getHeight()||this.vDomRowHeight,d=l.initialized,t>=c?(this.styleRow(l,n),s.insertBefore(l.getElement(),s.firstChild),(!l.initialized||!l.heightInitialized)&&a.push(l),l.initialize(),d||(c=l.getElement().offsetHeight,c>this.vDomWindowBuffer&&(this.vDomWindowBuffer=c*2)),t-=c,i+=c,this.vDomTop--,n--,r++):o=!1):o=!1}else o=!1;for(let l of a)l.clearCellHeight();this._quickNormalizeRowHeight(a),i&&(this.vDomTopPad-=i,this.vDomTopPad<0&&(this.vDomTopPad=n*this.vDomRowHeight),n<1&&(this.vDomTopPad=0),s.style.paddingTop=this.vDomTopPad+"px",this.vDomScrollPosTop-=i)}_removeTopRow(e,t){for(var s=[],a=0,i=0,n=!0;n;){let r=e[this.vDomTop],o;r&&i<this.vDomMaxRenderChain?(o=r.getHeight()||this.vDomRowHeight,t>=o?(this.vDomTop++,t-=o,a+=o,s.push(r),i++):n=!1):n=!1}for(let r of s){let o=r.getElement();o.parentNode&&o.parentNode.removeChild(o)}a&&(this.vDomTopPad+=a,this.tableElement.style.paddingTop=this.vDomTopPad+"px",this.vDomScrollPosTop+=this.vDomTop?a:a+this.vDomWindowBuffer)}_addBottomRow(e,t){for(var s=this.tableElement,a=[],i=0,n=this.vDomBottom+1,r=0,o=!0;o;){let l=e[n],c,d;l&&r<this.vDomMaxRenderChain?(c=l.getHeight()||this.vDomRowHeight,d=l.initialized,t>=c?(this.styleRow(l,n),s.appendChild(l.getElement()),(!l.initialized||!l.heightInitialized)&&a.push(l),l.initialize(),d||(c=l.getElement().offsetHeight,c>this.vDomWindowBuffer&&(this.vDomWindowBuffer=c*2)),t-=c,i+=c,this.vDomBottom++,n++,r++):o=!1):o=!1}for(let l of a)l.clearCellHeight();this._quickNormalizeRowHeight(a),i&&(this.vDomBottomPad-=i,(this.vDomBottomPad<0||n==e.length-1)&&(this.vDomBottomPad=0),s.style.paddingBottom=this.vDomBottomPad+"px",this.vDomScrollPosBottom+=i)}_removeBottomRow(e,t){for(var s=[],a=0,i=0,n=!0;n;){let r=e[this.vDomBottom],o;r&&i<this.vDomMaxRenderChain?(o=r.getHeight()||this.vDomRowHeight,t>=o?(this.vDomBottom--,t-=o,a+=o,s.push(r),i++):n=!1):n=!1}for(let r of s){let o=r.getElement();o.parentNode&&o.parentNode.removeChild(o)}a&&(this.vDomBottomPad+=a,this.vDomBottomPad<0&&(this.vDomBottomPad=0),this.tableElement.style.paddingBottom=this.vDomBottomPad+"px",this.vDomScrollPosBottom-=a)}_quickNormalizeRowHeight(e){for(let t of e)t.calcHeight();for(let t of e)t.setCellHeight()}}class Yi extends j{constructor(e){super(e),this.element=this.createHolderElement(),this.tableElement=this.createTableElement(),this.heightFixer=this.createTableElement(),this.placeholder=null,this.placeholderContents=null,this.firstRender=!1,this.renderMode="virtual",this.fixedHeight=!1,this.rows=[],this.activeRowsPipeline=[],this.activeRows=[],this.activeRowsCount=0,this.displayRows=[],this.displayRowsCount=0,this.scrollTop=0,this.scrollLeft=0,this.redrawBlock=!1,this.redrawBlockRestoreConfig=!1,this.redrawBlockRenderInPosition=!1,this.dataPipeline=[],this.displayPipeline=[],this.scrollbarWidth=0,this.renderer=null}createHolderElement(){var e=document.createElement("div");return e.classList.add("tabulator-tableholder"),e.setAttribute("tabindex",0),e}createTableElement(){var e=document.createElement("div");return e.classList.add("tabulator-table"),e.setAttribute("role","rowgroup"),e.setAttribute("id","tabulator-table-body"),e}initializePlaceholder(){var e=this.table.options.placeholder;if(typeof e=="function"&&(e=e.call(this.table)),e=this.chain("placeholder",[e],e,e)||e,e){let t=document.createElement("div");if(t.classList.add("tabulator-placeholder"),typeof e=="string"){let s=document.createElement("div");s.classList.add("tabulator-placeholder-contents"),s.innerHTML=e,t.appendChild(s),this.placeholderContents=s}else typeof HTMLElement<"u"&&e instanceof HTMLElement?(t.appendChild(e),this.placeholderContents=e):(console.warn("Invalid placeholder provided, must be string or HTML Element",e),this.el=null);this.placeholder=t}}getElement(){return this.element}getTableElement(){return this.tableElement}initialize(){this.initializePlaceholder(),this.initializeRenderer(),this.element.appendChild(this.tableElement),this.firstRender=!0,this.element.addEventListener("scroll",()=>{var e=this.element.scrollLeft,t=this.scrollLeft>e,s=this.element.scrollTop,a=this.scrollTop>s;this.scrollLeft!=e&&(this.scrollLeft=e,this.dispatch("scroll-horizontal",e,t),this.dispatchExternal("scrollHorizontal",e,t),this._positionPlaceholder()),this.scrollTop!=s&&(this.scrollTop=s,this.renderer.scrollRows(s,a),this.dispatch("scroll-vertical",s,a),this.dispatchExternal("scrollVertical",s,a))})}findRow(e){if(typeof e=="object"){if(e instanceof Y)return e;if(e instanceof Je)return e._getSelf()||!1;if(typeof HTMLElement<"u"&&e instanceof HTMLElement)return this.rows.find(s=>s.getElement()===e)||!1;if(e===null)return!1}else return typeof e>"u"?!1:this.rows.find(s=>s.data[this.table.options.index]==e)||!1;return!1}getRowFromDataObject(e){var t=this.rows.find(s=>s.data===e);return t||!1}getRowFromPosition(e){return this.getDisplayRows().find(t=>t.type==="row"&&t.getPosition()===e&&t.isDisplayed())}scrollToRow(e,t,s){return this.renderer.scrollToRowPosition(e,t,s)}setData(e,t,s){return new Promise((a,i)=>{t&&this.getDisplayRows().length?this.table.options.pagination?this._setDataActual(e,!0):this.reRenderInPosition(()=>{this._setDataActual(e)}):(this.table.options.autoColumns&&s&&this.table.initialized&&this.table.columnManager.generateColumnsFromRowData(e),this.resetScroll(),this._setDataActual(e)),a()})}_setDataActual(e,t){this.dispatchExternal("dataProcessing",e),this._wipeElements(),Array.isArray(e)?(this.dispatch("data-processing",e),e.forEach((s,a)=>{if(s&&typeof s=="object"){var i=new Y(s,this);this.rows.push(i)}else console.warn("Data Loading Warning - Invalid row data detected and ignored, expecting object but received:",s)}),this.refreshActiveData(!1,!1,t),this.dispatch("data-processed",e),this.dispatchExternal("dataProcessed",e)):console.error(`Data Loading Error - Unable to process data due to invalid data type 
Expecting: array 
Received: `,typeof e,`
Data:     `,e)}_wipeElements(){this.dispatch("rows-wipe"),this.destroy(),this.adjustTableSize(),this.dispatch("rows-wiped")}destroy(){this.rows.forEach(e=>{e.wipe()}),this.rows=[],this.activeRows=[],this.activeRowsPipeline=[],this.activeRowsCount=0,this.displayRows=[],this.displayRowsCount=0}deleteRow(e,t){var s=this.rows.indexOf(e),a=this.activeRows.indexOf(e);a>-1&&this.activeRows.splice(a,1),s>-1&&this.rows.splice(s,1),this.setActiveRows(this.activeRows),this.displayRowIterator(i=>{var n=i.indexOf(e);n>-1&&i.splice(n,1)}),t||this.reRenderInPosition(),this.regenerateRowPositions(),this.dispatchExternal("rowDeleted",e.getComponent()),this.displayRowsCount||this.tableEmpty(),this.subscribedExternal("dataChanged")&&this.dispatchExternal("dataChanged",this.getData())}addRow(e,t,s,a){var i=this.addRowActual(e,t,s,a);return i}addRows(e,t,s,a){var i=[];return new Promise((n,r)=>{t=this.findAddRowPos(t),Array.isArray(e)||(e=[e]),(typeof s>"u"&&t||typeof s<"u"&&!t)&&e.reverse(),e.forEach((o,l)=>{var c=this.addRow(o,t,s,!0);i.push(c),this.dispatch("row-added",c,o,t,s)}),this.refreshActiveData(a?"displayPipeline":!1,!1,!0),this.regenerateRowPositions(),this.displayRowsCount&&this._clearPlaceholder(),n(i)})}findAddRowPos(e){return typeof e>"u"&&(e=this.table.options.addRowPos),e==="pos"&&(e=!0),e==="bottom"&&(e=!1),e}addRowActual(e,t,s,a){var i=e instanceof Y?e:new Y(e||{},this),n=this.findAddRowPos(t),r=-1,o,l;return s||(l=this.chain("row-adding-position",[i,n],null,{index:s,top:n}),s=l.index,n=l.top),typeof s<"u"&&(s=this.findRow(s)),s=this.chain("row-adding-index",[i,s,n],null,s),s&&(r=this.rows.indexOf(s)),s&&r>-1?(o=this.activeRows.indexOf(s),this.displayRowIterator(function(c){var d=c.indexOf(s);d>-1&&c.splice(n?d:d+1,0,i)}),o>-1&&this.activeRows.splice(n?o:o+1,0,i),this.rows.splice(n?r:r+1,0,i)):n?(this.displayRowIterator(function(c){c.unshift(i)}),this.activeRows.unshift(i),this.rows.unshift(i)):(this.displayRowIterator(function(c){c.push(i)}),this.activeRows.push(i),this.rows.push(i)),this.setActiveRows(this.activeRows),this.dispatchExternal("rowAdded",i.getComponent()),this.subscribedExternal("dataChanged")&&this.dispatchExternal("dataChanged",this.table.rowManager.getData()),a||this.reRenderInPosition(),i}moveRow(e,t,s){this.dispatch("row-move",e,t,s),this.moveRowActual(e,t,s),this.regenerateRowPositions(),this.dispatch("row-moved",e,t,s),this.dispatchExternal("rowMoved",e.getComponent())}moveRowActual(e,t,s){this.moveRowInArray(this.rows,e,t,s),this.moveRowInArray(this.activeRows,e,t,s),this.displayRowIterator(a=>{this.moveRowInArray(a,e,t,s)}),this.dispatch("row-moving",e,t,s)}moveRowInArray(e,t,s,a){var i,n,r,o;if(t!==s&&(i=e.indexOf(t),i>-1&&(e.splice(i,1),n=e.indexOf(s),n>-1?a?e.splice(n+1,0,t):e.splice(n,0,t):e.splice(i,0,t)),e===this.getDisplayRows())){r=i<n?i:n,o=n>i?n:i+1;for(let l=r;l<=o;l++)e[l]&&this.styleRow(e[l],l)}}clearData(){this.setData([])}getRowIndex(e){return this.findRowIndex(e,this.rows)}getDisplayRowIndex(e){var t=this.getDisplayRows().indexOf(e);return t>-1?t:!1}nextDisplayRow(e,t){var s=this.getDisplayRowIndex(e),a=!1;return s!==!1&&s<this.displayRowsCount-1&&(a=this.getDisplayRows()[s+1]),a&&(!(a instanceof Y)||a.type!="row")?this.nextDisplayRow(a,t):a}prevDisplayRow(e,t){var s=this.getDisplayRowIndex(e),a=!1;return s&&(a=this.getDisplayRows()[s-1]),t&&a&&(!(a instanceof Y)||a.type!="row")?this.prevDisplayRow(a,t):a}findRowIndex(e,t){var s;return e=this.findRow(e),e&&(s=t.indexOf(e),s>-1)?s:!1}getData(e,t){var s=[],a=this.getRows(e);return a.forEach(function(i){i.type=="row"&&s.push(i.getData(t||"data"))}),s}getComponents(e){var t=[],s=this.getRows(e);return s.forEach(function(a){t.push(a.getComponent())}),t}getDataCount(e){var t=this.getRows(e);return t.length}scrollHorizontal(e){this.scrollLeft=e,this.element.scrollLeft=e,this.dispatch("scroll-horizontal",e)}registerDataPipelineHandler(e,t){typeof t<"u"?(this.dataPipeline.push({handler:e,priority:t}),this.dataPipeline.sort((s,a)=>s.priority-a.priority)):console.error("Data pipeline handlers must have a priority in order to be registered")}registerDisplayPipelineHandler(e,t){typeof t<"u"?(this.displayPipeline.push({handler:e,priority:t}),this.displayPipeline.sort((s,a)=>s.priority-a.priority)):console.error("Display pipeline handlers must have a priority in order to be registered")}refreshActiveData(e,t,s){var a=this.table,i="",n=0,r=["all","dataPipeline","display","displayPipeline","end"];if(!this.table.destroyed){if(typeof e=="function")if(n=this.dataPipeline.findIndex(o=>o.handler===e),n>-1)i="dataPipeline",t&&(n==this.dataPipeline.length-1?i="display":n++);else if(n=this.displayPipeline.findIndex(o=>o.handler===e),n>-1)i="displayPipeline",t&&(n==this.displayPipeline.length-1?i="end":n++);else{console.error("Unable to refresh data, invalid handler provided",e);return}else i=e||"all",n=0;if(this.redrawBlock){(!this.redrawBlockRestoreConfig||this.redrawBlockRestoreConfig&&(this.redrawBlockRestoreConfig.stage===i&&n<this.redrawBlockRestoreConfig.index||r.indexOf(i)<r.indexOf(this.redrawBlockRestoreConfig.stage)))&&(this.redrawBlockRestoreConfig={handler:e,skipStage:t,renderInPosition:s,stage:i,index:n});return}else B.elVisible(this.element)?s?this.reRenderInPosition(this.refreshPipelines.bind(this,e,i,n,s)):(this.refreshPipelines(e,i,n,s),e||this.table.columnManager.renderer.renderColumns(),this.renderTable(),a.options.layoutColumnsOnNewData&&this.table.columnManager.redraw(!0)):this.refreshPipelines(e,i,n,s),this.dispatch("data-refreshed")}}refreshPipelines(e,t,s,a){switch(this.dispatch("data-refreshing"),(!e||!this.activeRowsPipeline[0])&&(this.activeRowsPipeline[0]=this.rows.slice(0)),t){case"all":case"dataPipeline":for(let i=s;i<this.dataPipeline.length;i++){let n=this.dataPipeline[i].handler(this.activeRowsPipeline[i].slice(0));this.activeRowsPipeline[i+1]=n||this.activeRowsPipeline[i].slice(0)}this.setActiveRows(this.activeRowsPipeline[this.dataPipeline.length]);case"display":s=0,this.resetDisplayRows();case"displayPipeline":for(let i=s;i<this.displayPipeline.length;i++){let n=this.displayPipeline[i].handler((i?this.getDisplayRows(i-1):this.activeRows).slice(0),a);this.setDisplayRows(n||this.getDisplayRows(i-1).slice(0),i)}case"end":this.regenerateRowPositions()}this.getDisplayRows().length&&this._clearPlaceholder()}regenerateRowPositions(){var e=this.getDisplayRows(),t=1;e.forEach(s=>{s.type==="row"&&(s.setPosition(t),t++)})}setActiveRows(e){this.activeRows=this.activeRows=Object.assign([],e),this.activeRowsCount=this.activeRows.length}resetDisplayRows(){this.displayRows=[],this.displayRows.push(this.activeRows.slice(0)),this.displayRowsCount=this.displayRows[0].length}setDisplayRows(e,t){this.displayRows[t]=e,t==this.displayRows.length-1&&(this.displayRowsCount=this.displayRows[this.displayRows.length-1].length)}getDisplayRows(e){return typeof e>"u"?this.displayRows.length?this.displayRows[this.displayRows.length-1]:[]:this.displayRows[e]||[]}getVisibleRows(e,t){var s=Object.assign([],this.renderer.visibleRows(!t));return e&&(s=this.chain("rows-visible",[t],s,s)),s}displayRowIterator(e){this.activeRowsPipeline.forEach(e),this.displayRows.forEach(e),this.displayRowsCount=this.displayRows[this.displayRows.length-1].length}getRows(e){var t=[];switch(e){case"active":t=this.activeRows;break;case"display":t=this.table.rowManager.getDisplayRows();break;case"visible":t=this.getVisibleRows(!1,!0);break;default:t=this.chain("rows-retrieve",e,null,this.rows)||this.rows}return t}reRenderInPosition(e){this.redrawBlock?e?e():this.redrawBlockRenderInPosition=!0:(this.dispatchExternal("renderStarted"),this.renderer.rerenderRows(e),this.fixedHeight||this.adjustTableSize(),this.scrollBarCheck(),this.dispatchExternal("renderComplete"))}scrollBarCheck(){var e=0;this.element.scrollHeight>this.element.clientHeight&&(e=this.element.offsetWidth-this.element.clientWidth),e!==this.scrollbarWidth&&(this.scrollbarWidth=e,this.dispatch("scrollbar-vertical",e))}initializeRenderer(){var e,t={virtual:Ji,basic:Ki};typeof this.table.options.renderVertical=="string"?e=t[this.table.options.renderVertical]:e=this.table.options.renderVertical,e?(this.renderMode=this.table.options.renderVertical,this.renderer=new e(this.table,this.element,this.tableElement),this.renderer.initialize(),(this.table.element.clientHeight||this.table.options.height)&&!(this.table.options.minHeight&&this.table.options.maxHeight)?this.fixedHeight=!0:this.fixedHeight=!1):console.error("Unable to find matching renderer:",this.table.options.renderVertical)}getRenderMode(){return this.renderMode}renderTable(){this.dispatchExternal("renderStarted"),this.element.scrollTop=0,this._clearTable(),this.displayRowsCount?(this.renderer.renderRows(),this.firstRender&&(this.firstRender=!1,this.fixedHeight||this.adjustTableSize(),this.layoutRefresh(!0))):this.renderEmptyScroll(),this.fixedHeight||this.adjustTableSize(),this.dispatch("table-layout"),this.displayRowsCount||this._showPlaceholder(),this.scrollBarCheck(),this.dispatchExternal("renderComplete")}renderEmptyScroll(){this.placeholder?this.tableElement.style.display="none":this.tableElement.style.minWidth=this.table.columnManager.getWidth()+"px"}_clearTable(){this._clearPlaceholder(),this.scrollTop=0,this.scrollLeft=0,this.renderer.clearRows()}tableEmpty(){this.renderEmptyScroll(),this._showPlaceholder()}checkPlaceholder(){this.displayRowsCount?this._clearPlaceholder():this.tableEmpty()}_showPlaceholder(){this.placeholder&&(this.placeholder&&this.placeholder.parentNode&&this.placeholder.parentNode.removeChild(this.placeholder),this.initializePlaceholder(),this.placeholder.setAttribute("tabulator-render-mode",this.renderMode),this.getElement().appendChild(this.placeholder),this._positionPlaceholder(),this.adjustTableSize())}_clearPlaceholder(){this.placeholder&&this.placeholder.parentNode&&this.placeholder.parentNode.removeChild(this.placeholder),this.tableElement.style.minWidth="",this.tableElement.style.display=""}_positionPlaceholder(){this.placeholder&&this.placeholder.parentNode&&(this.placeholder.style.width=this.table.columnManager.getWidth()+"px",this.placeholderContents.style.width=this.table.rowManager.element.clientWidth+"px",this.placeholderContents.style.marginLeft=this.scrollLeft+"px")}styleRow(e,t){var s=e.getElement();t%2?(s.classList.add("tabulator-row-even"),s.classList.remove("tabulator-row-odd")):(s.classList.add("tabulator-row-odd"),s.classList.remove("tabulator-row-even"))}normalizeHeight(e){this.activeRows.forEach(function(t){t.normalizeHeight(e)})}adjustTableSize(){let e=this.element.clientHeight,t,s=!1;if(this.renderer.verticalFillMode==="fill"){let a=Math.floor(this.table.columnManager.getElement().getBoundingClientRect().height+(this.table.footerManager&&this.table.footerManager.active&&!this.table.footerManager.external?this.table.footerManager.getElement().getBoundingClientRect().height:0));if(this.fixedHeight){t=isNaN(this.table.options.minHeight)?this.table.options.minHeight:this.table.options.minHeight+"px";const i="calc(100% - "+a+"px)";this.element.style.minHeight=t||"calc(100% - "+a+"px)",this.element.style.height=i,this.element.style.maxHeight=i}else this.element.style.height="",this.element.style.height=this.table.element.clientHeight-a+"px",this.element.scrollTop=this.scrollTop;this.renderer.resize(),!this.fixedHeight&&e!=this.element.clientHeight&&(s=!0,this.redrawing||(this.redrawing=!0,this.subscribed("table-resize")?this.dispatch("table-resize"):this.redraw(),this.redrawing=!1)),this.scrollBarCheck()}return this._positionPlaceholder(),s}reinitialize(){this.rows.forEach(function(e){e.reinitialize(!0)})}blockRedraw(){this.redrawBlock=!0,this.redrawBlockRestoreConfig=!1}restoreRedraw(){this.redrawBlock=!1,this.redrawBlockRestoreConfig?(this.refreshActiveData(this.redrawBlockRestoreConfig.handler,this.redrawBlockRestoreConfig.skipStage,this.redrawBlockRestoreConfig.renderInPosition),this.redrawBlockRestoreConfig=!1):this.redrawBlockRenderInPosition&&this.reRenderInPosition(),this.redrawBlockRenderInPosition=!1}redraw(e){this.adjustTableSize(),this.table.tableWidth=this.table.element.clientWidth,e?this.renderTable():(this.reRenderInPosition(),this.scrollHorizontal(this.scrollLeft))}resetScroll(){if(this.element.scrollLeft=0,this.element.scrollTop=0,this.table.browser==="ie"){var e=document.createEvent("Event");e.initEvent("scroll",!1,!0),this.element.dispatchEvent(e)}else this.element.dispatchEvent(new Event("scroll"))}}class Qi extends j{constructor(e){super(e),this.active=!1,this.element=this.createElement(),this.containerElement=this.createContainerElement(),this.external=!1}initialize(){this.initializeElement()}createElement(){var e=document.createElement("div");return e.classList.add("tabulator-footer"),e}createContainerElement(){var e=document.createElement("div");return e.classList.add("tabulator-footer-contents"),this.element.appendChild(e),e}initializeElement(){if(this.table.options.footerElement)switch(typeof this.table.options.footerElement){case"string":this.table.options.footerElement[0]==="<"?this.containerElement.innerHTML=this.table.options.footerElement:(this.external=!0,this.containerElement=document.querySelector(this.table.options.footerElement));break;default:this.element=this.table.options.footerElement;break}}getElement(){return this.element}append(e){this.activate(),this.containerElement.appendChild(e),this.table.rowManager.adjustTableSize()}prepend(e){this.activate(),this.element.insertBefore(e,this.element.firstChild),this.table.rowManager.adjustTableSize()}remove(e){e.parentNode.removeChild(e),this.deactivate()}deactivate(e){(!this.element.firstChild||e)&&(this.external||this.element.parentNode.removeChild(this.element),this.active=!1)}activate(){this.active||(this.active=!0,this.external||(this.table.element.appendChild(this.getElement()),this.table.element.style.display=""))}redraw(){this.dispatch("footer-redraw")}}class Zi extends j{constructor(e){super(e),this.el=null,this.abortClasses=["tabulator-headers","tabulator-table"],this.previousTargets={},this.listeners=["click","dblclick","contextmenu","mouseenter","mouseleave","mouseover","mouseout","mousemove","mouseup","mousedown","touchstart","touchend"],this.componentMap={"tabulator-cell":"cell","tabulator-row":"row","tabulator-group":"group","tabulator-col":"column"},this.pseudoTrackers={row:{subscriber:null,target:null},cell:{subscriber:null,target:null},group:{subscriber:null,target:null},column:{subscriber:null,target:null}},this.pseudoTracking=!1}initialize(){this.el=this.table.element,this.buildListenerMap(),this.bindSubscriptionWatchers()}buildListenerMap(){var e={};this.listeners.forEach(t=>{e[t]={handler:null,components:[]}}),this.listeners=e}bindPseudoEvents(){Object.keys(this.pseudoTrackers).forEach(e=>{this.pseudoTrackers[e].subscriber=this.pseudoMouseEnter.bind(this,e),this.subscribe(e+"-mouseover",this.pseudoTrackers[e].subscriber)}),this.pseudoTracking=!0}pseudoMouseEnter(e,t,s){this.pseudoTrackers[e].target!==s&&(this.pseudoTrackers[e].target&&this.dispatch(e+"-mouseleave",t,this.pseudoTrackers[e].target),this.pseudoMouseLeave(e,t),this.pseudoTrackers[e].target=s,this.dispatch(e+"-mouseenter",t,s))}pseudoMouseLeave(e,t){var s=Object.keys(this.pseudoTrackers),a={row:["cell"],cell:["row"]};s=s.filter(i=>{var n=a[e];return i!==e&&(!n||n&&!n.includes(i))}),s.forEach(i=>{var n=this.pseudoTrackers[i].target;this.pseudoTrackers[i].target&&(this.dispatch(i+"-mouseleave",t,n),this.pseudoTrackers[i].target=null)})}bindSubscriptionWatchers(){var e=Object.keys(this.listeners),t=Object.values(this.componentMap);for(let s of t)for(let a of e){let i=s+"-"+a;this.subscriptionChange(i,this.subscriptionChanged.bind(this,s,a))}this.subscribe("table-destroy",this.clearWatchers.bind(this))}subscriptionChanged(e,t,s){var a=this.listeners[t].components,i=a.indexOf(e),n=!1;s?i===-1&&(a.push(e),n=!0):this.subscribed(e+"-"+t)||i>-1&&(a.splice(i,1),n=!0),(t==="mouseenter"||t==="mouseleave")&&!this.pseudoTracking&&this.bindPseudoEvents(),n&&this.updateEventListeners()}updateEventListeners(){for(let e in this.listeners){let t=this.listeners[e];t.components.length?t.handler||(t.handler=this.track.bind(this,e),this.el.addEventListener(e,t.handler)):t.handler&&(this.el.removeEventListener(e,t.handler),t.handler=null)}}track(e,t){var s=t.composedPath&&t.composedPath()||t.path,a=this.findTargets(s);a=this.bindComponents(e,a),this.triggerEvents(e,t,a),this.pseudoTracking&&(e=="mouseover"||e=="mouseleave")&&!Object.keys(a).length&&this.pseudoMouseLeave("none",t)}findTargets(e){var t={};let s=Object.keys(this.componentMap);for(let a of e){let i=a.classList?[...a.classList]:[];if(i.filter(o=>this.abortClasses.includes(o)).length)break;let r=i.filter(o=>s.includes(o));for(let o of r)t[this.componentMap[o]]||(t[this.componentMap[o]]=a)}return t.group&&t.group===t.row&&delete t.row,t}bindComponents(e,t){var s=Object.keys(t).reverse(),a=this.listeners[e],i={},n={},r={};for(let o of s){let l,c=t[o],d=this.previousTargets[o];if(d&&d.target===c)l=d.component;else switch(o){case"row":case"group":(a.components.includes("row")||a.components.includes("cell")||a.components.includes("group"))&&(l=this.table.rowManager.getVisibleRows(!0).find(u=>u.getElement()===c),t.row&&t.row.parentNode&&t.row.parentNode.closest(".tabulator-row")&&(t[o]=!1));break;case"column":a.components.includes("column")&&(l=this.table.columnManager.findColumn(c));break;case"cell":a.components.includes("cell")&&(i.row instanceof Y?l=i.row.findCell(c):t.row&&console.warn("Event Target Lookup Error - The row this cell is attached to cannot be found, has the table been reinitialized without being destroyed first?"));break}l&&(i[o]=l,r[o]={target:c,component:l})}return this.previousTargets=r,Object.keys(t).forEach(o=>{let l=i[o];n[o]=l}),n}triggerEvents(e,t,s){var a=this.listeners[e];for(let i in s)s[i]&&a.components.includes(i)&&this.dispatch(i+"-"+e,t,s[i])}clearWatchers(){for(let e in this.listeners){let t=this.listeners[e];t.handler&&(this.el.removeEventListener(e,t.handler),t.handler=null)}}}class Xi{constructor(e){this.table=e,this.bindings={}}bind(e,t,s){this.bindings[e]||(this.bindings[e]={}),this.bindings[e][t]?console.warn("Unable to bind component handler, a matching function name is already bound",e,t,s):this.bindings[e][t]=s}handle(e,t,s){if(this.bindings[e]&&this.bindings[e][s]&&typeof this.bindings[e][s].bind=="function")return this.bindings[e][s].bind(null,t);s!=="then"&&typeof s=="string"&&!s.startsWith("_")&&this.table.options.debugInvalidComponentFuncs&&console.error("The "+e+" component does not have a "+s+" function, have you checked that you have the correct Tabulator module installed?")}}class en extends j{constructor(e){super(e),this.requestOrder=0,this.loading=!1}initialize(){}load(e,t,s,a,i,n){var r=++this.requestOrder;if(this.table.destroyed)return Promise.resolve();if(this.dispatchExternal("dataLoading",e),e&&(e.indexOf("{")==0||e.indexOf("[")==0)&&(e=JSON.parse(e)),this.confirm("data-loading",[e,t,s,i])){this.loading=!0,i||this.alertLoader(),t=this.chain("data-params",[e,s,i],t||{},t||{}),t=this.mapParams(t,this.table.options.dataSendParams);var o=this.chain("data-load",[e,t,s,i],!1,Promise.resolve([]));return o.then(l=>{if(this.table.destroyed)console.warn("Data Load Response Blocked - Table has been destroyed");else{!Array.isArray(l)&&typeof l=="object"&&(l=this.mapParams(l,this.objectInvert(this.table.options.dataReceiveParams)));var c=this.chain("data-loaded",[l],null,l);r==this.requestOrder?(this.clearAlert(),c!==!1&&(this.dispatchExternal("dataLoaded",c),this.table.rowManager.setData(c,a,typeof n>"u"?!a:n))):console.warn("Data Load Response Blocked - An active data load request was blocked by an attempt to change table data while the request was being made")}}).catch(l=>{console.error("Data Load Error: ",l),this.dispatchExternal("dataLoadError",l),i||this.alertError(),setTimeout(()=>{this.clearAlert()},this.table.options.dataLoaderErrorTimeout)}).finally(()=>{this.loading=!1})}else return this.dispatchExternal("dataLoaded",e),e||(e=[]),this.table.rowManager.setData(e,a,typeof n>"u"?!a:n),Promise.resolve()}mapParams(e,t){var s={};for(let a in e)s[t.hasOwnProperty(a)?t[a]:a]=e[a];return s}objectInvert(e){var t={};for(let s in e)t[e[s]]=s;return t}blockActiveLoad(){this.requestOrder++}alertLoader(){var e=typeof this.table.options.dataLoader=="function"?this.table.options.dataLoader():this.table.options.dataLoader;e&&this.table.alertManager.alert(this.table.options.dataLoaderLoading||this.langText("data|loading"))}alertError(){this.table.alertManager.alert(this.table.options.dataLoaderError||this.langText("data|error"),"error")}clearAlert(){this.table.alertManager.clear()}}class tn{constructor(e,t,s){this.table=e,this.events={},this.optionsList=t||{},this.subscriptionNotifiers={},this.dispatch=s?this._debugDispatch.bind(this):this._dispatch.bind(this),this.debug=s}subscriptionChange(e,t){this.subscriptionNotifiers[e]||(this.subscriptionNotifiers[e]=[]),this.subscriptionNotifiers[e].push(t),this.subscribed(e)&&this._notifySubscriptionChange(e,!0)}subscribe(e,t){this.events[e]||(this.events[e]=[]),this.events[e].push(t),this._notifySubscriptionChange(e,!0)}unsubscribe(e,t){var s;if(this.events[e])if(t)if(s=this.events[e].findIndex(a=>a===t),s>-1)this.events[e].splice(s,1);else{console.warn("Cannot remove event, no matching event found:",e,t);return}else delete this.events[e];else{console.warn("Cannot remove event, no events set on:",e);return}this._notifySubscriptionChange(e,!1)}subscribed(e){return this.events[e]&&this.events[e].length}_notifySubscriptionChange(e,t){var s=this.subscriptionNotifiers[e];s&&s.forEach(a=>{a(t)})}_dispatch(){var e=Array.from(arguments),t=e.shift(),s;return this.events[t]&&this.events[t].forEach((a,i)=>{let n=a.apply(this.table,e);i||(s=n)}),s}_debugDispatch(){var e=Array.from(arguments),t=e[0];return e[0]="ExternalEvent:"+e[0],(this.debug===!0||this.debug.includes(t))&&console.log(...e),this._dispatch(...arguments)}}class sn{constructor(e){this.events={},this.subscriptionNotifiers={},this.dispatch=e?this._debugDispatch.bind(this):this._dispatch.bind(this),this.chain=e?this._debugChain.bind(this):this._chain.bind(this),this.confirm=e?this._debugConfirm.bind(this):this._confirm.bind(this),this.debug=e}subscriptionChange(e,t){this.subscriptionNotifiers[e]||(this.subscriptionNotifiers[e]=[]),this.subscriptionNotifiers[e].push(t),this.subscribed(e)&&this._notifySubscriptionChange(e,!0)}subscribe(e,t,s=1e4){this.events[e]||(this.events[e]=[]),this.events[e].push({callback:t,priority:s}),this.events[e].sort((a,i)=>a.priority-i.priority),this._notifySubscriptionChange(e,!0)}unsubscribe(e,t){var s;if(this.events[e]){if(t)if(s=this.events[e].findIndex(a=>a.callback===t),s>-1)this.events[e].splice(s,1);else{console.warn("Cannot remove event, no matching event found:",e,t);return}}else{console.warn("Cannot remove event, no events set on:",e);return}this._notifySubscriptionChange(e,!1)}subscribed(e){return this.events[e]&&this.events[e].length}_chain(e,t,s,a){var i=s;return Array.isArray(t)||(t=[t]),this.subscribed(e)?(this.events[e].forEach((n,r)=>{i=n.callback.apply(this,t.concat([i]))}),i):typeof a=="function"?a():a}_confirm(e,t){var s=!1;return Array.isArray(t)||(t=[t]),this.subscribed(e)&&this.events[e].forEach((a,i)=>{a.callback.apply(this,t)&&(s=!0)}),s}_notifySubscriptionChange(e,t){var s=this.subscriptionNotifiers[e];s&&s.forEach(a=>{a(t)})}_dispatch(){var e=Array.from(arguments),t=e.shift();this.events[t]&&this.events[t].forEach(s=>{s.callback.apply(this,e)})}_debugDispatch(){var e=Array.from(arguments),t=e[0];return e[0]="InternalEvent:"+t,(this.debug===!0||this.debug.includes(t))&&console.log(...e),this._dispatch(...arguments)}_debugChain(){var e=Array.from(arguments),t=e[0];return e[0]="InternalEvent:"+t,(this.debug===!0||this.debug.includes(t))&&console.log(...e),this._chain(...arguments)}_debugConfirm(){var e=Array.from(arguments),t=e[0];return e[0]="InternalEvent:"+t,(this.debug===!0||this.debug.includes(t))&&console.log(...e),this._confirm(...arguments)}}class an extends j{constructor(e){super(e)}_warnUser(){this.options("debugDeprecation")&&console.warn(...arguments)}check(e,t,s){var a="";return typeof this.options(e)<"u"?(a="Deprecated Setup Option - Use of the %c"+e+"%c option is now deprecated",t?(a=a+", Please use the %c"+t+"%c option instead",this._warnUser(a,"font-weight: bold;","font-weight: normal;","font-weight: bold;","font-weight: normal;"),s&&(this.table.options[t]=this.table.options[e])):this._warnUser(a,"font-weight: bold;","font-weight: normal;"),!1):!0}checkMsg(e,t){return typeof this.options(e)<"u"?(this._warnUser("%cDeprecated Setup Option - Use of the %c"+e+" %c option is now deprecated, "+t,"font-weight: normal;","font-weight: bold;","font-weight: normal;"),!1):!0}msg(e){this._warnUser(e)}}class nn extends j{constructor(e){super(e),this.deps={},this.props={}}initialize(){this.deps=Object.assign({},this.options("dependencies"))}lookup(e,t,s){if(Array.isArray(e)){for(const i of e){var a=this.lookup(i,t,!0);if(a)break}if(a)return a;this.error(e)}else return t?this.lookupProp(e,t,s):this.lookupKey(e,s)}lookupProp(e,t,s){var a;if(this.props[e]&&this.props[e][t])return this.props[e][t];if(a=this.lookupKey(e,s),a)return this.props[e]||(this.props[e]={}),this.props[e][t]=a[t]||a,this.props[e][t]}lookupKey(e,t){var s;return this.deps[e]?s=this.deps[e]:window[e]?(this.deps[e]=window[e],s=this.deps[e]):t||this.error(e),s}error(e){console.error("Unable to find dependency",e,"Please check documentation and ensure you have imported the required library into your project")}}function rn(p,e){e&&this.table.columnManager.renderer.reinitializeColumnWidths(p),this.table.options.responsiveLayout&&this.table.modExists("responsiveLayout",!0)&&this.table.modules.responsiveLayout.update()}function Kt(p,e){p.forEach(function(t){t.reinitializeWidth()}),this.table.options.responsiveLayout&&this.table.modExists("responsiveLayout",!0)&&this.table.modules.responsiveLayout.update()}function on(p,e){var t=0,s=this.table.rowManager.element.clientWidth,a=0,i=!1;p.forEach((n,r)=>{n.widthFixed||n.reinitializeWidth(),(this.table.options.responsiveLayout?n.modules.responsive.visible:n.visible)&&(i=n),n.visible&&(t+=n.getWidth())}),i?(a=s-t+i.getWidth(),this.table.options.responsiveLayout&&this.table.modExists("responsiveLayout",!0)&&(i.setWidth(0),this.table.modules.responsiveLayout.update()),a>0?i.setWidth(a):i.reinitializeWidth()):this.table.options.responsiveLayout&&this.table.modExists("responsiveLayout",!0)&&this.table.modules.responsiveLayout.update()}function ln(p,e){var t=this.table.rowManager.element.getBoundingClientRect().width,s=0,a=0,i=0,n=0,r=[],o=[],l=0,c=0,d=0;function h(f){var m;return typeof f=="string"?f.indexOf("%")>-1?m=t/100*parseInt(f):m=parseInt(f):m=f,m}function u(f,m,b,v){var y=[],$=0,w=0,_=0,k=i,R=0,H=0,q=[];function P(S){return b*(S.column.definition.widthGrow||1)}function J(S){return h(S.width)-b*(S.column.definition.widthShrink||0)}return f.forEach(function(S,Dt){var $e=v?J(S):P(S);S.column.minWidth>=$e?y.push(S):S.column.maxWidth&&S.column.maxWidth<$e?(S.width=S.column.maxWidth,m-=S.column.maxWidth,k-=v?S.column.definition.widthShrink||1:S.column.definition.widthGrow||1,k&&(b=Math.floor(m/k))):(q.push(S),H+=v?S.column.definition.widthShrink||1:S.column.definition.widthGrow||1)}),y.length?(y.forEach(function(S){$+=v?S.width-S.column.minWidth:S.column.minWidth,S.width=S.column.minWidth}),w=m-$,_=H?Math.floor(w/H):w,R=u(q,w,_,v)):(R=H?m-Math.floor(m/H)*H:m,q.forEach(function(S){S.width=v?J(S):P(S)})),R}this.table.options.responsiveLayout&&this.table.modExists("responsiveLayout",!0)&&this.table.modules.responsiveLayout.update(),this.table.rowManager.element.scrollHeight>this.table.rowManager.element.clientHeight&&(t-=this.table.rowManager.element.offsetWidth-this.table.rowManager.element.clientWidth),p.forEach(function(f){var m,b,v;f.visible&&(m=f.definition.width,b=parseInt(f.minWidth),m?(v=h(m),s+=v>b?v:b,f.definition.widthShrink&&(o.push({column:f,width:v>b?v:b}),l+=f.definition.widthShrink)):(r.push({column:f,width:0}),i+=f.definition.widthGrow||1))}),a=t-s,n=Math.floor(a/i),d=u(r,a,n,!1),r.length&&d>0&&(r[r.length-1].width+=d),r.forEach(function(f){a-=f.width}),c=Math.abs(d)+a,c>0&&l&&(d=u(o,c,Math.floor(c/l),!0)),d&&o.length&&(o[o.length-1].width-=d),r.forEach(function(f){f.column.setWidth(f.width)}),o.forEach(function(f){f.column.setWidth(f.width)})}var cn={fitData:rn,fitDataFill:Kt,fitDataTable:Kt,fitDataStretch:on,fitColumns:ln};const ne=class ne extends I{constructor(e){super(e,"layout"),this.mode=null,this.registerTableOption("layout","fitData"),this.registerTableOption("layoutColumnsOnNewData",!1),this.registerColumnOption("widthGrow"),this.registerColumnOption("widthShrink")}initialize(){var e=this.table.options.layout;ne.modes[e]?this.mode=e:(console.warn("Layout Error - invalid mode set, defaulting to 'fitData' : "+e),this.mode="fitData"),this.table.element.setAttribute("tabulator-layout",this.mode),this.subscribe("column-init",this.initializeColumn.bind(this))}initializeColumn(e){e.definition.widthGrow&&(e.definition.widthGrow=Number(e.definition.widthGrow)),e.definition.widthShrink&&(e.definition.widthShrink=Number(e.definition.widthShrink))}getMode(){return this.mode}layout(e){var t=this.table.columnManager.columnsByIndex.find(s=>s.definition.variableHeight||s.definition.formatter==="textarea");this.dispatch("layout-refreshing"),ne.modes[this.mode].call(this,this.table.columnManager.columnsByIndex,e),t&&this.table.rowManager.normalizeHeight(!0),this.dispatch("layout-refreshed")}};g(ne,"moduleName","layout"),g(ne,"modes",cn);let et=ne;var dn={default:{groups:{item:"item",items:"items"},columns:{},data:{loading:"Loading",error:"Error"},pagination:{page_size:"Page Size",page_title:"Show Page",first:"First",first_title:"First Page",last:"Last",last_title:"Last Page",prev:"Prev",prev_title:"Prev Page",next:"Next",next_title:"Next Page",all:"All",counter:{showing:"Showing",of:"of",rows:"rows",pages:"pages"}},headerFilters:{default:"filter column...",columns:{}}}};const we=class we extends I{constructor(e){super(e),this.locale="default",this.lang=!1,this.bindings={},this.langList={},this.registerTableOption("locale",!1),this.registerTableOption("langs",{})}initialize(){this.langList=B.deepClone(we.langs),this.table.options.columnDefaults.headerFilterPlaceholder!==!1&&this.setHeaderFilterPlaceholder(this.table.options.columnDefaults.headerFilterPlaceholder);for(let e in this.table.options.langs)this.installLang(e,this.table.options.langs[e]);this.setLocale(this.table.options.locale),this.registerTableFunction("setLocale",this.setLocale.bind(this)),this.registerTableFunction("getLocale",this.getLocale.bind(this)),this.registerTableFunction("getLang",this.getLang.bind(this))}setHeaderFilterPlaceholder(e){this.langList.default.headerFilters.default=e}installLang(e,t){this.langList[e]?this._setLangProp(this.langList[e],t):this.langList[e]=t}_setLangProp(e,t){for(let s in t)e[s]&&typeof e[s]=="object"?this._setLangProp(e[s],t[s]):e[s]=t[s]}setLocale(e){e=e||"default";function t(s,a){for(var i in s)typeof s[i]=="object"?(a[i]||(a[i]={}),t(s[i],a[i])):a[i]=s[i]}if(e===!0&&navigator.language&&(e=navigator.language.toLowerCase()),e&&!this.langList[e]){let s=e.split("-")[0];this.langList[s]?(console.warn("Localization Error - Exact matching locale not found, using closest match: ",e,s),e=s):(console.warn("Localization Error - Matching locale not found, using default: ",e),e="default")}this.locale=e,this.lang=B.deepClone(this.langList.default||{}),e!="default"&&t(this.langList[e],this.lang),this.dispatchExternal("localized",this.locale,this.lang),this._executeBindings()}getLocale(e){return this.locale}getLang(e){return e?this.langList[e]:this.lang}getText(e,t){var s=t?e+"|"+t:e,a=s.split("|"),i=this._getLangElement(a,this.locale);return i||""}_getLangElement(e,t){var s=this.lang;return e.forEach(function(a){var i;s&&(i=s[a],typeof i<"u"?s=i:s=!1)}),s}bind(e,t){this.bindings[e]||(this.bindings[e]=[]),this.bindings[e].push(t),t(this.getText(e),this.lang)}_executeBindings(){for(let e in this.bindings)this.bindings[e].forEach(t=>{t(this.getText(e),this.lang)})}};g(we,"moduleName","localize"),g(we,"langs",dn);let tt=we;class Jt extends I{constructor(e){super(e)}initialize(){this.registerTableFunction("tableComms",this.receive.bind(this))}getConnections(e){var t=[],s;return s=this.table.constructor.registry.lookupTable(e),s.forEach(a=>{this.table!==a&&t.push(a)}),t}send(e,t,s,a){var i=this.getConnections(e);i.forEach(n=>{n.tableComms(this.table.element,t,s,a)}),!i.length&&e&&console.warn("Table Connection Error - No tables matching selector found",e)}receive(e,t,s,a){if(this.table.modExists(t))return this.table.modules[t].commsReceived(e,s,a);console.warn("Inter-table Comms Error - no such module:",t)}}g(Jt,"moduleName","comms");var pn=Object.freeze({__proto__:null,CommsModule:Jt,LayoutModule:et,LocalizeModule:tt});const F=class F{static findTable(e){var t=F.registry.lookupTable(e,!0);return Array.isArray(t)&&!t.length?!1:t}};g(F,"registry",{tables:[],register(e){F.registry.tables.push(e)},deregister(e){var t=F.registry.tables.indexOf(e);t>-1&&F.registry.tables.splice(t,1)},lookupTable(e,t){var s=[],a,i;if(typeof e=="string"){if(a=document.querySelectorAll(e),a.length)for(var n=0;n<a.length;n++)i=F.registry.matchElement(a[n]),i&&s.push(i)}else typeof HTMLElement<"u"&&e instanceof HTMLElement||e instanceof F?(i=F.registry.matchElement(e),i&&s.push(i)):Array.isArray(e)?e.forEach(function(r){s=s.concat(F.registry.lookupTable(r))}):t||console.warn("Table Connection Error - Invalid Selector",e);return s},matchElement(e){return F.registry.tables.find(function(t){return e instanceof F?t===e:t.element===e})}});let st=F;const T=class T extends st{constructor(){super()}static initializeModuleBinder(e){T.modulesRegistered||(T.modulesRegistered=!0,T._registerModules(pn,!0),e&&T._registerModules(e))}static _extendModule(e,t,s){if(T.moduleBindings[e]){var a=T.moduleBindings[e][t];if(a)if(typeof s=="object")for(let i in s)a[i]=s[i];else console.warn("Module Error - Invalid value type, it must be an object");else console.warn("Module Error - property does not exist:",t)}else console.warn("Module Error - module does not exist:",e)}static _registerModules(e,t){var s=Object.values(e);t&&s.forEach(a=>{a.prototype.moduleCore=!0}),T._registerModule(s)}static _registerModule(e){Array.isArray(e)||(e=[e]),e.forEach(t=>{T._registerModuleBinding(t),T._registerModuleExtensions(t)})}static _registerModuleBinding(e){e.moduleName?T.moduleBindings[e.moduleName]=e:console.error("Unable to bind module, no moduleName defined",e.moduleName)}static _registerModuleExtensions(e){var t=e.moduleExtensions;if(e.moduleExtensions)for(let s in t){let a=t[s];if(T.moduleBindings[s])for(let i in a)T._extendModule(s,i,a[i]);else{T.moduleExtensions[s]||(T.moduleExtensions[s]={});for(let i in a)T.moduleExtensions[s][i]||(T.moduleExtensions[s][i]={}),Object.assign(T.moduleExtensions[s][i],a[i])}}T._extendModuleFromQueue(e)}static _extendModuleFromQueue(e){var t=T.moduleExtensions[e.moduleName];if(t)for(let s in t)T._extendModule(e.moduleName,s,t[s])}_bindModules(){var e=[],t=[],s=[];this.modules={};for(var a in T.moduleBindings){let i=T.moduleBindings[a],n=new i(this);this.modules[a]=n,i.prototype.moduleCore?this.modulesCore.push(n):i.moduleInitOrder?i.moduleInitOrder<0?e.push(n):t.push(n):s.push(n)}e.sort((i,n)=>i.moduleInitOrder>n.moduleInitOrder?1:-1),t.sort((i,n)=>i.moduleInitOrder>n.moduleInitOrder?1:-1),this.modulesRegular=e.concat(s.concat(t))}};g(T,"moduleBindings",{}),g(T,"moduleExtensions",{}),g(T,"modulesRegistered",!1),g(T,"defaultModules",!1);let at=T;class hn extends j{constructor(e){super(e),this.element=this._createAlertElement(),this.msgElement=this._createMsgElement(),this.type=null,this.element.appendChild(this.msgElement)}_createAlertElement(){var e=document.createElement("div");return e.classList.add("tabulator-alert"),e}_createMsgElement(){var e=document.createElement("div");return e.classList.add("tabulator-alert-msg"),e.setAttribute("role","alert"),e}_typeClass(){return"tabulator-alert-state-"+this.type}alert(e,t="msg"){if(e){for(this.clear(),this.dispatch("alert-show",t),this.type=t;this.msgElement.firstChild;)this.msgElement.removeChild(this.msgElement.firstChild);this.msgElement.classList.add(this._typeClass()),typeof e=="function"&&(e=e()),e instanceof HTMLElement?this.msgElement.appendChild(e):this.msgElement.innerHTML=e,this.table.element.appendChild(this.element)}}clear(){this.dispatch("alert-hide",this.type),this.element.parentNode&&this.element.parentNode.removeChild(this.element),this.msgElement.classList.remove(this._typeClass())}}const V=class V extends at{static extendModule(){V.initializeModuleBinder(),V._extendModule(...arguments)}static registerModule(){V.initializeModuleBinder(),V._registerModule(...arguments)}constructor(e,t,s){super(),V.initializeModuleBinder(s),this.options={},this.columnManager=null,this.rowManager=null,this.footerManager=null,this.alertManager=null,this.vdomHoz=null,this.externalEvents=null,this.eventBus=null,this.interactionMonitor=!1,this.browser="",this.browserSlow=!1,this.browserMobile=!1,this.rtl=!1,this.originalElement=null,this.componentFunctionBinder=new Xi(this),this.dataLoader=!1,this.modules={},this.modulesCore=[],this.modulesRegular=[],this.deprecationAdvisor=new an(this),this.optionsList=new Gt(this,"table constructor"),this.dependencyRegistry=new nn(this),this.initialized=!1,this.destroyed=!1,this.initializeElement(e)&&(this.initializeCoreSystems(t),setTimeout(()=>{this._create()})),this.constructor.registry.register(this)}initializeElement(e){return typeof HTMLElement<"u"&&e instanceof HTMLElement?(this.element=e,!0):typeof e=="string"?(this.element=document.querySelector(e),this.element?!0:(console.error("Tabulator Creation Error - no element found matching selector: ",e),!1)):(console.error("Tabulator Creation Error - Invalid element provided:",e),!1)}initializeCoreSystems(e){this.columnManager=new Gi(this),this.rowManager=new Yi(this),this.footerManager=new Qi(this),this.dataLoader=new en(this),this.alertManager=new hn(this),this._bindModules(),this.options=this.optionsList.generate(V.defaultOptions,e),this._clearObjectPointers(),this._mapDeprecatedFunctionality(),this.externalEvents=new tn(this,this.options,this.options.debugEventsExternal),this.eventBus=new sn(this.options.debugEventsInternal),this.interactionMonitor=new Zi(this),this.dataLoader.initialize(),this.footerManager.initialize(),this.dependencyRegistry.initialize()}_mapDeprecatedFunctionality(){}_clearSelection(){this.element.classList.add("tabulator-block-select"),window.getSelection?window.getSelection().empty?window.getSelection().empty():window.getSelection().removeAllRanges&&window.getSelection().removeAllRanges():document.selection&&document.selection.empty(),this.element.classList.remove("tabulator-block-select")}_create(){this.externalEvents.dispatch("tableBuilding"),this.eventBus.dispatch("table-building"),this._rtlCheck(),this._buildElement(),this._initializeTable(),this.initialized=!0,this._loadInitialData().finally(()=>{this.eventBus.dispatch("table-initialized"),this.externalEvents.dispatch("tableBuilt")})}_rtlCheck(){var e=window.getComputedStyle(this.element);switch(this.options.textDirection){case"auto":if(e.direction!=="rtl")break;case"rtl":this.element.classList.add("tabulator-rtl"),this.rtl=!0;break;case"ltr":this.element.classList.add("tabulator-ltr");default:this.rtl=!1}}_clearObjectPointers(){this.options.columns=this.options.columns.slice(0),Array.isArray(this.options.data)&&!this.options.reactiveData&&(this.options.data=this.options.data.slice(0))}_buildElement(){var e=this.element,t=this.options,s;if(e.tagName==="TABLE"){this.originalElement=this.element,s=document.createElement("div");var a=e.attributes;for(var i in a)typeof a[i]=="object"&&s.setAttribute(a[i].name,a[i].value);e.parentNode.replaceChild(s,e),this.element=e=s}for(e.classList.add("tabulator"),e.setAttribute("role","grid"),e.setAttribute("aria-owns","tabulator-table-body");e.firstChild;)e.removeChild(e.firstChild);t.height&&(t.height=isNaN(t.height)?t.height:t.height+"px",e.style.height=t.height),t.minHeight!==!1&&(t.minHeight=isNaN(t.minHeight)?t.minHeight:t.minHeight+"px",e.style.minHeight=t.minHeight),t.maxHeight!==!1&&(t.maxHeight=isNaN(t.maxHeight)?t.maxHeight:t.maxHeight+"px",e.style.maxHeight=t.maxHeight)}_initializeTable(){var e=this.element,t=this.options;this.interactionMonitor.initialize(),this.columnManager.initialize(),this.rowManager.initialize(),this._detectBrowser(),this.modulesCore.forEach(s=>{s.initialize()}),e.appendChild(this.columnManager.getElement()),e.appendChild(this.rowManager.getElement()),t.footerElement&&this.footerManager.activate(),t.autoColumns&&t.data&&this.columnManager.generateColumnsFromRowData(this.options.data),this.modulesRegular.forEach(s=>{s.initialize()}),this.columnManager.setColumns(t.columns),this.eventBus.dispatch("table-built")}_loadInitialData(){return this.dataLoader.load(this.options.data).finally(()=>{this.columnManager.verticalAlignHeaders()})}destroy(){var e=this.element;for(this.destroyed=!0,this.constructor.registry.deregister(this),this.eventBus.dispatch("table-destroy"),this.rowManager.destroy();e.firstChild;)e.removeChild(e.firstChild);e.classList.remove("tabulator"),e.removeAttribute("tabulator-layout"),this.externalEvents.dispatch("tableDestroyed")}_detectBrowser(){var e=navigator.userAgent||navigator.vendor||window.opera;e.indexOf("Trident")>-1?(this.browser="ie",this.browserSlow=!0):e.indexOf("Edge")>-1?(this.browser="edge",this.browserSlow=!0):e.indexOf("Firefox")>-1?(this.browser="firefox",this.browserSlow=!1):e.indexOf("Mac OS")>-1?(this.browser="safari",this.browserSlow=!1):(this.browser="other",this.browserSlow=!1),this.browserMobile=/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino|android|ipad|playbook|silk/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55\/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|_)|g1 u|g560|gene|gf-5|g-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk\/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(e.slice(0,4))}initGuard(e,t){var s,a;return this.options.debugInitialization&&!this.initialized&&(e||(s=new Error().stack.split(`
`),a=s[0]=="Error"?s[2]:s[1],a[0]==" "?e=a.trim().split(" ")[1].split(".")[1]:e=a.trim().split("@")[0]),console.warn("Table Not Initialized - Calling the "+e+" function before the table is initialized may result in inconsistent behavior, Please wait for the `tableBuilt` event before calling this function."+(t?" "+t:""))),this.initialized}blockRedraw(){this.initGuard(),this.eventBus.dispatch("redraw-blocking"),this.rowManager.blockRedraw(),this.columnManager.blockRedraw(),this.eventBus.dispatch("redraw-blocked")}restoreRedraw(){this.initGuard(),this.eventBus.dispatch("redraw-restoring"),this.rowManager.restoreRedraw(),this.columnManager.restoreRedraw(),this.eventBus.dispatch("redraw-restored")}setData(e,t,s){return this.initGuard(!1,"To set initial data please use the 'data' property in the table constructor."),this.dataLoader.load(e,t,s,!1)}clearData(){this.initGuard(),this.dataLoader.blockActiveLoad(),this.rowManager.clearData()}getData(e){return this.rowManager.getData(e)}getDataCount(e){return this.rowManager.getDataCount(e)}replaceData(e,t,s){return this.initGuard(),this.dataLoader.load(e,t,s,!0,!0)}updateData(e){var t=0;return this.initGuard(),new Promise((s,a)=>{this.dataLoader.blockActiveLoad(),typeof e=="string"&&(e=JSON.parse(e)),e&&e.length>0?e.forEach(i=>{var n=this.rowManager.findRow(i[this.options.index]);n?(t++,n.updateData(i).then(()=>{t--,t||s()}).catch(r=>{a("Update Error - Unable to update row",i,r)})):a("Update Error - Unable to find row",i)}):(console.warn("Update Error - No data provided"),a("Update Error - No data provided"))})}addData(e,t,s){return this.initGuard(),new Promise((a,i)=>{this.dataLoader.blockActiveLoad(),typeof e=="string"&&(e=JSON.parse(e)),e?this.rowManager.addRows(e,t,s).then(n=>{var r=[];n.forEach(function(o){r.push(o.getComponent())}),a(r)}):(console.warn("Update Error - No data provided"),i("Update Error - No data provided"))})}updateOrAddData(e){var t=[],s=0;return this.initGuard(),new Promise((a,i)=>{this.dataLoader.blockActiveLoad(),typeof e=="string"&&(e=JSON.parse(e)),e&&e.length>0?e.forEach(n=>{var r=this.rowManager.findRow(n[this.options.index]);s++,r?r.updateData(n).then(()=>{s--,t.push(r.getComponent()),s||a(t)}):this.rowManager.addRows(n).then(o=>{s--,t.push(o[0].getComponent()),s||a(t)})}):(console.warn("Update Error - No data provided"),i("Update Error - No data provided"))})}getRow(e){var t=this.rowManager.findRow(e);return t?t.getComponent():(console.warn("Find Error - No matching row found:",e),!1)}getRowFromPosition(e){var t=this.rowManager.getRowFromPosition(e);return t?t.getComponent():(console.warn("Find Error - No matching row found:",e),!1)}deleteRow(e){var t=[];this.initGuard(),Array.isArray(e)||(e=[e]);for(let s of e){let a=this.rowManager.findRow(s,!0);if(a)t.push(a);else return console.error("Delete Error - No matching row found:",s),Promise.reject("Delete Error - No matching row found")}return t.sort((s,a)=>this.rowManager.rows.indexOf(s)>this.rowManager.rows.indexOf(a)?1:-1),t.forEach(s=>{s.delete()}),this.rowManager.reRenderInPosition(),Promise.resolve()}addRow(e,t,s){return this.initGuard(),typeof e=="string"&&(e=JSON.parse(e)),this.rowManager.addRows(e,t,s,!0).then(a=>a[0].getComponent())}updateOrAddRow(e,t){var s=this.rowManager.findRow(e);return this.initGuard(),typeof t=="string"&&(t=JSON.parse(t)),s?s.updateData(t).then(()=>s.getComponent()):this.rowManager.addRows(t).then(a=>a[0].getComponent())}updateRow(e,t){var s=this.rowManager.findRow(e);return this.initGuard(),typeof t=="string"&&(t=JSON.parse(t)),s?s.updateData(t).then(()=>Promise.resolve(s.getComponent())):(console.warn("Update Error - No matching row found:",e),Promise.reject("Update Error - No matching row found"))}scrollToRow(e,t,s){var a=this.rowManager.findRow(e);return a?this.rowManager.scrollToRow(a,t,s):(console.warn("Scroll Error - No matching row found:",e),Promise.reject("Scroll Error - No matching row found"))}moveRow(e,t,s){var a=this.rowManager.findRow(e);this.initGuard(),a?a.moveToRow(t,s):console.warn("Move Error - No matching row found:",e)}getRows(e){return this.rowManager.getComponents(e)}getRowPosition(e){var t=this.rowManager.findRow(e);return t?t.getPosition():(console.warn("Position Error - No matching row found:",e),!1)}setColumns(e){this.initGuard(!1,"To set initial columns please use the 'columns' property in the table constructor"),this.columnManager.setColumns(e)}getColumns(e){return this.columnManager.getComponents(e)}getColumn(e){var t=this.columnManager.findColumn(e);return t?t.getComponent():(console.warn("Find Error - No matching column found:",e),!1)}getColumnDefinitions(){return this.columnManager.getDefinitionTree()}showColumn(e){var t=this.columnManager.findColumn(e);if(this.initGuard(),t)t.show();else return console.warn("Column Show Error - No matching column found:",e),!1}hideColumn(e){var t=this.columnManager.findColumn(e);if(this.initGuard(),t)t.hide();else return console.warn("Column Hide Error - No matching column found:",e),!1}toggleColumn(e){var t=this.columnManager.findColumn(e);if(this.initGuard(),t)t.visible?t.hide():t.show();else return console.warn("Column Visibility Toggle Error - No matching column found:",e),!1}addColumn(e,t,s){var a=this.columnManager.findColumn(s);return this.initGuard(),this.columnManager.addColumn(e,t,a).then(i=>i.getComponent())}deleteColumn(e){var t=this.columnManager.findColumn(e);return this.initGuard(),t?t.delete():(console.warn("Column Delete Error - No matching column found:",e),Promise.reject())}updateColumnDefinition(e,t){var s=this.columnManager.findColumn(e);return this.initGuard(),s?s.updateDefinition(t):(console.warn("Column Update Error - No matching column found:",e),Promise.reject())}moveColumn(e,t,s){var a=this.columnManager.findColumn(e),i=this.columnManager.findColumn(t);this.initGuard(),a?i?this.columnManager.moveColumn(a,i,s):console.warn("Move Error - No matching column found:",i):console.warn("Move Error - No matching column found:",e)}scrollToColumn(e,t,s){return new Promise((a,i)=>{var n=this.columnManager.findColumn(e);return n?this.columnManager.scrollToColumn(n,t,s):(console.warn("Scroll Error - No matching column found:",e),Promise.reject("Scroll Error - No matching column found"))})}redraw(e){this.initGuard(),this.columnManager.redraw(e),this.rowManager.redraw(e)}setHeight(e){this.options.height=isNaN(e)?e:e+"px",this.element.style.height=this.options.height,this.rowManager.initializeRenderer(),this.rowManager.redraw(!0)}setMaxHeight(e){this.options.maxHeight=isNaN(e)?e:e+"px",this.element.style.maxHeight=this.options.maxHeight,this.rowManager.initializeRenderer(),this.rowManager.redraw(!0)}setMinHeight(e){this.options.minHeight=isNaN(e)?e:e+"px",this.element.style.minHeight=this.options.minHeight,this.rowManager.initializeRenderer(),this.rowManager.redraw(!0)}on(e,t){this.externalEvents.subscribe(e,t)}off(e,t){this.externalEvents.unsubscribe(e,t)}dispatchEvent(){var e=Array.from(arguments);e.shift(),this.externalEvents.dispatch(...arguments)}alert(e,t){this.initGuard(),this.alertManager.alert(e,t)}clearAlert(){this.initGuard(),this.alertManager.clear()}modExists(e,t){return this.modules[e]?!0:(t&&console.error("Tabulator Module Not Installed: "+e),!1)}module(e){var t=this.modules[e];return t||console.error("Tabulator module not installed: "+e),t}};g(V,"defaultOptions",Vi);let se=V;se.registerModule([Ye,Re,Ce,Me,Ze,Le,Te,Qe]);class Yt extends C{constructor(e={}){super(e),this.api=e.api,this.table=null,this._stylesInjected=!1,this.editModalElement=null,this.currentEditingUser=null,this.currentEditingRow=null}async render(e){await super.render(e);const t=this.ref("body");return t.innerHTML=`
            <div class="users-wrapper">

                <div class="users-toolbar">
                    <button class="btn-add">Add</button>
                    <button class="btn-delete">Delete</button>
                    <button class="btn-refresh">Refresh</button>
                    <input class="users-search" type="text" placeholder="Search...">
                </div>

                <div class="users-table users-cards-container"></div>

            </div>
        `,this._ensureEditModal(t),this.initTable(),this.bindEvents(),this}initTable(){const e=this.ref("body").querySelector(".users-table"),t=window.matchMedia("(max-width: 768px)").matches;this.table=new se(e,{height:t?void 0:520,layout:"fitData",headerVisible:!1,pagination:!0,paginationMode:"remote",paginationSize:10,ajaxURL:"/users",ajaxRequestFunc:async(s,a,i)=>{const n=i.page||1,r=i.size||10,o=i.search||"";if(!this.api||typeof this.api.get!="function")throw console.error("UsersListView: api client is missing or invalid",this.api),new Error("ApiClient is not available in UsersListView");const l=await this.api.get("users",{page:n,size:r,search:o});return{data:Array.isArray(l.data)?l.data:[],last_page:l.last_page??1}},ajaxParams:{size:10},selectableRows:1,columns:[{title:"ID",field:"id",sorter:"number",visible:!1},{title:"Username",field:"username",editor:"input"},{title:"Full Name",field:"fullname",editor:"input"},{title:"Email",field:"email",editor:"input"},{title:"Roles",field:"roles"},{title:"Delete",field:"delete",formatter:()=>"🗑",width:80,hozAlign:"center",visible:!1}],rowFormatter:s=>{const a=s.getData(),i=s.getElement();i.innerHTML="",i.classList.add("user-card-row");const n=Array.isArray(a.roles)?a.roles.map(d=>typeof d=="string"?d:d.name||"").filter(Boolean):[],r=n.length?n.join(", "):"No roles",o=document.createElement("div");o.className="user-card",o.innerHTML=`
                    <div class="user-card-header">
                        <div class="user-card-avatar">
                            ${a.fullname?a.fullname.charAt(0).toUpperCase():"U"}
                        </div>
                        <div class="user-card-title">
                            <div class="user-card-fullname">${a.fullname||"(no name)"}</div>
                            <div class="user-card-username">@${a.username||""}</div>
                        </div>
                    </div>

                    <div class="user-card-body">
                        <div class="user-card-row-item">
                            <span class="label">Email:</span>
                            <span class="value">${a.email||"-"}</span>
                        </div>
                        <div class="user-card-row-item">
                            <span class="label">Roles:</span>
                            <span class="value">${r}</span>
                        </div>
                    </div>

                    <div class="user-card-footer">
                        <button type="button" class="btn-card-edit">Edit</button>
                        <button type="button" class="btn-card-delete">Delete</button>
                    </div>
                `;const l=o.querySelector(".btn-card-edit"),c=o.querySelector(".btn-card-delete");l&&l.addEventListener("click",()=>{console.log("Edit user:",a),this._openEditModal(a,s)}),c&&c.addEventListener("click",()=>{confirm(`Delete user ${a.username}?`)&&s.delete()}),i.appendChild(o)},cellEdited:s=>{const a=s.getRow().getData();console.log("updated",a)}})}bindEvents(){const e=this.ref("body"),t=e.querySelector(".btn-add"),s=e.querySelector(".btn-delete"),a=e.querySelector(".btn-refresh"),i=e.querySelector(".users-search");t==null||t.addEventListener("click",()=>{const n={id:Date.now(),username:"new_user",fullname:"New User",email:"test@email.com",roles:[]};this.table.addRow(n,!0)}),s==null||s.addEventListener("click",()=>{const n=this.table.getSelectedRows()[0];if(!n){alert("Select a user");return}const r=n.getData();confirm(`Delete selected user ${r.username}?`)&&n.delete()}),a==null||a.addEventListener("click",()=>{this.table.replaceData()}),i==null||i.addEventListener("input",n=>{const r=n.target.value||"";this.table.setData(null,{search:r})})}_ensureEditModal(e){if(this.editModalElement)return;const t=document.createElement("div");t.className="user-edit-modal-backdrop",t.innerHTML=`
            <div class="user-edit-modal">
                <div class="user-edit-modal-header">
                    <h3>Edit User</h3>
                    <button type="button" class="user-edit-modal-close">&times;</button>
                </div>
                <div class="user-edit-modal-body">
                    <form class="user-edit-form">
                        <div class="form-group">
                            <label>Username</label>
                            <input name="username" type="text" class="form-control" />
                        </div>
                        <div class="form-group">
                            <label>Full Name</label>
                            <input name="fullname" type="text" class="form-control" />
                        </div>
                        <div class="form-group">
                            <label>Email</label>
                            <input name="email" type="email" class="form-control" />
                        </div>
                        <!-- در صورت نیاز، فیلد نقش‌ها یا موارد دیگر را هم اضافه کن -->

                        <div class="user-edit-modal-footer">
                            <button type="button" class="btn btn-secondary user-edit-cancel">Cancel</button>
                            <button type="submit" class="btn btn-primary">Save</button>
                        </div>
                    </form>
                </div>
            </div>
        `,e.appendChild(t),this.editModalElement=t,this._bindEditModalEvents(),this._injectEditModalStyles()}_bindEditModalEvents(){const e=this.editModalElement;if(!e)return;const t=e.querySelector(".user-edit-form"),s=e.querySelector(".user-edit-modal-close"),a=e.querySelector(".user-edit-cancel");s==null||s.addEventListener("click",()=>this._closeEditModal()),a==null||a.addEventListener("click",()=>this._closeEditModal()),t==null||t.addEventListener("submit",async i=>{if(i.preventDefault(),!this.currentEditingRow||!this.currentEditingUser){console.warn("No current editing user/row");return}const n=new FormData(t),r={...this.currentEditingUser,username:n.get("username"),fullname:n.get("fullname"),email:n.get("email")};try{if(!this.api)throw new Error("ApiClient not available");await this.api.request("PUT",`users/${this.currentEditingUser.id}`,r),this.currentEditingRow.update(r),this._closeEditModal()}catch(o){console.error("Failed to update user",o),alert("Failed to update user")}})}_openEditModal(e,t){this.currentEditingUser=e,this.currentEditingRow=t;const s=this.editModalElement;if(!s)return;const a=s.querySelector(".user-edit-form");a&&(a.elements.username.value=e.username||"",a.elements.fullname.value=e.fullname||"",a.elements.email.value=e.email||"",s.classList.add("is-open"))}_closeEditModal(){const e=this.editModalElement;e&&(e.classList.remove("is-open"),this.currentEditingUser=null,this.currentEditingRow=null)}_injectEditModalStyles(){if(this._stylesInjected)return;const e=document.createElement("style");e.textContent=`
            .user-edit-modal-backdrop {
                position: fixed;
                inset: 0;
                background: rgba(0, 0, 0, 0.4);
                display: none;
                align-items: center;
                justify-content: center;
                z-index: 9999;
            }

            .user-edit-modal-backdrop.is-open {
                display: flex;
            }

            .user-edit-modal {
                background: #fff;
                padding: 16px 20px;
                border-radius: 6px;
                min-width: 320px;
                max-width: 480px;
                box-shadow: 0 4px 16px rgba(0, 0, 0, 0.2);
            }

            .user-edit-modal-header {
                display: flex;
                justify-content: space-between;
                align-items: center;
                margin-bottom: 10px;
            }

            .user-edit-modal-header h3 {
                margin: 0;
                font-size: 18px;
            }

            .user-edit-modal-close {
                border: none;
                background: transparent;
                font-size: 20px;
                cursor: pointer;
            }

            .user-edit-modal-body .form-group {
                margin-bottom: 10px;
            }

            .user-edit-modal-body label {
                display: block;
                margin-bottom: 4px;
                font-size: 13px;
                font-weight: 600;
            }

            .user-edit-modal-body .form-control {
                width: 100%;
                box-sizing: border-box;
                padding: 6px 8px;
                border-radius: 4px;
                border: 1px solid #ccc;
                font-size: 13px;
            }

            .user-edit-modal-footer {
                display: flex;
                justify-content: flex-end;
                gap: 8px;
                margin-top: 12px;
            }

            .user-edit-modal-footer .btn {
                padding: 6px 12px;
                font-size: 13px;
                cursor: pointer;
                border-radius: 4px;
                border: 1px solid transparent;
            }

            .user-edit-modal-footer .btn-primary {
                background-color: #007bff;
                border-color: #007bff;
                color: #fff;
            }

            .user-edit-modal-footer .btn-secondary {
                background-color: #f0f0f0;
                border-color: #ccc;
                color: #333;
            }
        `,document.head.appendChild(e),this._stylesInjected=!0}destroy(){var e,t;(e=this.table)==null||e.destroy(),this.table=null,(t=this.editModalElement)!=null&&t.parentNode&&this.editModalElement.parentNode.removeChild(this.editModalElement),this.editModalElement=null,this.currentEditingUser=null,this.currentEditingRow=null,super.destroy()}}g(Yt,"title","Users"),E.register("users",Yt);class un extends C{constructor(e={}){super(e),this.apiUrl=e.apiUrl||"/wp-json/acc/v1/trrc/tree"}getTitle(){return"نمایش درختی"}template(){return`
            <div class="tree-view-container">
                <h2 class="view-title">🌳 نمایش ساختار درختی</h2>

                <div class="tree-view-content">
                    <div id="tree-root"
                         class="trrc-root"
                         data-module="trrc"
                         data-source="api"
                         data-api="${this.apiUrl}">
                    </div>
                </div>
            </div>
        `}afterRender(){this.mountTRRC()}bindEvents(){super.bindEvents()}mountTRRC(){var s,a,i,n,r;if(!this.container)return;const e=this.container.querySelector('[data-module="trrc"]');if(!e)return;if(!((a=(s=window.ACC)==null?void 0:s.modules)!=null&&a.trrc)){console.warn("TRRC module is not loaded");return}if(e.__trrcMounted)return;e.__trrcMounted=!0;const t=ACC.modules.trrc;try{if(typeof t=="function"){const o=t(e);(i=o==null?void 0:o.mount)==null||i.call(o);return}if(typeof t.mount=="function"){t.mount(e,{apiUrl:e.dataset.api,tab:this.tab});return}if(typeof t.init=="function"){const o=t.init({el:e,apiUrl:e.dataset.api});(n=o==null?void 0:o.mount)==null||n.call(o);return}if(t.App){const o=new t.App({el:e,apiUrl:e.dataset.api});(r=o==null?void 0:o.mount)==null||r.call(o);return}console.error("ACC.modules.trrc has unsupported shape:",t)}catch(o){console.error("Failed to mount TRRC:",o)}}destroy(){var e;(e=super.destroy)==null||e.call(this)}}E.register("tree",un);class x{constructor({eventBus:e,store:t,tab:s,api:a}={}){this.eventBus=e??null,this.store=t??null,this.tab=s??null,this.api=a??null,this.container=null,this.refs={},this.boundEvents=[],this.busEvents=[],this.isDestroyed=!1}async render(e){if(!e)return this;this.container=e,typeof this.beforeRender=="function"&&await this.beforeRender();const t=await this.template();e.innerHTML=t??"",this._bindRefs(),typeof this.afterRender=="function"&&await this.afterRender();try{this.applyAclToDom()}catch{}return this}can(e,t=null,s=null){return L.can(e,t,s)}cannot(e,t=null,s=null){return!L.can(e,t,s)}applyAclToDom(e=null){const t=e||this.container;t&&t.querySelectorAll("[data-perm]").forEach(s=>{const a=s.dataset.perm;if(!a||L.can(a))return;(s.dataset.permMode||"hide")==="disable"?(s.setAttribute("disabled","disabled"),s.style.opacity="0.5",s.style.cursor="not-allowed",s.title="🚫 دسترسی ندارید"):s.style.display="none"})}async template(){return""}_bindRefs(){this.refs={},this.container&&this.container.querySelectorAll("[data-ref]").forEach(e=>{e.dataset.ref&&(this.refs[e.dataset.ref]=e)})}ref(e){return this.refs[e]??null}on(e,t,s){!e||!t||!s||(e.addEventListener(t,s),this.boundEvents.push({element:e,event:t,handler:s}))}listen(e,t){if(!this.eventBus)return;const s=this.eventBus.on(e,t);s&&this.busEvents.push(s)}destroy(){this.isDestroyed||(this.boundEvents.forEach(({element:e,event:t,handler:s})=>{try{e.removeEventListener(t,s)}catch{}}),this.busEvents.forEach(e=>{try{typeof e=="function"&&e()}catch{}}),this.boundEvents=[],this.busEvents=[],this.refs={},this.container=null,this.isDestroyed=!0)}escape(e){return e==null?"":String(e).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}}const oe={office:{label:"دفتر",icon:"🏢",color:"#3b82f6"},warehouse:{label:"انبار",icon:"🏭",color:"#f59e0b"},home:{label:"منزل",icon:"🏠",color:"#10b981"},site:{label:"محل پروژه",icon:"🏗️",color:"#ef4444"},meeting:{label:"محل ملاقات",icon:"📍",color:"#8b5cf6"},branch:{label:"شعبه",icon:"🏪",color:"#06b6d4"},factory:{label:"کارخانه",icon:"🏭",color:"#dc2626"},other:{label:"سایر",icon:"📍",color:"#64748b"}};class z{constructor(e={}){this.api=e.api,this.entityType=e.entityType,this.entityId=e.entityId,this.entityName=e.entityName??"",this.onSaved=e.onSaved??(()=>{}),this.onChange=e.onChange??(()=>{}),this._locations=[],this._map=null,this._markers=[],this._activePin=null,this._container=null}static openModal(e){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:780px;max-height:92vh;overflow:hidden;display:flex;flex-direction:column;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">📍 موقعیت‌های ${z._esc(e.entityName||"")}</div>
            <div data-ref-picker style="flex:1;min-height:500px;"></div>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.addEventListener("click",i=>{i.target===t&&s()});const a=new z({...e,onSaved:i=>{var n;(n=e.onSaved)==null||n.call(e,i)}});return a.render(t.querySelector("[data-ref-picker]")),a}async render(e){e&&(this._container=e,e.innerHTML=`
        <div style="display:grid;grid-template-columns:280px 1fr;gap:12px;height:100%;min-height:450px;">

            <!-- لیست موقعیت‌ها -->
            <div style="display:flex;flex-direction:column;gap:8px;overflow-y:auto;">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref-pk="addBtn">➕ موقعیت جدید</button>
                <div data-ref-pk="list" style="display:flex;flex-direction:column;gap:6px;"></div>
            </div>

            <!-- نقشه -->
            <div data-ref-pk="map" style="border:1px solid #cbd5e1;border-radius:8px;min-height:450px;position:relative;background:#f8fafc;">
                <div data-ref-pk="loading" style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;color:#64748b;font-size:12px;">⏳ بارگذاری نقشه...</div>
            </div>
        </div>`,await this._loadLeaflet(),this._initMap(),await this._load(),e.querySelector('[data-ref-pk="addBtn"]').addEventListener("click",()=>this._openForm()))}async _loadLeaflet(){var s;if(window.L)return;const e=(((s=window.ACC_CONFIG)==null?void 0:s.pluginUrl)??"").replace(/\/+$/,""),t=e?`${e}/assets/vendor/leaflet`:"/wp-content/plugins/acc-engine/assets/vendor/leaflet";if(!document.querySelector('link[href*="leaflet"]')){const a=document.createElement("link");a.rel="stylesheet",a.href=`${t}/leaflet.css`,document.head.appendChild(a)}window.L||await new Promise((a,i)=>{const n=document.createElement("script");n.src=`${t}/leaflet.js`,n.onload=a,n.onerror=i,document.head.appendChild(n)})}_initMap(){var i;const e=window.L,t=this._container.querySelector('[data-ref-pk="map"]'),s=this._container.querySelector('[data-ref-pk="loading"]');s.style.display="none",this._map=e.map(t,{zoomControl:!0}).setView([29.5926,52.5836],13);const a=(((i=window.ACC_CONFIG)==null?void 0:i.pluginUrl)??"").replace(/\/+$/,"");e.tileLayer(`${a||"/wp-content/plugins/acc-engine"}/assets/vendor/leaflet/tiles_esri/{z}/{x}/{y}.png`,{attribution:"© Esri",minZoom:10,maxZoom:19,maxNativeZoom:16}).addTo(this._map),this._map.on("click",n=>this._openForm(null,n.latlng.lat,n.latlng.lng))}async _load(){try{const e=await this.api.get("/gis/locations",{entity_type:this.entityType,entity_id:this.entityId});this._locations=(e==null?void 0:e.data)??[],this._renderList(),this._renderMarkers(),this.onChange(this._locations)}catch{this._container.querySelector('[data-ref-pk="list"]').innerHTML='<div style="color:#ef4444;font-size:12px;padding:8px;">❌ خطا در بارگذاری</div>'}}_renderList(){const e=this._container.querySelector('[data-ref-pk="list"]');if(!this._locations.length){e.innerHTML=`
                <div style="color:#64748b;font-size:12px;padding:16px;text-align:center;background:#f8fafc;border-radius:8px;">
                    موقعیتی ثبت نشده.<br>
                    <small>روی نقشه کلیک کنید یا دکمه بالا را بزنید.</small>
                </div>`;return}e.innerHTML=this._locations.map(t=>{const s=oe[t.location_type]??oe.other;return`
            <div class="loc-item" data-loc-id="${t.id}" style="border:1.5px solid ${t.is_primary==1?s.color:"#e2e8f0"};border-radius:8px;padding:8px 10px;cursor:pointer;background:#fff;">
                <div style="display:flex;justify-content:space-between;align-items:start;gap:4px;">
                    <div style="flex:1;min-width:0;">
                        <div style="font-size:12px;font-weight:700;color:${s.color};">
                            ${s.icon} ${z._esc(t.label||s.label)}
                            ${t.is_primary==1?'<span style="background:'+s.color+';color:#fff;border-radius:3px;padding:0 4px;font-size:10px;margin-right:3px;">اصلی</span>':""}
                        </div>
                        ${t.address?`<div style="font-size:11px;color:#64748b;margin-top:3px;line-height:1.4;">${z._esc(t.address)}</div>`:""}
                        ${t.parcel_code?`<div style="font-size:10px;color:#3b82f6;margin-top:2px;">🔗 پارسل ${z._esc(t.parcel_code)}</div>`:""}
                    </div>
                    <div style="display:flex;flex-direction:column;gap:2px;">
                        <button class="loc-edit" style="background:none;border:none;cursor:pointer;font-size:11px;">✏️</button>
                        <button class="loc-del" style="background:none;border:none;cursor:pointer;font-size:11px;color:#ef4444;">🗑️</button>
                    </div>
                </div>
            </div>`}).join(""),e.querySelectorAll(".loc-item").forEach(t=>{const s=parseInt(t.dataset.locId),a=this._locations.find(i=>i.id==s);t.addEventListener("click",i=>{i.target.closest(".loc-edit")||i.target.closest(".loc-del")||this._focusOnMap(a)}),t.querySelector(".loc-edit").addEventListener("click",i=>{i.stopPropagation(),this._openForm(a)}),t.querySelector(".loc-del").addEventListener("click",async i=>{if(i.stopPropagation(),!!confirm("حذف این موقعیت؟"))try{await this.api.delete(`/gis/locations/${s}`),this._load()}catch(n){alert("خطا: "+((n==null?void 0:n.message)??""))}})})}_renderMarkers(){const e=window.L;this._markers.forEach(s=>this._map.removeLayer(s)),this._markers=[];const t=[];this._locations.forEach(s=>{if(!s.lat||!s.lng)return;const a=oe[s.location_type]??oe.other,i=parseFloat(s.lat),n=parseFloat(s.lng),r=e.marker([i,n],{title:s.label||a.label,icon:e.divIcon({className:"",iconSize:[28,28],html:`<div style="background:${a.color};color:#fff;border-radius:50%;width:28px;height:28px;display:flex;align-items:center;justify-content:center;border:2px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,.3);font-size:14px;">${a.icon}</div>`})});r.bindTooltip(`<b>${z._esc(s.label||a.label)}</b>${s.address?"<br>"+z._esc(s.address):""}`,{direction:"top"}),r.on("click",()=>this._openForm(s)),r.addTo(this._map),this._markers.push(r),t.push([i,n])}),t.length&&this._map.fitBounds(t,{padding:[40,40],maxZoom:16})}_focusOnMap(e){!(e!=null&&e.lat)||!(e!=null&&e.lng)||this._map.setView([parseFloat(e.lat),parseFloat(e.lng)],17,{animate:!0})}_openForm(e=null,t=null,s=null){const a=!!e,i=Object.entries(oe).map(([o,l])=>`<option value="${o}" ${(e==null?void 0:e.location_type)===o?"selected":""}>${l.icon} ${l.label}</option>`).join(""),n=document.createElement("div");n.className="acc-modal-overlay",n.style.zIndex="10000",n.innerHTML=`
        <div class="acc-modal" style="max-width:440px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${a?"✏️ ویرایش موقعیت":"➕ موقعیت جدید"}</div>
            <form>
                <div class="acc-form-group"><label>برچسب</label>
                    <input name="label" value="${z._esc((e==null?void 0:e.label)??"")}" placeholder="مثلاً: دفتر مرکزی">
                </div>
                <div class="acc-form-group"><label>نوع</label>
                    <select name="location_type">${i}</select>
                </div>
                <div class="acc-form-group"><label>آدرس</label>
                    <textarea name="address" rows="2">${z._esc((e==null?void 0:e.address)??"")}</textarea>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>عرض (lat)</label>
                        <input name="lat" type="number" step="any" required value="${(e==null?void 0:e.lat)??t??""}" dir="ltr">
                    </div>
                    <div class="acc-form-group"><label>طول (lng)</label>
                        <input name="lng" type="number" step="any" required value="${(e==null?void 0:e.lng)??s??""}" dir="ltr">
                    </div>
                </div>
                <div class="acc-form-group"><label>اتصال به پارسل GIS (اختیاری)</label>
                    <input name="parcel_id" type="number" placeholder="ID پارسل" value="${(e==null?void 0:e.parcel_id)??""}">
                    <small style="color:#94a3b8;font-size:11px;">اگر این موقعیت یک پارسل ثبت‌شده است، ID آن را وارد کن</small>
                </div>
                <label style="display:flex;gap:6px;align-items:center;font-size:13px;margin:10px 0;">
                    <input type="checkbox" name="is_primary" value="1" ${(e==null?void 0:e.is_primary)==1?"checked":""}> ⭐ موقعیت اصلی
                </label>
                <div class="acc-form-group"><label>یادداشت</label>
                    <input name="notes" value="${z._esc((e==null?void 0:e.notes)??"")}">
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector("[data-action=cancel]").addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()}),n.querySelector("form").addEventListener("submit",async o=>{o.preventDefault();const l=Object.fromEntries(new FormData(o.target).entries());l.entity_type=this.entityType,l.entity_id=this.entityId,l.is_primary=l.is_primary?1:0,l.parcel_id||delete l.parcel_id;const c=o.target.querySelector("[type=submit]");c.disabled=!0;try{a?await this.api.put(`/gis/locations/${e.id}`,l):await this.api.post("/gis/locations",l),r(),await this._load(),this.onSaved(this._locations)}catch(d){alert("خطا: "+((d==null?void 0:d.message)??"")),c.disabled=!1}})}static _esc(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}}const fn={planned:{label:"برنامه‌ریزی",color:"#6366f1",bg:"#eef2ff"},active:{label:"فعال",color:"#059669",bg:"#ecfdf5"},on_hold:{label:"متوقف",color:"#d97706",bg:"#fffbeb"},completed:{label:"تکمیل‌شده",color:"#0284c7",bg:"#e0f2fe"},cancelled:{label:"لغو‌شده",color:"#dc2626",bg:"#fef2f2"}},mn={construction:"ساختمانی",software:"نرم‌افزاری",infrastructure:"زیرساخت",other:"سایر"};class vn extends x{constructor(e={}){super(e),this.cpmView=e.cpmView??null,this._projects=[],this._lands=[],this._search=""}async template(){return`
            <div class="cpm-section-wrap">
                <div class="cpm-toolbar">
                    <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">+ پروژه جدید</button>
                    <input type="text" data-ref="searchIn" placeholder="جستجو نام / کد..."
                           style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;min-width:200px;">
                    <select data-ref="statusFilter" style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;">
                        <option value="">همه وضعیت‌ها</option>
                        <option value="planned">برنامه‌ریزی</option>
                        <option value="active">فعال</option>
                        <option value="on_hold">متوقف</option>
                        <option value="completed">تکمیل‌شده</option>
                        <option value="cancelled">لغو‌شده</option>
                    </select>
                </div>
                <div class="cpm-grid" data-ref="grid"></div>
            </div>
        `}async afterRender(){try{const e=await this.api.get("/pc/lands");this._lands=(e==null?void 0:e.data)??[]}catch{}this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),this.on(this.ref("searchIn"),"input",()=>this._debouncedLoad()),this.on(this.ref("statusFilter"),"change",()=>this._load()),await this._load()}_debouncedLoad(){clearTimeout(this._searchTimer),this._searchTimer=setTimeout(()=>this._load(),280)}async _load(){var i,n,r;const e=this.ref("grid");e.innerHTML='<div class="cpm-loading"><div class="acc-spinner"></div></div>';const t={},s=(n=(i=this.ref("searchIn"))==null?void 0:i.value)==null?void 0:n.trim(),a=(r=this.ref("statusFilter"))==null?void 0:r.value;s&&(t.search=s),a&&(t.status=a);try{const o=await this.api.get("/pc/projects",t);this._projects=(o==null?void 0:o.data)??[],this._render(e)}catch{e.innerHTML='<div class="acc-empty">خطا در بارگذاری پروژه‌ها</div>'}}_render(e){if(!this._projects.length){e.innerHTML='<div class="acc-empty" style="grid-column:1/-1">پروژه‌ای یافت نشد.</div>';return}e.innerHTML="",this._projects.forEach(t=>{const s=fn[t.status]??{label:t.status,color:"#64748b",bg:"#f1f5f9"},a=parseFloat(t.progress??0).toFixed(0),i=document.createElement("div");i.className="cpm-project-card",i.innerHTML=`
                <div class="cpm-project-card__head">
                    <span class="cpm-project-card__code">${this.escape(t.code||"#"+t.id)}</span>
                    <span class="cpm-status-badge" style="background:${s.bg};color:${s.color}">${s.label}</span>
                </div>
                <div class="cpm-project-card__name">${this.escape(t.name)}</div>
                <div class="cpm-project-card__meta">
                    <span>🏗 ${mn[t.type]??t.type}</span>
                    ${t.start_date?`<span>📅 ${t.start_date}</span>`:""}
                    ${t.manager_name?`<span>👤 ${this.escape(t.manager_name)}</span>`:""}
                </div>
                <div class="cpm-progress-bar-wrap">
                    <div class="cpm-progress-bar" style="width:${a}%"></div>
                    <span class="cpm-progress-label">${a}٪</span>
                </div>
                ${t.budget>0?`<div class="cpm-project-card__budget">💰 بودجه: ${Number(t.budget).toLocaleString("fa-IR")} ریال</div>`:""}
                <div class="cpm-project-card__actions">
                    <button class="acc-btn acc-btn--primary acc-btn--sm" data-action="select">🎯 انتخاب</button>
                    <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit">ویرایش</button>
                    <button class="acc-btn acc-btn--sm" data-action="loc" style="background:#dbeafe;color:#1e40af;">📍 محل پروژه</button>
                    <button class="acc-btn acc-btn--danger acc-btn--sm" data-action="del">حذف</button>
                </div>
            `,i.querySelector("[data-action='select']").addEventListener("click",()=>{this.cpmView&&this.cpmView.selectProject(t),this._highlightSelected(i)}),i.querySelector("[data-action='edit']").addEventListener("click",()=>this._openForm(t)),i.querySelector("[data-action='del']").addEventListener("click",()=>this._delete(t)),i.querySelector("[data-action='loc']").addEventListener("click",()=>z.openModal({api:this.api,entityType:"project",entityId:t.id,entityName:t.name||`پروژه #${t.id}`})),e.appendChild(i)})}_highlightSelected(e){var t;(t=this.ref("grid"))==null||t.querySelectorAll(".cpm-project-card").forEach(s=>s.classList.toggle("cpm-project-card--selected",s===e))}onProjectChange(e){var t;e||(t=this.ref("grid"))==null||t.querySelectorAll(".cpm-project-card").forEach(s=>s.classList.remove("cpm-project-card--selected"))}_openForm(e=null){const t=!!e,s=this._lands.map(n=>`<option value="${n.id}" ${(e==null?void 0:e.land_id)==n.id?"selected":""}>${this.escape(n.name)}</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
            <div class="acc-modal" style="max-width:600px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${t?"ویرایش پروژه":"پروژه جدید"}</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>کد پروژه</label>
                            <input name="code" value="${this.escape((e==null?void 0:e.code)||"")}">
                        </div>
                        <div class="acc-form-group">
                            <label>نام پروژه *</label>
                            <input name="name" value="${this.escape((e==null?void 0:e.name)||"")}" required>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>نوع پروژه</label>
                            <select name="type">
                                <option value="construction" ${(e==null?void 0:e.type)==="construction"?"selected":""}>ساختمانی</option>
                                <option value="software"     ${(e==null?void 0:e.type)==="software"?"selected":""}>نرم‌افزاری</option>
                                <option value="infrastructure" ${(e==null?void 0:e.type)==="infrastructure"?"selected":""}>زیرساخت</option>
                                <option value="other"        ${(e==null?void 0:e.type)==="other"?"selected":""}>سایر</option>
                            </select>
                        </div>
                        <div class="acc-form-group">
                            <label>وضعیت</label>
                            <select name="status">
                                <option value="planned"   ${(e==null?void 0:e.status)==="planned"?"selected":""}>برنامه‌ریزی</option>
                                <option value="active"    ${(e==null?void 0:e.status)==="active"?"selected":""}>فعال</option>
                                <option value="on_hold"   ${(e==null?void 0:e.status)==="on_hold"?"selected":""}>متوقف</option>
                                <option value="completed" ${(e==null?void 0:e.status)==="completed"?"selected":""}>تکمیل‌شده</option>
                                <option value="cancelled" ${(e==null?void 0:e.status)==="cancelled"?"selected":""}>لغو‌شده</option>
                            </select>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>تاریخ شروع</label>
                            <input type="date" name="start_date" value="${this.escape((e==null?void 0:e.start_date)||"")}">
                        </div>
                        <div class="acc-form-group">
                            <label>تاریخ پایان</label>
                            <input type="date" name="end_date" value="${this.escape((e==null?void 0:e.end_date)||"")}">
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>بودجه (ریال)</label>
                            <input type="number" name="budget" value="${this.escape((e==null?void 0:e.budget)||"0")}" min="0">
                        </div>
                        <div class="acc-form-group">
                            <label>زمین</label>
                            <select name="land_id">
                                <option value="">— بدون زمین —</option>
                                ${s}
                            </select>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>نام مدیر پروژه</label>
                            <input name="manager_name" value="${this.escape((e==null?void 0:e.manager_name)||"")}">
                        </div>
                        <div class="acc-form-group">
                            <label>ارز</label>
                            <select name="currency">
                                <option value="IRR" ${(e==null?void 0:e.currency)==="IRR"?"selected":""}>ریال (IRR)</option>
                                <option value="USD" ${(e==null?void 0:e.currency)==="USD"?"selected":""}>دلار (USD)</option>
                            </select>
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>توضیحات</label>
                        <textarea name="description" rows="3">${this.escape((e==null?void 0:e.description)||"")}</textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"ایجاد پروژه"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action='cancel']").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());r.land_id||delete r.land_id;const o=n.target.querySelector("[type='submit']");o.disabled=!0,o.textContent="در حال ذخیره...";try{t?await this.api.put(`/pc/projects/${e.id}`,r):await this.api.post("/pc/projects",r),i(),await this._load()}catch(l){alert("خطا: "+((l==null?void 0:l.message)??"")),o.disabled=!1,o.textContent=t?"ذخیره":"ایجاد پروژه"}})}async _delete(e){if(confirm(`حذف پروژه «${e.name}»؟ تمام وظایف و داده‌های مرتبط نیز حذف می‌شوند.`))try{await this.api.delete(`/pc/projects/${e.id}`),await this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}}const bn={not_started:{label:"شروع نشده",color:"#6b7280",bg:"#f3f4f6"},in_progress:{label:"در حال انجام",color:"#2563eb",bg:"#eff6ff"},completed:{label:"تکمیل",color:"#059669",bg:"#ecfdf5"},on_hold:{label:"متوقف",color:"#d97706",bg:"#fffbeb"},cancelled:{label:"لغو",color:"#dc2626",bg:"#fef2f2"}},gn={low:{label:"کم",color:"#6b7280"},medium:{label:"متوسط",color:"#2563eb"},high:{label:"بالا",color:"#d97706"},critical:{label:"بحرانی",color:"#dc2626"}};class yn extends x{constructor(e={}){super(e),this.cpmView=e.cpmView??null,this._projectId=null,this._tasks=[],this._wbs=[],this._members=[],this._deps=[]}async template(){return`
            <div class="cpm-section-wrap">
                <div class="cpm-section-notice" data-ref="notice" style="display:none">
                    <span>⚠️ لطفاً ابتدا یک پروژه از تب «پروژه‌ها» انتخاب کنید.</span>
                </div>
                <div data-ref="content" style="display:none">
                    <div class="cpm-toolbar">
                        <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addTaskBtn">+ وظیفه جدید</button>
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="addWbsBtn">+ WBS</button>
                        <select data-ref="wbsFilter" style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;">
                            <option value="">همه WBS</option>
                        </select>
                        <select data-ref="statusFilter" style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;">
                            <option value="">همه وضعیت‌ها</option>
                            <option value="not_started">شروع نشده</option>
                            <option value="in_progress">در حال انجام</option>
                            <option value="completed">تکمیل</option>
                            <option value="on_hold">متوقف</option>
                            <option value="cancelled">لغو</option>
                        </select>
                    </div>
                    <div data-ref="tasksWrap"></div>
                </div>
            </div>
        `}async afterRender(){this.ref("notice").style.display="flex"}async onProjectChange(e){if(this._projectId=(e==null?void 0:e.id)??null,!this._projectId){this.ref("notice").style.display="flex",this.ref("content").style.display="none";return}this.ref("notice").style.display="none",this.ref("content").style.display="block",this.on(this.ref("addTaskBtn"),"click",()=>this._openTaskForm(null)),this.on(this.ref("addWbsBtn"),"click",()=>this._openWbsForm(null)),this.on(this.ref("wbsFilter"),"change",()=>this._renderTasks()),this.on(this.ref("statusFilter"),"change",()=>this._renderTasks()),await this._loadAll()}async _loadAll(){const e=this.ref("tasksWrap");e.innerHTML='<div class="cpm-loading"><div class="acc-spinner"></div></div>';try{const t=await this.api.get(`/pc/projects/${this._projectId}/workspace`,{scope:"tasks"});this._wbs=(t==null?void 0:t.wbs)??[],this._tasks=(t==null?void 0:t.tasks)??[],this._members=(t==null?void 0:t.members)??[],this._deps=(t==null?void 0:t.dependencies)??[],this._populateWbsFilter(),this._renderTasks()}catch{e.innerHTML='<div class="acc-empty">خطا در بارگذاری وظایف</div>'}}_populateWbsFilter(){const e=this.ref("wbsFilter");e&&(e.innerHTML='<option value="">همه WBS</option>'+this._wbs.map(t=>`<option value="${t.id}">${this.escape(t.code?t.code+" — ":"")}${this.escape(t.name)}</option>`).join(""))}_renderTasks(){var r,o;const e=this.ref("tasksWrap"),t=(r=this.ref("wbsFilter"))==null?void 0:r.value,s=(o=this.ref("statusFilter"))==null?void 0:o.value;let a=this._tasks;if(t&&(a=a.filter(l=>String(l.wbs_id)===t)),s&&(a=a.filter(l=>l.status===s)),!a.length){e.innerHTML='<div class="acc-empty">وظیفه‌ای یافت نشد.</div>';return}const i={};this._wbs.forEach(l=>{i[l.id]=l});const n={};a.forEach(l=>{const c=l.wbs_id??"0";n[c]||(n[c]={wbs:i[c]??null,tasks:[]}),n[c].tasks.push(l)}),e.innerHTML="",Object.entries(n).forEach(([l,c])=>{var f;const d=document.createElement("div");d.className="cpm-wbs-group";const h=c.wbs?`<span class="cpm-wbs-code">${this.escape(c.wbs.code||"")}</span> ${this.escape(c.wbs.name)}`:"بدون WBS";d.innerHTML=`
                <div class="cpm-wbs-group__header">
                    <span class="cpm-wbs-icon">📂</span>
                    <span>${h}</span>
                    ${c.wbs?`<button class="acc-btn acc-btn--secondary acc-btn--xs" data-wbs-edit="${c.wbs.id}">ویرایش WBS</button>`:""}
                </div>
                <div class="cpm-task-list"></div>
            `,c.wbs&&((f=d.querySelector("[data-wbs-edit]"))==null||f.addEventListener("click",()=>this._openWbsForm(c.wbs)));const u=d.querySelector(".cpm-task-list");c.tasks.forEach(m=>u.appendChild(this._buildTaskRow(m))),e.appendChild(d)})}_buildTaskRow(e){const t=bn[e.status]??{label:e.status,color:"#64748b",bg:"#f1f5f9"},s=gn[e.priority]??{label:e.priority,color:"#64748b"},a=parseFloat(e.progress??0).toFixed(0),i=this._members.find(c=>c.id==e.assigned_member_id),n=document.createElement("div");n.className="cpm-task-row"+(e.is_critical?" cpm-task-row--critical":""),n.innerHTML=`
            <div class="cpm-task-row__info">
                <div class="cpm-task-row__top">
                    <span class="cpm-task-code">${this.escape(e.code||"T-"+e.id)}</span>
                    ${e.is_critical?'<span class="cpm-badge cpm-badge--critical" title="مسیر بحرانی">🔴 بحرانی</span>':""}
                    <span class="cpm-task-name">${this.escape(e.name)}</span>
                    <span class="cpm-status-badge" style="background:${t.bg};color:${t.color}">${t.label}</span>
                    <span style="font-size:11px;font-weight:700;color:${s.color}">${s.label}</span>
                </div>
                <div class="cpm-task-row__meta">
                    ${e.start_date?`📅 ${e.start_date} → ${e.end_date||"؟"}`:""}
                    ${e.duration?` | ⏱ ${e.duration} ${e.duration_unit==="day"?"روز":e.duration_unit==="hour"?"ساعت":"هفته"}`:""}
                    ${i?` | 👤 ${this.escape(i.name)}`:""}
                </div>
                <div class="cpm-task-progress-row">
                    <input type="range" class="cpm-progress-slider" min="0" max="100" value="${a}" data-tid="${e.id}">
                    <span class="cpm-progress-pct">${a}٪</span>
                </div>
            </div>
            <div class="cpm-task-row__actions">
                <button class="acc-btn acc-btn--secondary acc-btn--xs" data-action="edit">ویرایش</button>
                <button class="acc-btn acc-btn--secondary acc-btn--xs" data-action="logs">لاگ</button>
                <button class="acc-btn acc-btn--danger acc-btn--xs"    data-action="del">حذف</button>
            </div>
        `;const r=n.querySelector(".cpm-progress-slider"),o=n.querySelector(".cpm-progress-pct");let l;return r.addEventListener("input",()=>{o.textContent=r.value+"٪"}),r.addEventListener("change",()=>{clearTimeout(l),l=setTimeout(()=>this._updateProgress(e,parseInt(r.value)),400)}),n.querySelector("[data-action='edit']").addEventListener("click",()=>this._openTaskForm(e)),n.querySelector("[data-action='logs']").addEventListener("click",()=>this._showLogs(e)),n.querySelector("[data-action='del']").addEventListener("click",()=>this._deleteTask(e)),n}async _updateProgress(e,t){try{await this.api.post(`/pc/tasks/${e.id}/progress`,{progress:t}),e.progress=t}catch(s){alert("خطا: "+((s==null?void 0:s.message)??""))}}_openTaskForm(e=null){const t=!!e,s=this._wbs.map(r=>`<option value="${r.id}" ${(e==null?void 0:e.wbs_id)==r.id?"selected":""}>${this.escape(r.name)}</option>`).join(""),a=this._members.map(r=>`<option value="${r.id}" ${(e==null?void 0:e.assigned_member_id)==r.id?"selected":""}>${this.escape(r.name)}</option>`).join(""),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
            <div class="acc-modal" style="max-width:620px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${t?"ویرایش وظیفه":"وظیفه جدید"}</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>کد وظیفه</label>
                            <input name="code" value="${this.escape((e==null?void 0:e.code)||"")}">
                        </div>
                        <div class="acc-form-group">
                            <label>نام وظیفه *</label>
                            <input name="name" value="${this.escape((e==null?void 0:e.name)||"")}" required>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>WBS</label>
                            <select name="wbs_id">
                                <option value="">— بدون WBS —</option>
                                ${s}
                            </select>
                        </div>
                        <div class="acc-form-group">
                            <label>نوع</label>
                            <select name="type">
                                <option value="task"      ${(e==null?void 0:e.type)==="task"?"selected":""}>وظیفه</option>
                                <option value="milestone" ${(e==null?void 0:e.type)==="milestone"?"selected":""}>نقطه عطف</option>
                                <option value="summary"   ${(e==null?void 0:e.type)==="summary"?"selected":""}>خلاصه</option>
                            </select>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>وضعیت</label>
                            <select name="status">
                                <option value="not_started" ${(e==null?void 0:e.status)==="not_started"?"selected":""}>شروع نشده</option>
                                <option value="in_progress"  ${(e==null?void 0:e.status)==="in_progress"?"selected":""}>در حال انجام</option>
                                <option value="completed"    ${(e==null?void 0:e.status)==="completed"?"selected":""}>تکمیل</option>
                                <option value="on_hold"      ${(e==null?void 0:e.status)==="on_hold"?"selected":""}>متوقف</option>
                                <option value="cancelled"    ${(e==null?void 0:e.status)==="cancelled"?"selected":""}>لغو</option>
                            </select>
                        </div>
                        <div class="acc-form-group">
                            <label>اولویت</label>
                            <select name="priority">
                                <option value="low"      ${(e==null?void 0:e.priority)==="low"?"selected":""}>کم</option>
                                <option value="medium"   ${(e==null?void 0:e.priority)==="medium"?"selected":""}>متوسط</option>
                                <option value="high"     ${(e==null?void 0:e.priority)==="high"?"selected":""}>بالا</option>
                                <option value="critical" ${(e==null?void 0:e.priority)==="critical"?"selected":""}>بحرانی</option>
                            </select>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>مدت (روز/ساعت/هفته)</label>
                            <input type="number" name="duration" value="${this.escape((e==null?void 0:e.duration)||"0")}" min="0">
                        </div>
                        <div class="acc-form-group">
                            <label>واحد مدت</label>
                            <select name="duration_unit">
                                <option value="day"  ${(e==null?void 0:e.duration_unit)==="day"?"selected":""}>روز</option>
                                <option value="hour" ${(e==null?void 0:e.duration_unit)==="hour"?"selected":""}>ساعت</option>
                                <option value="week" ${(e==null?void 0:e.duration_unit)==="week"?"selected":""}>هفته</option>
                            </select>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>تاریخ شروع</label>
                            <input type="date" name="start_date" value="${this.escape((e==null?void 0:e.start_date)||"")}">
                        </div>
                        <div class="acc-form-group">
                            <label>تاریخ پایان</label>
                            <input type="date" name="end_date" value="${this.escape((e==null?void 0:e.end_date)||"")}">
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>پیشرفت (٪)</label>
                            <input type="number" name="progress" value="${this.escape((e==null?void 0:e.progress)||"0")}" min="0" max="100">
                        </div>
                        <div class="acc-form-group">
                            <label>عضو مسئول</label>
                            <select name="assigned_member_id">
                                <option value="">— بدون تخصیص —</option>
                                ${a}
                            </select>
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>توضیحات</label>
                        <textarea name="description" rows="2">${this.escape((e==null?void 0:e.description)||"")}</textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(i);const n=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",n),i.querySelector("[data-action='cancel']").addEventListener("click",n),i.addEventListener("click",r=>{r.target===i&&n()}),i.querySelector("form").addEventListener("submit",async r=>{r.preventDefault();const o=Object.fromEntries(new FormData(r.target).entries());o.wbs_id||delete o.wbs_id,o.assigned_member_id||delete o.assigned_member_id,o.project_id=this._projectId;const l=r.target.querySelector("[type='submit']");l.disabled=!0,l.textContent="در حال ذخیره...";try{t?await this.api.put(`/pc/tasks/${e.id}`,o):await this.api.post(`/pc/projects/${this._projectId}/tasks`,o),n(),await this._loadAll()}catch(c){alert("خطا: "+((c==null?void 0:c.message)??"")),l.disabled=!1,l.textContent=t?"ذخیره":"افزودن"}})}_openWbsForm(e=null){const t=!!e,s=this._wbs.filter(n=>n.id!==(e==null?void 0:e.id)).map(n=>`<option value="${n.id}" ${(e==null?void 0:e.parent_id)==n.id?"selected":""}>${this.escape(n.name)}</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
            <div class="acc-modal" style="max-width:480px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${t?"ویرایش WBS":"WBS جدید"}</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>کد WBS</label>
                            <input name="code" value="${this.escape((e==null?void 0:e.code)||"")}">
                        </div>
                        <div class="acc-form-group">
                            <label>نام WBS *</label>
                            <input name="name" value="${this.escape((e==null?void 0:e.name)||"")}" required>
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>WBS والد</label>
                        <select name="parent_id">
                            <option value="">— سطح اول —</option>
                            ${s}
                        </select>
                    </div>
                    <div class="acc-form-group">
                        <label>توضیحات</label>
                        <textarea name="description" rows="2">${this.escape((e==null?void 0:e.description)||"")}</textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action='cancel']").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());r.parent_id||delete r.parent_id;const o=n.target.querySelector("[type='submit']");o.disabled=!0,o.textContent="در حال ذخیره...";try{t?await this.api.put(`/pc/wbs/${e.id}`,r):await this.api.post(`/pc/projects/${this._projectId}/wbs`,r),i(),await this._loadAll()}catch(l){alert("خطا: "+((l==null?void 0:l.message)??"")),o.disabled=!1,o.textContent=t?"ذخیره":"افزودن"}})}async _showLogs(e){let t=[];try{const i=await this.api.get(`/pc/tasks/${e.id}/logs`);t=(i==null?void 0:i.data)??[]}catch{}const s=document.createElement("div");s.className="acc-modal-overlay";const a=t.length?t.map(i=>{var n;return`
                <tr>
                    <td>${((n=i.created_at)==null?void 0:n.slice(0,16))??""}</td>
                    <td>${this.escape(i.reporter_name||"—")}</td>
                    <td>${i.old_progress}٪ → ${i.new_progress}٪</td>
                    <td>${this.escape(i.old_status||"")} → ${this.escape(i.new_status||"")}</td>
                    <td>${this.escape(i.note||"")}</td>
                </tr>`}).join(""):'<tr><td colspan="5" style="text-align:center;padding:20px;color:#94a3b8;">لاگی ثبت نشده</td></tr>';s.innerHTML=`
            <div class="acc-modal" style="max-width:700px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">لاگ پیشرفت: ${this.escape(e.name)}</div>
                <table class="acc-table" style="width:100%;font-size:12px;">
                    <thead><tr><th>تاریخ</th><th>گزارش‌دهنده</th><th>پیشرفت</th><th>وضعیت</th><th>یادداشت</th></tr></thead>
                    <tbody>${a}</tbody>
                </table>
                <div class="acc-modal__actions"><button class="acc-btn acc-btn--secondary" data-action="close">بستن</button></div>
            </div>`,document.body.appendChild(s),s.querySelector(".acc-modal__close").addEventListener("click",()=>s.remove()),s.querySelector("[data-action='close']").addEventListener("click",()=>s.remove()),s.addEventListener("click",i=>{i.target===s&&s.remove()})}async _deleteTask(e){if(confirm(`حذف وظیفه «${e.name}»؟`))try{await this.api.delete(`/pc/tasks/${e.id}`),await this._loadAll()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}}const le={human:{label:"انسانی",icon:"👤",color:"#2563eb",bg:"#eff6ff"},equipment:{label:"تجهیزات",icon:"⚙️",color:"#7c3aed",bg:"#f5f3ff"},material:{label:"مواد",icon:"📦",color:"#d97706",bg:"#fffbeb"},other:{label:"سایر",icon:"🔧",color:"#6b7280",bg:"#f3f4f6"}};class _n extends x{constructor(e={}){super(e),this.cpmView=e.cpmView??null,this._projectId=null,this._resources=[],this._tasks=[],this._assignments=[],this._tab="resources"}async template(){return`
            <div class="cpm-section-wrap">
                <div class="cpm-section-notice" data-ref="notice">
                    <span>⚠️ لطفاً ابتدا یک پروژه از تب «پروژه‌ها» انتخاب کنید.</span>
                </div>
                <div data-ref="content" style="display:none">
                    <div class="cpm-sub-tabs" data-ref="subTabs">
                        <button class="cpm-sub-tab cpm-sub-tab--active" data-tab="resources">👷 منابع</button>
                        <button class="cpm-sub-tab" data-tab="assignments">🔗 تخصیص منابع</button>
                    </div>
                    <div data-ref="tabContent"></div>
                </div>
            </div>
        `}async afterRender(){}async onProjectChange(e){if(this._projectId=(e==null?void 0:e.id)??null,!this._projectId){this.ref("notice").style.display="flex",this.ref("content").style.display="none";return}this.ref("notice").style.display="none",this.ref("content").style.display="block",this.ref("subTabs").querySelectorAll(".cpm-sub-tab").forEach(t=>{this.on(t,"click",()=>this._switchTab(t.dataset.tab))}),await this._loadAll(),this._renderTab()}async _loadAll(){try{const e=await this.api.get(`/pc/projects/${this._projectId}/workspace`,{scope:"resources"});this._resources=(e==null?void 0:e.resources)??[],this._tasks=(e==null?void 0:e.tasks)??[],this._assignments=(e==null?void 0:e.assignments)??[]}catch{}}_switchTab(e){this._tab=e,this.ref("subTabs").querySelectorAll(".cpm-sub-tab").forEach(t=>t.classList.toggle("cpm-sub-tab--active",t.dataset.tab===e)),this._renderTab()}_renderTab(){this._tab==="resources"?this._renderResources():this._renderAssignments()}_renderResources(){const e=this.ref("tabContent");e.innerHTML=`
            <div class="cpm-toolbar" style="margin-top:12px">
                <button class="acc-btn acc-btn--primary acc-btn--sm" id="addResBtn">+ منبع جدید</button>
            </div>
            <div class="cpm-res-grid" id="resGrid"></div>
        `,e.querySelector("#addResBtn").addEventListener("click",()=>this._openResourceForm(null)),this._fillResourceGrid(e.querySelector("#resGrid"))}_fillResourceGrid(e){if(!this._resources.length){e.innerHTML='<div class="acc-empty">منبعی تعریف نشده است.</div>';return}e.innerHTML="",this._resources.forEach(t=>{const s=le[t.type]??le.other,a=document.createElement("div");a.className="cpm-res-card",a.innerHTML=`
                <div class="cpm-res-card__type" style="background:${s.bg};color:${s.color}">
                    ${s.icon} ${s.label}
                </div>
                <div class="cpm-res-card__name">${this.escape(t.name)}</div>
                ${t.code?`<div class="cpm-res-card__code">${this.escape(t.code)}</div>`:""}
                <div class="cpm-res-card__meta">
                    ${t.unit?`واحد: ${this.escape(t.unit)}`:""}
                    ${t.cost_per_unit>0?` | نرخ: ${Number(t.cost_per_unit).toLocaleString("fa-IR")} ${t.currency}`:""}
                </div>
                <div class="cpm-res-card__actions">
                    <button class="acc-btn acc-btn--secondary acc-btn--xs" data-action="edit">ویرایش</button>
                    <button class="acc-btn acc-btn--danger acc-btn--xs"    data-action="del">حذف</button>
                </div>
            `,a.querySelector("[data-action='edit']").addEventListener("click",()=>this._openResourceForm(t)),a.querySelector("[data-action='del']").addEventListener("click",()=>this._deleteResource(t)),e.appendChild(a)})}_openResourceForm(e=null){const t=!!e,s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
            <div class="acc-modal" style="max-width:480px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${t?"ویرایش منبع":"منبع جدید"}</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>کد منبع</label>
                            <input name="code" value="${this.escape((e==null?void 0:e.code)||"")}">
                        </div>
                        <div class="acc-form-group">
                            <label>نام منبع *</label>
                            <input name="name" value="${this.escape((e==null?void 0:e.name)||"")}" required>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>نوع</label>
                            <select name="type">
                                <option value="human"     ${(e==null?void 0:e.type)==="human"?"selected":""}>انسانی</option>
                                <option value="equipment" ${(e==null?void 0:e.type)==="equipment"?"selected":""}>تجهیزات</option>
                                <option value="material"  ${(e==null?void 0:e.type)==="material"?"selected":""}>مواد</option>
                                <option value="other"     ${(e==null?void 0:e.type)==="other"?"selected":""}>سایر</option>
                            </select>
                        </div>
                        <div class="acc-form-group">
                            <label>واحد</label>
                            <input name="unit" value="${this.escape((e==null?void 0:e.unit)||"")}" placeholder="نفر/روز، کیلوگرم...">
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>نرخ هر واحد (ریال)</label>
                            <input type="number" name="cost_per_unit" value="${this.escape((e==null?void 0:e.cost_per_unit)||"0")}" min="0">
                        </div>
                        <div class="acc-form-group">
                            <label>ارز</label>
                            <select name="currency">
                                <option value="IRR" ${(e==null?void 0:e.currency)==="IRR"?"selected":""}>ریال</option>
                                <option value="USD" ${(e==null?void 0:e.currency)==="USD"?"selected":""}>دلار</option>
                            </select>
                        </div>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action='cancel']").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries()),r=i.target.querySelector("[type='submit']");r.disabled=!0,r.textContent="در حال ذخیره...";try{t?await this.api.put(`/pc/resources/${e.id}`,n):await this.api.post(`/pc/projects/${this._projectId}/resources`,n),a(),await this._loadAll(),this._renderTab()}catch(o){alert("خطا: "+((o==null?void 0:o.message)??"")),r.disabled=!1,r.textContent=t?"ذخیره":"افزودن"}})}async _deleteResource(e){if(confirm(`حذف منبع «${e.name}»؟`))try{await this.api.delete(`/pc/resources/${e.id}`),await this._loadAll(),this._renderTab()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}async _renderAssignments(){const e=this.ref("tabContent"),t=this._assignments,s={},a={};this._resources.forEach(o=>{s[o.id]=o}),this._tasks.forEach(o=>{a[o.id]=o});const i=this._tasks.map(o=>`<option value="${o.id}">${this.escape(o.code?o.code+" — ":"")}${this.escape(o.name)}</option>`).join(""),n=this._resources.map(o=>{var l;return`<option value="${o.id}">${this.escape(o.name)} (${((l=le[o.type])==null?void 0:l.label)??o.type})</option>`}).join(""),r=t.length?t.map(o=>{const l=s[o.resource_id],c=a[o.task_id],d=le[l==null?void 0:l.type]??le.other;return`
                    <tr>
                        <td>${this.escape((c==null?void 0:c.name)??"#"+o.task_id)}</td>
                        <td>
                            <span class="cpm-badge" style="background:${d.bg};color:${d.color}">${d.icon} ${this.escape((l==null?void 0:l.name)??"#"+o.resource_id)}</span>
                        </td>
                        <td>${o.quantity} ${this.escape((l==null?void 0:l.unit)||"")}</td>
                        <td>${Number(o.cost_per_unit).toLocaleString("fa-IR")}</td>
                        <td><strong>${Number(o.total_cost).toLocaleString("fa-IR")}</strong></td>
                        <td>${this.escape(o.notes||"")}</td>
                        <td>
                            <button class="acc-btn acc-btn--danger acc-btn--xs" data-del="${o.id}">حذف</button>
                        </td>
                    </tr>`}).join(""):'<tr><td colspan="7" style="text-align:center;padding:20px;color:#94a3b8;">تخصیصی ثبت نشده</td></tr>';e.innerHTML=`
            <div style="margin-top:12px">
                <div class="cpm-toolbar">
                    <button class="acc-btn acc-btn--primary acc-btn--sm" id="addAssignBtn">+ تخصیص جدید</button>
                </div>
                <table class="acc-table" style="width:100%;margin-top:10px">
                    <thead>
                        <tr>
                            <th>وظیفه</th><th>منبع</th><th>مقدار</th>
                            <th>نرخ واحد</th><th>هزینه کل</th><th>یادداشت</th><th></th>
                        </tr>
                    </thead>
                    <tbody>${r}</tbody>
                </table>
            </div>`,e.querySelector("#addAssignBtn").addEventListener("click",()=>this._openAssignmentForm(i,n)),e.querySelectorAll("[data-del]").forEach(o=>o.addEventListener("click",()=>this._deleteAssignment(o.dataset.del)))}_openAssignmentForm(e,t){const s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
            <div class="acc-modal" style="max-width:480px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">تخصیص منبع به وظیفه</div>
                <form>
                    <div class="acc-form-group">
                        <label>وظیفه *</label>
                        <select name="task_id" required><option value="">انتخاب کنید</option>${e}</select>
                    </div>
                    <div class="acc-form-group">
                        <label>منبع *</label>
                        <select name="resource_id" required><option value="">انتخاب کنید</option>${t}</select>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>مقدار / تعداد</label>
                            <input type="number" name="quantity" value="1" min="0" step="0.01">
                        </div>
                        <div class="acc-form-group">
                            <label>نرخ واحد (ریال)</label>
                            <input type="number" name="cost_per_unit" value="0" min="0">
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>یادداشت</label>
                        <textarea name="notes" rows="2"></textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">ثبت تخصیص</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action='cancel']").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries()),r=parseFloat(n.quantity||1),o=parseFloat(n.cost_per_unit||0);n.total_cost=(r*o).toFixed(4);const l=i.target.querySelector("[type='submit']");l.disabled=!0,l.textContent="در حال ذخیره...";try{await this.api.post(`/pc/projects/${this._projectId}/assignments`,n),a(),await this._loadAll(),this._renderAssignments()}catch(c){alert("خطا: "+((c==null?void 0:c.message)??"")),l.disabled=!1,l.textContent="ثبت تخصیص"}})}async _deleteAssignment(e){if(confirm("حذف این تخصیص؟"))try{await this.api.delete(`/pc/assignments/${e}`),await this._loadAll(),this._renderAssignments()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}}const Qt={manager:{label:"مدیر پروژه",icon:"👑",color:"#7c3aed",bg:"#f5f3ff"},engineer:{label:"مهندس",icon:"🔧",color:"#2563eb",bg:"#eff6ff"},supervisor:{label:"ناظر",icon:"👁",color:"#0891b2",bg:"#ecfeff"},worker:{label:"کارگر",icon:"🦺",color:"#d97706",bg:"#fffbeb"},consultant:{label:"مشاور",icon:"💼",color:"#059669",bg:"#ecfdf5"},client:{label:"کارفرما",icon:"🏢",color:"#dc2626",bg:"#fef2f2"},other:{label:"سایر",icon:"👤",color:"#6b7280",bg:"#f3f4f6"}};class xn extends x{constructor(e={}){super(e),this.cpmView=e.cpmView??null,this._projectId=null,this._members=[]}async template(){return`
            <div class="cpm-section-wrap">
                <div class="cpm-section-notice" data-ref="notice">
                    <span>⚠️ لطفاً ابتدا یک پروژه از تب «پروژه‌ها» انتخاب کنید.</span>
                </div>
                <div data-ref="content" style="display:none">
                    <div class="cpm-toolbar">
                        <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">+ عضو جدید</button>
                        <select data-ref="roleFilter" style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;">
                            <option value="">همه نقش‌ها</option>
                            <option value="manager">مدیر پروژه</option>
                            <option value="engineer">مهندس</option>
                            <option value="supervisor">ناظر</option>
                            <option value="worker">کارگر</option>
                            <option value="consultant">مشاور</option>
                            <option value="client">کارفرما</option>
                            <option value="other">سایر</option>
                        </select>
                        <input type="text" data-ref="searchIn" placeholder="جستجو نام..."
                               style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;min-width:180px;">
                    </div>
                    <div class="cpm-grid" data-ref="grid"></div>
                </div>
            </div>
        `}async afterRender(){}async onProjectChange(e){if(this._projectId=(e==null?void 0:e.id)??null,!this._projectId){this.ref("notice").style.display="flex",this.ref("content").style.display="none";return}this.ref("notice").style.display="none",this.ref("content").style.display="block",this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),this.on(this.ref("roleFilter"),"change",()=>this._render()),this.on(this.ref("searchIn"),"input",()=>this._render()),await this._load()}async _load(){const e=this.ref("grid");e.innerHTML='<div class="cpm-loading"><div class="acc-spinner"></div></div>';try{const t=await this.api.get(`/pc/projects/${this._projectId}/members`);this._members=(t==null?void 0:t.data)??[],this._render()}catch{e.innerHTML='<div class="acc-empty">خطا در بارگذاری اعضا</div>'}}_render(){var i,n,r;const e=this.ref("grid"),t=(i=this.ref("roleFilter"))==null?void 0:i.value,s=(r=(n=this.ref("searchIn"))==null?void 0:n.value)==null?void 0:r.trim().toLowerCase();let a=this._members;if(t&&(a=a.filter(o=>o.role===t)),s&&(a=a.filter(o=>{var l,c;return((l=o.name)==null?void 0:l.toLowerCase().includes(s))||((c=o.email)==null?void 0:c.toLowerCase().includes(s))})),!a.length){e.innerHTML='<div class="acc-empty" style="grid-column:1/-1">عضوی یافت نشد.</div>';return}e.innerHTML="",a.forEach(o=>{const l=Qt[o.role]??Qt.other,c=document.createElement("div");c.className="cpm-member-card"+(o.is_active?"":" cpm-member-card--inactive"),c.innerHTML=`
                <div class="cpm-member-card__avatar" style="background:${l.bg};color:${l.color}">
                    ${l.icon}
                </div>
                <div class="cpm-member-card__info">
                    <div class="cpm-member-card__name">${this.escape(o.name)}</div>
                    <div class="cpm-member-card__role">
                        <span class="cpm-badge" style="background:${l.bg};color:${l.color}">${l.label}</span>
                        ${o.is_active?"":'<span class="cpm-badge" style="background:#fee2e2;color:#dc2626">غیرفعال</span>'}
                    </div>
                    <div class="cpm-member-card__meta">
                        ${o.email?`📧 ${this.escape(o.email)}`:""}
                        ${o.phone?` | 📱 ${this.escape(o.phone)}`:""}
                        ${o.joined_at?`<br>📅 پیوستن: ${o.joined_at}`:""}
                    </div>
                </div>
                <div class="cpm-member-card__actions">
                    <button class="acc-btn acc-btn--secondary acc-btn--xs" data-action="edit">ویرایش</button>
                    <button class="acc-btn ${o.is_active?"acc-btn--warning":"acc-btn--success"} acc-btn--xs" data-action="toggle">
                        ${o.is_active?"غیرفعال":"فعال‌سازی"}
                    </button>
                    <button class="acc-btn acc-btn--danger acc-btn--xs" data-action="del">حذف</button>
                </div>
            `,c.querySelector("[data-action='edit']").addEventListener("click",()=>this._openForm(o)),c.querySelector("[data-action='toggle']").addEventListener("click",()=>this._toggleActive(o)),c.querySelector("[data-action='del']").addEventListener("click",()=>this._delete(o)),e.appendChild(c)})}_openForm(e=null){const t=!!e,s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
            <div class="acc-modal" style="max-width:520px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${t?"ویرایش عضو":"عضو جدید"}</div>
                <form>
                    <div class="acc-form-group">
                        <label>نام و نام خانوادگی *</label>
                        <input name="name" value="${this.escape((e==null?void 0:e.name)||"")}" required>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>ایمیل</label>
                            <input type="email" name="email" value="${this.escape((e==null?void 0:e.email)||"")}">
                        </div>
                        <div class="acc-form-group">
                            <label>تلفن</label>
                            <input name="phone" value="${this.escape((e==null?void 0:e.phone)||"")}">
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>نقش *</label>
                            <select name="role">
                                <option value="manager"    ${(e==null?void 0:e.role)==="manager"?"selected":""}>مدیر پروژه</option>
                                <option value="engineer"   ${(e==null?void 0:e.role)==="engineer"?"selected":""}>مهندس</option>
                                <option value="supervisor" ${(e==null?void 0:e.role)==="supervisor"?"selected":""}>ناظر</option>
                                <option value="worker"     ${(e==null?void 0:e.role)==="worker"?"selected":""}>کارگر</option>
                                <option value="consultant" ${(e==null?void 0:e.role)==="consultant"?"selected":""}>مشاور</option>
                                <option value="client"     ${(e==null?void 0:e.role)==="client"?"selected":""}>کارفرما</option>
                                <option value="other"      ${(e==null?void 0:e.role)==="other"?"selected":""}>سایر</option>
                            </select>
                        </div>
                        <div class="acc-form-group">
                            <label>تاریخ پیوستن</label>
                            <input type="date" name="joined_at" value="${this.escape((e==null?void 0:e.joined_at)||"")}">
                        </div>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action='cancel']").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries()),r=i.target.querySelector("[type='submit']");r.disabled=!0,r.textContent="در حال ذخیره...";try{t?await this.api.put(`/pc/members/${e.id}`,n):await this.api.post(`/pc/projects/${this._projectId}/members`,n),a(),await this._load()}catch(o){alert("خطا: "+((o==null?void 0:o.message)??"")),r.disabled=!1,r.textContent=t?"ذخیره":"افزودن"}})}async _toggleActive(e){try{await this.api.put(`/pc/members/${e.id}`,{is_active:e.is_active?0:1}),await this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}async _delete(e){if(confirm(`حذف عضو «${e.name}»؟`))try{await this.api.delete(`/pc/members/${e.id}`),await this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}}class wn extends x{constructor(e={}){super(e),this.cpmView=e.cpmView??null,this._projectId=null,this._members=[],this._messages=[],this._senderId=null,this._pollTimer=null}async template(){return`
            <div class="cpm-section-wrap">
                <div class="cpm-section-notice" data-ref="notice">
                    <span>⚠️ لطفاً ابتدا یک پروژه از تب «پروژه‌ها» انتخاب کنید.</span>
                </div>
                <div class="cpm-chat-wrap" data-ref="chatWrap" style="display:none">
                    <div class="cpm-chat-sidebar" data-ref="sidebar">
                        <div class="cpm-chat-sidebar__title">اعضای تیم</div>
                        <div class="cpm-chat-member-list" data-ref="memberList"></div>
                        <div class="cpm-chat-identity">
                            <label style="font-size:11px;color:#94a3b8;margin-bottom:4px;display:block">ارسال به‌عنوان:</label>
                            <select data-ref="senderSel" style="width:100%;padding:6px 10px;border:1.5px solid #d1d5db;border-radius:8px;font-size:12px;">
                                <option value="">— انتخاب هویت —</option>
                            </select>
                        </div>
                    </div>
                    <div class="cpm-chat-main">
                        <div class="cpm-chat-header" data-ref="chatHeader">
                            <span>💬 گفتگوی عمومی پروژه</span>
                            <button class="acc-btn acc-btn--secondary acc-btn--xs" data-ref="refreshBtn" title="بارگذاری مجدد">🔄</button>
                        </div>
                        <div class="cpm-chat-messages" data-ref="msgList"></div>
                        <form class="cpm-chat-form" data-ref="msgForm">
                            <select data-ref="receiverSel" style="min-width:130px;padding:8px 10px;border:1.5px solid #d1d5db;border-radius:8px;font-size:12px;">
                                <option value="">📢 همه اعضا</option>
                            </select>
                            <input type="text" data-ref="msgInput" placeholder="پیام خود را بنویسید..." autocomplete="off" required>
                            <button type="submit" class="acc-btn acc-btn--primary">ارسال ↑</button>
                        </form>
                    </div>
                </div>
            </div>
        `}async afterRender(){}async onProjectChange(e){if(this._stopPoll(),this._projectId=(e==null?void 0:e.id)??null,!this._projectId){this.ref("notice").style.display="flex",this.ref("chatWrap").style.display="none";return}this.ref("notice").style.display="none",this.ref("chatWrap").style.display="flex",await this._loadMembers(),await this._loadMessages(),this._bindEvents(),this._startPoll()}async _loadMembers(){try{const a=await this.api.get(`/pc/projects/${this._projectId}/members`);this._members=((a==null?void 0:a.data)??[]).filter(i=>i.is_active)}catch{this._members=[]}const e=this.ref("memberList");e&&(e.innerHTML=this._members.map(a=>`
                <div class="cpm-chat-member" data-mid="${a.id}">
                    <span class="cpm-chat-member__avatar">${(a.name||"?")[0]}</span>
                    <span class="cpm-chat-member__name">${this.escape(a.name)}</span>
                </div>
            `).join("")||'<div style="padding:12px;font-size:12px;color:#94a3b8">عضوی یافت نشد</div>');const t=this.ref("senderSel"),s=this.ref("receiverSel");t&&(t.innerHTML='<option value="">— انتخاب هویت —</option>'+this._members.map(a=>`<option value="${a.id}">${this.escape(a.name)}</option>`).join(""),this._senderId&&(t.value=this._senderId)),s&&(s.innerHTML='<option value="">📢 همه اعضا</option>'+this._members.map(a=>`<option value="${a.id}">🔒 ${this.escape(a.name)}</option>`).join(""))}async _loadMessages(e=!1){if(!e){const t=this.ref("msgList");t&&(t.innerHTML='<div class="cpm-loading" style="justify-content:center;padding:24px"><div class="acc-spinner"></div></div>')}try{const t=await this.api.get(`/pc/projects/${this._projectId}/messages`);this._messages=(t==null?void 0:t.data)??[],this._renderMessages()}catch{const t=this.ref("msgList");t&&!e&&(t.innerHTML='<div class="acc-empty">خطا در بارگذاری پیام‌ها</div>')}}_renderMessages(){var i;const e=this.ref("msgList");if(!e)return;const t=parseInt(((i=this.ref("senderSel"))==null?void 0:i.value)||"0"),s=e.scrollHeight-e.scrollTop-e.clientHeight<60;if(!this._messages.length){e.innerHTML='<div class="cpm-chat-empty">هنوز پیامی ارسال نشده. اولین نفر باشید! 💬</div>';return}e.innerHTML="";let a="";this._messages.forEach(n=>{var h,u,f,m;const r=((h=n.created_at)==null?void 0:h.slice(0,10))??"";if(r&&r!==a){a=r;const b=document.createElement("div");b.className="cpm-chat-date-sep",b.textContent=r,e.appendChild(b)}const o=t&&n.sender_member_id==t,l=n.receiver_member_id!=null,c=document.createElement("div");c.className="cpm-chat-bubble"+(o?" cpm-chat-bubble--mine":" cpm-chat-bubble--other");const d=l?((u=this._members.find(b=>b.id==n.receiver_member_id))==null?void 0:u.name)??"":"";c.innerHTML=`
                <div class="cpm-chat-bubble__meta">
                    <span class="cpm-chat-bubble__sender">${this.escape(n.sender_name||"ناشناس")}</span>
                    ${l?`<span class="cpm-chat-bubble__private" title="پیام خصوصی">🔒 → ${this.escape(d)}</span>`:""}
                    <span class="cpm-chat-bubble__time">${((f=n.created_at)==null?void 0:f.slice(11,16))??""}</span>
                </div>
                <div class="cpm-chat-bubble__text">${this.escape(n.message)}</div>
                ${o?`<button class="cpm-chat-del" data-mid="${n.id}" title="حذف">✕</button>`:""}
            `,(m=c.querySelector(".cpm-chat-del"))==null||m.addEventListener("click",()=>this._deleteMsg(n.id)),e.appendChild(c)}),s&&(e.scrollTop=e.scrollHeight)}_bindEvents(){const e=this.ref("msgForm");e&&!e._bound&&(e._bound=!0,e.addEventListener("submit",async a=>{var l,c,d,h;a.preventDefault();const i=parseInt(((l=this.ref("senderSel"))==null?void 0:l.value)||"0");if(!i){alert("لطفاً هویت فرستنده را انتخاب کنید.");return}const n=(d=(c=this.ref("msgInput"))==null?void 0:c.value)==null?void 0:d.trim(),r=((h=this.ref("receiverSel"))==null?void 0:h.value)||null;if(!n)return;const o=e.querySelector("[type='submit']");o.disabled=!0;try{await this.api.post(`/pc/projects/${this._projectId}/messages`,{sender_member_id:i,receiver_member_id:r||null,message:n}),this.ref("msgInput")&&(this.ref("msgInput").value=""),await this._loadMessages(!0);const u=this.ref("msgList");u&&(u.scrollTop=u.scrollHeight)}catch(u){alert("خطا در ارسال: "+((u==null?void 0:u.message)??""))}finally{o.disabled=!1}}));const t=this.ref("senderSel");t&&!t._bound&&(t._bound=!0,t.addEventListener("change",()=>{this._senderId=parseInt(t.value||"0"),this._renderMessages()}));const s=this.ref("refreshBtn");s&&!s._bound&&(s._bound=!0,s.addEventListener("click",()=>this._loadMessages()))}async _deleteMsg(e){if(confirm("حذف این پیام؟"))try{await this.api.delete(`/pc/messages/${e}`),await this._loadMessages(!0)}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}_startPoll(){this._pollTimer=setInterval(()=>{this._projectId&&this._loadMessages(!0)},3e4)}_stopPoll(){this._pollTimer&&(clearInterval(this._pollTimer),this._pollTimer=null)}destroy(){this._stopPoll(),super.destroy()}}const $n={not_started:"#94a3b8",in_progress:"#3b82f6",completed:"#22c55e",on_hold:"#f59e0b",cancelled:"#ef4444"};class kn extends x{constructor(e={}){super(e),this.cpmView=e.cpmView??null,this._projectId=null,this._tasks=[],this._wbs=[],this._project=null}async template(){return`
            <div class="cpm-section-wrap">
                <div class="cpm-section-notice" data-ref="notice">
                    <span>⚠️ لطفاً ابتدا یک پروژه از تب «پروژه‌ها» انتخاب کنید.</span>
                </div>
                <div data-ref="content" style="display:none">
                    <div class="cpm-toolbar">
                        <span data-ref="projLabel" style="font-weight:700;color:#1e293b;font-size:14px;"></span>
                        <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="calcCpmBtn">⚡ محاسبه CPM</button>
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄 بروزرسانی</button>
                    </div>
                    <div class="cpm-gantt-legend">
                        <span class="cpm-gantt-legend-item" style="--clr:#94a3b8">شروع نشده</span>
                        <span class="cpm-gantt-legend-item" style="--clr:#3b82f6">در حال انجام</span>
                        <span class="cpm-gantt-legend-item" style="--clr:#22c55e">تکمیل</span>
                        <span class="cpm-gantt-legend-item" style="--clr:#f59e0b">متوقف</span>
                        <span class="cpm-gantt-legend-item" style="--clr:#ef4444">لغو</span>
                        <span class="cpm-gantt-legend-item cpm-gantt-legend-item--critical" style="--clr:#dc2626">🔴 بحرانی</span>
                    </div>
                    <div class="cpm-gantt-wrap" data-ref="ganttWrap"></div>
                </div>
            </div>
        `}async afterRender(){}async onProjectChange(e){if(this._projectId=(e==null?void 0:e.id)??null,this._project=e,!this._projectId){this.ref("notice").style.display="flex",this.ref("content").style.display="none";return}this.ref("notice").style.display="none",this.ref("content").style.display="block",e!=null&&e.name&&(this.ref("projLabel").textContent=`🏗 ${e.name}`),this.on(this.ref("calcCpmBtn"),"click",()=>this._calculateCpm()),this.on(this.ref("refreshBtn"),"click",()=>this._loadAndRender()),await this._loadAndRender()}async _loadAndRender(){const e=this.ref("ganttWrap");e.innerHTML='<div class="cpm-loading" style="padding:40px 0"><div class="acc-spinner"></div></div>';try{const t=await this.api.get(`/pc/projects/${this._projectId}/workspace`,{scope:"gantt"});this._wbs=(t==null?void 0:t.wbs)??[],this._tasks=(t==null?void 0:t.tasks)??[],t!=null&&t.project&&(this._project=t.project),this._renderGantt(e)}catch{e.innerHTML='<div class="acc-empty">خطا در بارگذاری داده‌های گانت</div>'}}async _calculateCpm(){const e=this.ref("calcCpmBtn");e.disabled=!0,e.textContent="⏳ در حال محاسبه...";try{const t=await this.api.post(`/pc/projects/${this._projectId}/calculate-cpm`);if(t!=null&&t.success){const s=t.count??0;e.textContent=`✅ ${s} وظیفه محاسبه شد`,setTimeout(()=>{e.disabled=!1,e.textContent="⚡ محاسبه CPM"},2500),await this._loadAndRender()}else throw new Error((t==null?void 0:t.message)??"خطای نامشخص")}catch(t){alert("خطا در محاسبه CPM: "+((t==null?void 0:t.message)??"")),e.disabled=!1,e.textContent="⚡ محاسبه CPM"}}_renderGantt(e){const t=this._tasks.filter(d=>(d.early_start||d.start_date)&&(d.early_finish||d.end_date));if(!t.length){e.innerHTML=`<div class="acc-empty">وظیفه‌ای با تاریخ یافت نشد.<br>
                <small style="color:#94a3b8">برای نمایش گانت، ابتدا روی «⚡ محاسبه CPM» کلیک کنید یا تاریخ وظایف را تنظیم کنید.</small></div>`;return}const s=t.flatMap(d=>[new Date(d.early_start||d.start_date),new Date(d.early_finish||d.end_date)]);let a=new Date(Math.min(...s)),i=new Date(Math.max(...s));a.setDate(a.getDate()-2),i.setDate(i.getDate()+2);const n=Math.ceil((i-a)/864e5)||1,r={};this._wbs.forEach(d=>{r[d.id]=d.name});const o=this._buildWeekHeaders(a,n),l=[...t].sort((d,h)=>{const u=new Date(d.early_start||d.start_date),f=new Date(h.early_start||h.start_date);return u-f||d.sort_index-h.sort_index}),c=l.map(d=>{const h=d.early_start||d.start_date,u=d.early_finish||d.end_date,f=Math.max(0,Math.ceil((new Date(h)-a)/864e5)),m=Math.ceil((new Date(u)-a)/864e5),b=Math.max(1,m-f),v=(f/n*100).toFixed(3),y=(b/n*100).toFixed(3),$=d.is_critical?"#dc2626":$n[d.status]??"#94a3b8",w=parseFloat(d.progress??0).toFixed(0),_=r[d.wbs_id]?`<span class="cpm-gantt-wbs">${this.escape(r[d.wbs_id])}</span>`:"";return`
                <div class="cpm-gantt-row${d.is_critical?" cpm-gantt-row--critical":""}">
                    <div class="cpm-gantt-row__label" title="${this.escape(d.name)}">
                        ${_}
                        <span class="cpm-gantt-task-name">${this.escape(d.name)}</span>
                    </div>
                    <div class="cpm-gantt-row__track">
                        <div class="cpm-gantt-bar" style="left:${v}%;width:${y}%;background:${$};"
                             title="${this.escape(d.name)} | ${h} → ${u} | ${w}٪">
                            <div class="cpm-gantt-bar__fill" style="width:${w}%"></div>
                            <span class="cpm-gantt-bar__label">${w}٪</span>
                        </div>
                    </div>
                </div>
            `}).join("");e.innerHTML=`
            <div class="cpm-gantt-table">
                <div class="cpm-gantt-header">
                    <div class="cpm-gantt-header__label">وظیفه</div>
                    <div class="cpm-gantt-header__track">
                        ${o}
                    </div>
                </div>
                <div class="cpm-gantt-body">${c}</div>
            </div>
            <div class="cpm-gantt-range-info">
                📅 بازه: ${a.toISOString().slice(0,10)} تا ${i.toISOString().slice(0,10)}
                &nbsp;|&nbsp; ${n} روز &nbsp;|&nbsp; ${l.length} وظیفه
                &nbsp;|&nbsp; 🔴 بحرانی: ${l.filter(d=>d.is_critical).length}
            </div>
        `}_buildWeekHeaders(e,t){const s=[];let a=new Date(e);for(a.setDate(a.getDate()-a.getDay());a<=new Date(e.getTime()+t*864e5);){const i=new Date(a),n=new Date(a);n.setDate(n.getDate()+6);const o=(Math.max(0,(i-e)/864e5)/t*100).toFixed(2);if(s.push(`<div class="cpm-gantt-week" style="left:${o}%">
                    ${i.toISOString().slice(5,10)}
                 </div>`),a.setDate(a.getDate()+7),s.length>60)break}return s.join("")}}const M=p=>Number(p||0).toLocaleString("fa-IR");class En extends x{constructor(e={}){super(e),this.cpmView=e.cpmView??null,this._projectId=null,this._data=null,this._subTab="overview"}async template(){return`
            <div class="cpm-section-wrap">
                <div class="cpm-section-notice" data-ref="notice">
                    <span>⚠️ لطفاً ابتدا یک پروژه از تب «پروژه‌ها» انتخاب کنید.</span>
                </div>
                <div data-ref="content" style="display:none">
                    <div class="cpm-sub-tabs" data-ref="subTabs">
                        <button class="cpm-sub-tab cpm-sub-tab--active" data-tab="overview">📊 خلاصه مالی</button>
                        <button class="cpm-sub-tab" data-tab="assignments">⚙️ هزینه منابع</button>
                        <button class="cpm-sub-tab" data-tab="purchase">🛒 فاکتورهای خرید</button>
                        <button class="cpm-sub-tab" data-tab="payroll">👥 حقوق مرتبط</button>
                        <button class="cpm-sub-tab" data-tab="sales">🏠 فروش واحدها</button>
                        <button class="cpm-sub-tab" data-tab="events">📒 رویدادهای حسابداری</button>
                    </div>
                    <div data-ref="tabBody" style="margin-top:12px"></div>
                </div>
            </div>
        `}async afterRender(){}async onProjectChange(e){if(this._projectId=(e==null?void 0:e.id)??null,!this._projectId){this.ref("notice").style.display="flex",this.ref("content").style.display="none";return}this.ref("notice").style.display="none",this.ref("content").style.display="block",this.ref("subTabs").querySelectorAll(".cpm-sub-tab").forEach(t=>this.on(t,"click",()=>this._switchTab(t.dataset.tab))),await this._load()}async _load(){const e=this.ref("tabBody");e.innerHTML='<div class="cpm-loading"><div class="acc-spinner"></div></div>';try{const t=await this.api.get(`/pc/projects/${this._projectId}/financials`);this._data=t,this._renderTab()}catch{e.innerHTML='<div class="acc-empty">خطا در بارگذاری داده‌های مالی</div>'}}_switchTab(e){this._subTab=e,this.ref("subTabs").querySelectorAll(".cpm-sub-tab").forEach(t=>t.classList.toggle("cpm-sub-tab--active",t.dataset.tab===e)),this._renderTab()}_renderTab(){const e=this.ref("tabBody");if(this._data)switch(this._subTab){case"overview":this._renderOverview(e);break;case"assignments":this._renderAssignments(e);break;case"purchase":this._renderPurchase(e);break;case"payroll":this._renderPayroll(e);break;case"sales":this._renderSales(e);break;case"events":this._renderEvents(e);break}}_renderOverview(e){const t=this._data.summary,s=Math.min(100,t.budget_used_pct),a=s>=90?"#dc2626":s>=70?"#f59e0b":"#22c55e",i=t.net_pl>=0?"#059669":"#dc2626";e.innerHTML=`
            <div class="fin-kpi-grid">
                <div class="fin-kpi-card">
                    <div class="fin-kpi-card__label">💰 بودجه پروژه</div>
                    <div class="fin-kpi-card__value">${M(t.budget)} ریال</div>
                </div>
                <div class="fin-kpi-card">
                    <div class="fin-kpi-card__label">📦 هزینه منابع (تأیید)</div>
                    <div class="fin-kpi-card__value">${M(t.total_assignment_confirmed)} ریال</div>
                    <div class="fin-kpi-card__sub">از ${M(t.total_assignment_cost)} ریال کل</div>
                </div>
                <div class="fin-kpi-card">
                    <div class="fin-kpi-card__label">🛒 هزینه خرید</div>
                    <div class="fin-kpi-card__value">${M(t.total_purchase)} ریال</div>
                </div>
                <div class="fin-kpi-card">
                    <div class="fin-kpi-card__label">👥 هزینه حقوق</div>
                    <div class="fin-kpi-card__value">${M(t.total_payroll)} ریال</div>
                </div>
                <div class="fin-kpi-card fin-kpi-card--total">
                    <div class="fin-kpi-card__label">⚖️ کل هزینه‌ها</div>
                    <div class="fin-kpi-card__value">${M(t.total_cost)} ریال</div>
                </div>
                <div class="fin-kpi-card">
                    <div class="fin-kpi-card__label">🏠 درآمد فروش</div>
                    <div class="fin-kpi-card__value">${M(t.total_revenue)} ریال</div>
                </div>
                <div class="fin-kpi-card fin-kpi-card--pl" style="--pl-color:${i}">
                    <div class="fin-kpi-card__label">📈 سود / زیان خالص</div>
                    <div class="fin-kpi-card__value" style="color:${i}">
                        ${t.net_pl>=0?"+":""}${M(t.net_pl)} ریال
                    </div>
                </div>
            </div>

            <div class="fin-budget-bar-wrap">
                <div class="fin-budget-bar-header">
                    <span>🎯 مصرف بودجه</span>
                    <span style="font-weight:700;color:${a}">${t.budget_used_pct}٪</span>
                </div>
                <div class="fin-budget-bar-track">
                    <div class="fin-budget-bar-fill" style="width:${s}%;background:${a}"></div>
                </div>
                <div class="fin-budget-bar-labels">
                    <span>۰</span>
                    <span>${M(t.total_cost)} ریال مصرف شده</span>
                    <span>${M(t.budget)} ریال بودجه</span>
                </div>
            </div>

            <div class="fin-cost-breakdown">
                <div class="fin-cost-breakdown__title">تفکیک هزینه‌ها</div>
                ${this._buildBreakdownBar(t)}
            </div>
        `;const n=document.createElement("button");n.className="acc-btn acc-btn--secondary acc-btn--sm",n.style.marginTop="14px",n.textContent="🔄 بروزرسانی",n.addEventListener("click",()=>this._load()),e.appendChild(n)}_buildBreakdownBar(e){const t=e.total_cost||1,s=[{label:"منابع",val:e.total_assignment_confirmed,color:"#3b82f6"},{label:"خرید",val:e.total_purchase,color:"#8b5cf6"},{label:"حقوق",val:e.total_payroll,color:"#f59e0b"}].filter(n=>n.val>0);if(!s.length)return'<div style="color:#94a3b8;font-size:13px">هنوز هزینه‌ای ثبت نشده.</div>';const a=s.map(n=>{const r=(n.val/t*100).toFixed(1);return`<div class="fin-breakdown-segment" style="width:${r}%;background:${n.color}"
                         title="${n.label}: ${M(n.val)} ریال (${r}٪)"></div>`}).join(""),i=s.map(n=>`
            <div class="fin-breakdown-legend-item">
                <span class="fin-breakdown-dot" style="background:${n.color}"></span>
                <span>${n.label}: ${M(n.val)} ریال</span>
            </div>`).join("");return`
            <div class="fin-breakdown-bar">${a}</div>
            <div class="fin-breakdown-legend">${i}</div>
        `}_renderAssignments(e){const t=this._data.assignment_costs??[];if(!t.length){e.innerHTML='<div class="acc-empty">تخصیصی ثبت نشده است.</div>';return}const s=t.map(a=>`
            <tr class="${a.is_confirmed?"fin-row--confirmed":""}">
                <td>${this.escape(a.wbs_name||"—")}</td>
                <td>${this.escape(a.task_name)}</td>
                <td>${this.escape(a.resource_name)}<br>
                    <small style="color:#94a3b8">${this._resTypeLabel(a.resource_type)}</small>
                </td>
                <td>${a.quantity} ${this.escape(a.resource_unit||"")}</td>
                <td>${M(a.cost_per_unit)}</td>
                <td><strong>${M(a.total_cost)}</strong></td>
                <td>
                    ${a.is_confirmed?`<span class="cpm-badge" style="background:#ecfdf5;color:#059669">✅ تأیید شده</span>
                           <br><small style="color:#94a3b8">رویداد #${a.acc_event_id}</small>`:`<button class="acc-btn acc-btn--success acc-btn--xs" data-confirm="${a.id}">ثبت حسابداری</button>`}
                </td>
            </tr>
        `).join("");e.innerHTML=`
            <p class="fin-hint">با کلیک «ثبت حسابداری»، یک رویداد <code>PROJECT_COST</code> در ماژول حسابداری ثبت می‌شود.</p>
            <table class="acc-table" style="width:100%">
                <thead><tr>
                    <th>WBS</th><th>وظیفه</th><th>منبع</th>
                    <th>مقدار</th><th>نرخ واحد</th><th>هزینه کل</th><th>وضعیت</th>
                </tr></thead>
                <tbody>${s}</tbody>
                <tfoot><tr>
                    <td colspan="5" style="text-align:left;font-weight:700;padding:10px 12px">جمع تأیید شده:</td>
                    <td colspan="2" style="font-weight:700;color:#059669;padding:10px 12px">
                        ${M(this._data.summary.total_assignment_confirmed)} ریال
                    </td>
                </tr></tfoot>
            </table>
        `,e.querySelectorAll("[data-confirm]").forEach(a=>a.addEventListener("click",async()=>{a.disabled=!0,a.textContent="در حال ثبت...";try{await this.api.post(`/pc/assignments/${a.dataset.confirm}/confirm`,{}),await this._load(),this._switchTab("assignments")}catch(i){alert("خطا: "+((i==null?void 0:i.message)??"")),a.disabled=!1,a.textContent="ثبت حسابداری"}}))}_resTypeLabel(e){return{human:"انسانی",equipment:"تجهیزات",material:"مواد",other:"سایر"}[e]??e}_renderPurchase(e){const t=this._data.purchase_invoices??[],s=n=>({draft:"پیش‌نویس",finalized:"نهایی‌شده",cancelled:"لغوشده"})[n]??n,a=n=>({draft:"#f59e0b",finalized:"#059669",cancelled:"#dc2626"})[n]??"#6b7280",i=t.length?t.map(n=>`
            <tr>
                <td>${this.escape(n.invoice_no)}</td>
                <td>${this.escape(n.supplier_name||"—")}</td>
                <td>${n.invoice_date||"—"}</td>
                <td><span class="cpm-status-badge" style="background:${a(n.status)}22;color:${a(n.status)}">${s(n.status)}</span></td>
                <td>${M(n.net_amount)}</td>
                <td>${M(n.vat_amount)}</td>
                <td><strong>${M(n.total_amount)}</strong></td>
            </tr>
        `).join(""):'<tr><td colspan="7" style="text-align:center;padding:20px;color:#94a3b8">فاکتور خریدی مرتبط نشده است.<br><small>در ماژول خرید هنگام ثبت فاکتور، پروژه را انتخاب کنید.</small></td></tr>';e.innerHTML=`
            <p class="fin-hint">برای الصاق فاکتور خرید به این پروژه، در ماژول <strong>خرید ← فاکتورها</strong> هنگام ثبت فاکتور، فیلد «پروژه» را پر کنید.</p>
            <table class="acc-table" style="width:100%">
                <thead><tr>
                    <th>شماره فاکتور</th><th>تأمین‌کننده</th><th>تاریخ</th>
                    <th>وضعیت</th><th>مبلغ خالص</th><th>مالیات</th><th>جمع کل</th>
                </tr></thead>
                <tbody>${i}</tbody>
                ${t.length?`<tfoot><tr>
                    <td colspan="6" style="text-align:left;font-weight:700;padding:10px 12px">جمع نهایی‌شده:</td>
                    <td style="font-weight:700;color:#7c3aed;padding:10px 12px">${M(this._data.summary.total_purchase)} ریال</td>
                </tr></tfoot>`:""}
            </table>
        `}_renderPayroll(e){const t=this._data.payroll_periods??[],s=t.length?t.map(a=>`
            <tr>
                <td>${this.escape(a.period_name)}</td>
                <td>${a.period_code}</td>
                <td><span class="cpm-status-badge">${a.status}</span></td>
                <td>${M(a.total_gross)}</td>
                <td>${M(a.total_deductions)}</td>
                <td><strong>${M(a.total_net)}</strong></td>
            </tr>
        `).join(""):'<tr><td colspan="6" style="text-align:center;padding:20px;color:#94a3b8">دوره حقوقی مرتبطی یافت نشد.<br><small>در ماژول حقوق هنگام ایجاد دوره، پروژه را انتخاب کنید.</small></td></tr>';e.innerHTML=`
            <p class="fin-hint">برای الصاق دوره حقوقی به این پروژه، در ماژول <strong>حقوق ← دوره‌ها</strong> هنگام ایجاد دوره، فیلد «پروژه» را پر کنید.</p>
            <table class="acc-table" style="width:100%">
                <thead><tr>
                    <th>دوره</th><th>کد</th><th>وضعیت</th>
                    <th>ناخالص</th><th>کسورات</th><th>خالص</th>
                </tr></thead>
                <tbody>${s}</tbody>
                ${t.length?`<tfoot><tr>
                    <td colspan="5" style="text-align:left;font-weight:700;padding:10px 12px">جمع خالص (نهایی):</td>
                    <td style="font-weight:700;color:#f59e0b;padding:10px 12px">${M(this._data.summary.total_payroll)} ریال</td>
                </tr></tfoot>`:""}
            </table>
        `}_renderSales(e){const t=this._data.sold_units??[],s=t.length?t.map(a=>`
            <tr>
                <td>${this.escape(a.code||"")}</td>
                <td>${this.escape(a.name)}</td>
                <td>${a.floor??"—"}</td>
                <td>${M(a.area_sqm)} m²</td>
                <td>${this.escape(a.buyer_name||"—")}</td>
                <td>${this.escape(a.invoice_no||"—")}</td>
                <td>${a.invoice_date||"—"}</td>
                <td><strong style="color:#059669">${M(a.invoice_amount)}</strong></td>
            </tr>
        `).join(""):'<tr><td colspan="8" style="text-align:center;padding:20px;color:#94a3b8">واحدی فروخته نشده است.</td></tr>';e.innerHTML=`
            <table class="acc-table" style="width:100%">
                <thead><tr>
                    <th>کد</th><th>نام واحد</th><th>طبقه</th><th>متراژ</th>
                    <th>خریدار</th><th>شماره فاکتور</th><th>تاریخ</th><th>مبلغ</th>
                </tr></thead>
                <tbody>${s}</tbody>
                ${t.length?`<tfoot><tr>
                    <td colspan="7" style="text-align:left;font-weight:700;padding:10px 12px">جمع درآمد:</td>
                    <td style="font-weight:700;color:#059669;padding:10px 12px">${M(this._data.summary.total_revenue)} ریال</td>
                </tr></tfoot>`:""}
            </table>
        `}_renderEvents(e){const t=this._data.acc_events??[],s=n=>({pending:"#f59e0b",posted:"#059669",confirmed:"#2563eb",cancelled:"#dc2626",failed:"#dc2626"})[n]??"#6b7280",a=n=>({PROJECT_COST:"هزینه پروژه",SALE_INVOICE:"فروش واحد"})[n]??n,i=t.length?t.map(n=>{var r;return`
            <tr>
                <td>#${n.id}</td>
                <td><span class="cpm-badge" style="background:#eff6ff;color:#2563eb">${a(n.event_type)}</span></td>
                <td><span class="cpm-status-badge" style="background:${s(n.workflow_state)}22;color:${s(n.workflow_state)}">${n.workflow_state}</span></td>
                <td><strong>${M(n.amount)}</strong></td>
                <td style="font-size:11px;color:#64748b">${this.escape(n.description||"")}</td>
                <td style="font-size:11px">${((r=n.created_at)==null?void 0:r.slice(0,16))??""}</td>
            </tr>
        `}).join(""):'<tr><td colspan="6" style="text-align:center;padding:20px;color:#94a3b8">رویداد حسابداری‌ای یافت نشد.</td></tr>';e.innerHTML=`
            <p class="fin-hint">رویدادهای <code>PROJECT_COST</code> و <code>SALE_INVOICE</code> مرتبط با این پروژه در اینجا نمایش داده می‌شوند.</p>
            <table class="acc-table" style="width:100%">
                <thead><tr>
                    <th>#</th><th>نوع رویداد</th><th>وضعیت</th><th>مبلغ</th><th>توضیحات</th><th>تاریخ</th>
                </tr></thead>
                <tbody>${i}</tbody>
            </table>
        `}}const He={pending:{label:"در انتظار",color:"#94a3b8",icon:"⏸"},active:{label:"در حال اجرا",color:"#3b82f6",icon:"🔄"},completed:{label:"تکمیل شده",color:"#10b981",icon:"✅"},skipped:{label:"رد شده",color:"#f59e0b",icon:"⏭"},blocked:{label:"مسدود",color:"#ef4444",icon:"🚫"}};class Ln extends x{constructor(e){super(e),this._project=null,this._instance=null,this._activeStageId=null,this._templates=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🔄 Workflow پروژه</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--secondary" data-ref="historyBtn">📜 تاریخچه</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap" style="display:flex;flex-direction:column;gap:14px;">
                <div class="acc-loading">⏳ بارگذاری...</div>
            </div>
        </div>`}async afterRender(){var e,t,s;this._project=((e=this.store)==null?void 0:e.get("context.project"))??null,await this._loadTemplates(),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("historyBtn"),"click",()=>this._showHistory()),this._unsubscribe=(s=(t=this.store)==null?void 0:t.subscribe)==null?void 0:s.call(t,"context.project",a=>{this._project=a,this._load()})}async _loadTemplates(){try{const e=await this.api.get("/wf/templates");this._templates=(e==null?void 0:e.data)??[]}catch{}}async _load(){var e,t,s,a;if(!((e=this._project)!=null&&e.id)){this.ref("wrap").innerHTML=`
                <div class="acc-empty" style="padding:40px;text-align:center;">
                    <div style="font-size:48px;margin-bottom:8px;">📊</div>
                    <div>لطفاً یک پروژه را از تب «پروژه‌ها» انتخاب کنید</div>
                </div>`;return}this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری workflow...</div>';try{const i=await this.api.get(`/wf/instances/project/${this._project.id}`);if(this._instance=(i==null?void 0:i.data)??null,!this._instance)this._renderTemplatePicker();else{if(!this._activeStageId){const n=(t=this._instance.stages)==null?void 0:t.find(r=>r.status==="active");this._activeStageId=(n==null?void 0:n.id)??((a=(s=this._instance.stages)==null?void 0:s[0])==null?void 0:a.id)}this._render()}}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_renderTemplatePicker(){if(!this._templates.length){this.ref("wrap").innerHTML='<div class="acc-empty">قالبی تعریف نشده است</div>';return}this.ref("wrap").innerHTML=`
        <div style="background:#eff6ff;padding:14px;border-radius:8px;color:#1e40af;font-size:13px;">
            💡 برای این پروژه (<b>${this.escape(this._project.name||`#${this._project.id}`)}</b>) workflowی تعریف نشده است.
            یک قالب انتخاب کنید:
        </div>
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;">
            ${this._templates.map(e=>`
            <div style="border:1.5px solid ${e.color};border-radius:10px;padding:14px;background:#fff;cursor:pointer;transition:transform .15s;"
                 class="wf-tpl-card" data-tpl="${e.id}"
                 onmouseenter="this.style.transform='translateY(-2px)';this.style.boxShadow='0 4px 12px rgba(0,0,0,.1)'"
                 onmouseleave="this.style.transform='';this.style.boxShadow=''">
                <div style="font-size:24px;margin-bottom:6px;">${e.icon}</div>
                <div style="font-weight:700;font-size:14px;color:${e.color};">${this.escape(e.name)}</div>
                <div style="font-size:12px;color:#64748b;margin-top:4px;">${this.escape(e.description??"")}</div>
                <div style="font-size:11px;color:#94a3b8;margin-top:8px;">
                    📋 ${e.stage_count} مرحله | ✅ ${e.instance_count} پروژه استفاده شده
                </div>
                <button class="acc-btn acc-btn--primary acc-btn--sm" style="margin-top:10px;background:${e.color};border-color:${e.color};">
                    🚀 اعمال این قالب
                </button>
            </div>`).join("")}
        </div>`,this.ref("wrap").querySelectorAll(".wf-tpl-card").forEach(e=>e.addEventListener("click",()=>this._applyTemplate(parseInt(e.dataset.tpl))))}async _applyTemplate(e){const t=this._templates.find(s=>s.id==e);if(confirm(`اعمال قالب «${t==null?void 0:t.name}» روی این پروژه؟`))try{await this.api.post("/wf/instances",{project_id:this._project.id,template_id:e}),this._toast("✅ Workflow ایجاد شد","#10b981"),this._load()}catch(s){alert("خطا: "+((s==null?void 0:s.message)??""))}}_render(){var n;const e=this._instance,t=(n=e.stages)==null?void 0:n.find(r=>r.id==this._activeStageId);this.ref("wrap").innerHTML=`
        ${this._renderHeader(e)}
        ${this._renderStepper(e)}
        ${t?this._renderStagePanel(t):""}
        `,this.ref("wrap").querySelectorAll("[data-stage-id]").forEach(r=>r.addEventListener("click",()=>{this._activeStageId=parseInt(r.dataset.stageId),this._render()})),this.ref("wrap").querySelectorAll("[data-task]").forEach(r=>r.addEventListener("change",()=>this._toggleTask(parseInt(r.dataset.task),r.checked)));const s=this.ref("wrap").querySelector("[data-action=advance]");s&&s.addEventListener("click",()=>this._advance(t));const a=this.ref("wrap").querySelector("[data-action=start]");a&&a.addEventListener("click",()=>this._startStage(t));const i=this.ref("wrap").querySelector("[data-action=edit-stage]");i&&i.addEventListener("click",()=>this._editStage(t))}_renderHeader(e){const t=parseFloat(e.progress_pct??0);return`
        <div style="background:linear-gradient(135deg,#eff6ff 0%,#f0fdf4 100%);padding:16px;border-radius:10px;border:1px solid #e2e8f0;">
            <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;">
                <div>
                    <div style="font-size:13px;color:#64748b;">قالب workflow:</div>
                    <div style="font-weight:700;font-size:16px;">
                        ${e.template_icon??""} ${this.escape(e.template_name??"—")}
                    </div>
                </div>
                <div style="text-align:left;">
                    <div style="font-size:12px;color:#64748b;">پیشرفت کل</div>
                    <div style="font-weight:700;font-size:24px;color:#10b981;">${t}%</div>
                </div>
            </div>
            <div style="height:8px;background:#e2e8f0;border-radius:4px;overflow:hidden;margin-top:10px;">
                <div style="height:100%;background:linear-gradient(90deg,#3b82f6,#10b981);width:${t}%;transition:width .3s;"></div>
            </div>
        </div>`}_renderStepper(e){return`
        <div style="overflow-x:auto;padding:8px 0;">
            <div style="display:flex;gap:0;align-items:stretch;min-width:100%;">
                ${e.stages.map((t,s)=>{const a=He[t.status]??He.pending,i=t.id==this._activeStageId;return`
                    <div data-stage-id="${t.id}" style="flex:1;min-width:130px;cursor:pointer;display:flex;flex-direction:column;align-items:center;padding:0 4px;">
                        <!-- خط اتصال -->
                        <div style="height:3px;width:100%;background:linear-gradient(90deg,
                            ${s===0?"transparent":t.status==="pending"?"#e2e8f0":a.color} 0%,
                            ${s===0?"transparent":t.status==="pending"?"#e2e8f0":a.color} 50%,
                            ${s===e.stages.length-1?"transparent":t.status==="pending"?"#e2e8f0":a.color} 100%);
                            margin-top:20px;"></div>

                        <!-- آیکن مرحله -->
                        <div style="background:${i?a.color:t.status==="pending"?"#fff":a.color+"1a"};
                                    color:${i?"#fff":a.color};
                                    border:3px solid ${a.color};
                                    width:44px;height:44px;border-radius:50%;
                                    display:flex;align-items:center;justify-content:center;font-size:18px;
                                    margin-top:-25px;
                                    box-shadow:${i?"0 4px 12px "+a.color+"66":"none"};
                                    transition:all .2s;">
                            ${t.icon||a.icon}
                        </div>

                        <!-- نام -->
                        <div style="margin-top:6px;text-align:center;">
                            <div style="font-size:12px;font-weight:${i?"700":"500"};color:${i?a.color:"#475569"};">
                                ${this.escape(t.name)}
                            </div>
                            <div style="font-size:10px;color:#94a3b8;margin-top:2px;">
                                ${t.tasks_done}/${t.tasks_total} ${a.label}
                            </div>
                        </div>
                    </div>`}).join("")}
            </div>
        </div>`}_renderStagePanel(e){var i,n;const t=He[e.status]??He.pending,s=e.status==="active",a=e.status==="pending";return`
        <div style="border:1.5px solid ${t.color};border-radius:10px;overflow:hidden;background:#fff;">
            <!-- هدر مرحله -->
            <div style="background:${t.color};color:#fff;padding:12px 16px;display:flex;justify-content:space-between;align-items:center;">
                <div>
                    <div style="font-size:18px;font-weight:700;">${e.icon} ${this.escape(e.name)}</div>
                    <div style="font-size:12px;opacity:.9;margin-top:2px;">${t.icon} ${t.label} — ${e.progress_pct}% تکمیل</div>
                </div>
                <div style="display:flex;gap:6px;">
                    ${a?`<button class="acc-btn acc-btn--sm" data-action="start" style="background:#fff;color:${t.color};">▶️ شروع</button>`:""}
                    ${s?`<button class="acc-btn acc-btn--sm" data-action="advance" style="background:#fff;color:${t.color};font-weight:700;">⏭️ مرحله بعد</button>`:""}
                    <button class="acc-btn acc-btn--sm" data-action="edit-stage" style="background:rgba(255,255,255,.2);color:#fff;border-color:#fff;">✏️</button>
                </div>
            </div>

            <!-- بدنه: tasks + gates + اطلاعات -->
            <div style="display:grid;grid-template-columns:2fr 1fr;gap:16px;padding:16px;">

                <!-- Tasks -->
                <div>
                    <h4 style="margin:0 0 10px 0;font-size:13px;color:#475569;">📋 Tasks (${e.tasks_done}/${e.tasks_total})</h4>
                    ${(i=e.tasks)!=null&&i.length?e.tasks.map(r=>{const o=r.status==="completed";return`
                        <label style="display:flex;gap:8px;align-items:flex-start;padding:8px;border-radius:6px;cursor:pointer;
                                      background:${o?"#f0fdf4":"#f8fafc"};margin-bottom:4px;border:1px solid ${o?"#86efac":"#e2e8f0"};">
                            <input type="checkbox" data-task="${r.id}" ${o?"checked":""} style="margin-top:2px;">
                            <div style="flex:1;">
                                <div style="font-size:13px;font-weight:600;${o?"text-decoration:line-through;color:#94a3b8;":"color:#1e293b;"}">
                                    ${this.escape(r.title)}
                                    ${r.is_required==1?'<small style="color:#ef4444;">*</small>':""}
                                </div>
                                ${r.assigned_name?`<div style="font-size:11px;color:#64748b;margin-top:2px;">👤 ${this.escape(r.assigned_name)}</div>`:""}
                                ${r.due_date?`<div style="font-size:11px;color:#f59e0b;margin-top:2px;">📅 ${r.due_date}</div>`:""}
                                ${o&&r.completed_by_name?`<div style="font-size:10px;color:#10b981;margin-top:2px;">✅ توسط ${this.escape(r.completed_by_name)}</div>`:""}
                            </div>
                        </label>`}).join(""):'<div style="color:#94a3b8;font-size:12px;padding:12px;">taskی تعریف نشده</div>'}
                </div>

                <!-- Gates + اطلاعات -->
                <div>
                    <h4 style="margin:0 0 10px 0;font-size:13px;color:#475569;">🚦 Gates ورود به مرحله بعد</h4>
                    ${(n=e.gates)!=null&&n.length?e.gates.map(r=>`
                        <div style="font-size:12px;padding:6px;background:#fef9c3;border-right:3px solid #eab308;margin-bottom:4px;border-radius:4px;">
                            ⚠️ ${this.escape(r.title)}
                        </div>
                    `).join(""):'<div style="color:#94a3b8;font-size:12px;">بدون gate</div>'}

                    <h4 style="margin:14px 0 10px 0;font-size:13px;color:#475569;">💰 بودجه</h4>
                    <div style="background:#eff6ff;padding:10px;border-radius:6px;font-size:12px;">
                        <div>اختصاص: <b>${this._fmt(e.budget_amount)} ﷼</b></div>
                        <div style="color:#dc2626;margin-top:4px;">مصرف: <b>${this._fmt(e.spent_amount)} ﷼</b></div>
                        ${e.budget_amount>0?`
                        <div style="margin-top:6px;height:6px;background:#fff;border-radius:3px;overflow:hidden;">
                            <div style="height:100%;background:${e.spent_amount>e.budget_amount?"#ef4444":"#10b981"};width:${Math.min(100,e.spent_amount/e.budget_amount*100)}%;"></div>
                        </div>`:""}
                    </div>

                    ${e.planned_start_date||e.actual_start_date?`
                    <h4 style="margin:14px 0 10px 0;font-size:13px;color:#475569;">📅 زمانبندی</h4>
                    <div style="font-size:11px;color:#64748b;line-height:1.7;">
                        ${e.planned_start_date?`<div>برنامه شروع: ${e.planned_start_date}</div>`:""}
                        ${e.planned_end_date?`<div>برنامه پایان: ${e.planned_end_date}</div>`:""}
                        ${e.actual_start_date?`<div style="color:#3b82f6;">واقعی شروع: ${e.actual_start_date}</div>`:""}
                        ${e.actual_end_date?`<div style="color:#10b981;">واقعی پایان: ${e.actual_end_date}</div>`:""}
                    </div>`:""}
                </div>
            </div>

            ${e.notes?`
            <div style="padding:0 16px 16px;">
                <div style="background:#fff7ed;padding:10px;border-right:3px solid #f97316;border-radius:6px;font-size:12px;">
                    📝 ${this.escape(e.notes)}
                </div>
            </div>`:""}
        </div>`}async _toggleTask(e,t){try{t?await this.api.post(`/wf/tasks/${e}/complete`,{}):await this.api.put(`/wf/tasks/${e}`,{status:"pending"}),this._load()}catch(s){alert("خطا: "+((s==null?void 0:s.message)??""))}}async _startStage(e){try{await this.api.post(`/wf/stages/${e.id}/start`,{}),this._toast("▶️ مرحله شروع شد"),this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}async _advance(e){var t;try{const s=await this.api.post(`/wf/stages/${e.id}/advance`,{});s!=null&&s.completed?this._toast("🎉 Workflow کامل شد!","#10b981"):this._toast("⏭️ به مرحله بعد رفت","#10b981"),this._activeStageId=((t=s==null?void 0:s.next_stage)==null?void 0:t.id)??null,this._load()}catch(s){if((s==null?void 0:s.code)===422||s!=null&&s.message&&s.message.includes("ناتمام")){if(confirm(`${s.message}

آیا با force رد کنیم؟`))try{await this.api.post(`/wf/stages/${e.id}/advance?force=1`,{}),this._load()}catch(a){alert("خطا: "+((a==null?void 0:a.message)??""))}}else alert("خطا: "+((s==null?void 0:s.message)??""))}}_editStage(e){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:460px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">✏️ ویرایش مرحله «${this.escape(e.name)}»</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>برنامه شروع</label>
                        <input name="planned_start_date" type="date" value="${e.planned_start_date??""}">
                    </div>
                    <div class="acc-form-group"><label>برنامه پایان</label>
                        <input name="planned_end_date" type="date" value="${e.planned_end_date??""}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>بودجه (ریال)</label>
                        <input name="budget_amount" type="number" value="${e.budget_amount??0}">
                    </div>
                    <div class="acc-form-group"><label>هزینه شده (ریال)</label>
                        <input name="spent_amount" type="number" value="${e.spent_amount??0}">
                    </div>
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="3">${this.escape(e.notes??"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector("[data-action=cancel]").addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries());try{await this.api.put(`/wf/stages/${e.id}`,i),s(),this._load()}catch(n){alert("خطا: "+((n==null?void 0:n.message)??""))}})}async _showHistory(){if(this._instance)try{const e=await this.api.get(`/wf/instances/${this._instance.id}/transitions`),t=(e==null?void 0:e.data)??[],s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
            <div class="acc-modal" style="max-width:600px;max-height:80vh;overflow-y:auto;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">📜 تاریخچه workflow</div>
                ${t.length?t.map(i=>`
                <div style="border-right:3px solid #3b82f6;padding:10px 12px;margin-bottom:8px;background:#f8fafc;border-radius:6px;">
                    <div style="font-weight:700;font-size:13px;">
                        ${this._actionIcon(i.action)} ${this.escape(i.notes)}
                    </div>
                    <div style="font-size:11px;color:#64748b;margin-top:4px;">
                        ${i.from_stage_name?`از: ${this.escape(i.from_stage_name)} → `:""}
                        ${i.to_stage_name?`به: ${this.escape(i.to_stage_name)}`:""}
                    </div>
                    <div style="font-size:11px;color:#94a3b8;margin-top:3px;">
                        👤 ${this.escape(i.actor_name||"سیستم")} — ${i.created_at}
                    </div>
                </div>`).join(""):'<div class="acc-empty">تاریخچه‌ای نیست</div>'}
                <div class="acc-modal__actions">
                    <button class="acc-btn acc-btn--secondary" data-action="close">بستن</button>
                </div>
            </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action=close]").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()})}catch{}}_actionIcon(e){return{create:"🚀",start_stage:"▶️",advance:"⏭️",complete:"🎉"}[e]??"🔄"}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}destroy(){var e,t;(e=this._unsubscribe)==null||e.call(this),(t=super.destroy)==null||t.call(this)}}class Sn extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🎨 قالب‌های Workflow</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ قالب جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._toast("⚠️ ساخت قالب جدید فعلاً در دست توسعه است","#f59e0b"))}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/wf/templates");this._rows=(e==null?void 0:e.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">قالبی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(320px,1fr));gap:14px;">
            ${this._rows.map(e=>`
            <div style="border:1.5px solid ${e.color};border-radius:10px;padding:14px;background:#fff;">
                <div style="display:flex;justify-content:space-between;align-items:start;">
                    <div>
                        <div style="font-size:28px;">${e.icon}</div>
                        <div style="font-weight:700;font-size:15px;color:${e.color};margin-top:4px;">${this.escape(e.name)}</div>
                        <small style="color:#94a3b8;font-family:monospace;">${this.escape(e.code)}</small>
                        ${e.is_system==1?'<span style="background:#dbeafe;color:#1e40af;padding:1px 6px;border-radius:4px;font-size:10px;margin-right:6px;">سیستمی</span>':""}
                    </div>
                </div>
                ${e.description?`<div style="font-size:12px;color:#64748b;margin-top:8px;">${this.escape(e.description)}</div>`:""}
                <div style="display:flex;gap:8px;margin-top:12px;font-size:12px;">
                    <span>📋 <b>${e.stage_count}</b> مرحله</span>
                    <span>✅ <b>${e.instance_count}</b> پروژه</span>
                </div>
                <div style="display:flex;gap:6px;margin-top:10px;">
                    <button class="acc-btn acc-btn--xs acc-btn--primary" data-view="${e.id}">👁️ نمایش جزئیات</button>
                </div>
            </div>`).join("")}
        </div>`,this.ref("wrap").querySelectorAll("[data-view]").forEach(e=>e.addEventListener("click",()=>this._viewTemplate(parseInt(e.dataset.view))))}async _viewTemplate(e){try{const t=await this.api.get(`/wf/templates/${e}`),s=t==null?void 0:t.data;if(!s)return;const a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
            <div class="acc-modal" style="max-width:760px;max-height:90vh;overflow-y:auto;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${s.icon} ${this.escape(s.name)}</div>
                <div style="font-size:12px;color:#64748b;margin-bottom:14px;">${this.escape(s.description??"")}</div>

                ${(s.stages??[]).map((n,r)=>{var o,l;return`
                <div style="border-right:3px solid ${n.color};padding:10px 14px;background:#f8fafc;border-radius:6px;margin-bottom:8px;">
                    <div style="font-weight:700;font-size:14px;color:${n.color};">
                        ${n.icon} ${r+1}. ${this.escape(n.name)}
                        <small style="color:#94a3b8;margin-right:8px;">${n.estimated_days} روز | ${n.budget_pct}% بودجه</small>
                    </div>
                    ${(o=n.tasks)!=null&&o.length?`
                    <div style="margin-top:8px;">
                        <b style="font-size:12px;color:#475569;">Tasks:</b>
                        <ul style="font-size:12px;color:#64748b;margin:4px 0 0 0;padding-right:20px;">
                            ${n.tasks.map(c=>`<li>${this.escape(c.title)}</li>`).join("")}
                        </ul>
                    </div>`:""}
                    ${(l=n.gates)!=null&&l.length?`
                    <div style="margin-top:8px;">
                        <b style="font-size:12px;color:#475569;">🚦 Gates:</b>
                        <ul style="font-size:12px;color:#eab308;margin:4px 0 0 0;padding-right:20px;">
                            ${n.gates.map(c=>`<li>${this.escape(c.title)}</li>`).join("")}
                        </ul>
                    </div>`:""}
                </div>
                `}).join("")}

                <div class="acc-modal__actions">
                    <button class="acc-btn acc-btn--secondary" data-action="close">بستن</button>
                </div>
            </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action=close]").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()})}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const it=[{key:"projects",icon:"🏗",title:"پروژه‌ها",desc:"مدیریت پروژه‌ها",Class:vn},{key:"workflow",icon:"🔄",title:"Workflow",desc:"ساختار پروژه",Class:Ln},{key:"wf-tpl",icon:"🎨",title:"قالب‌ها",desc:"قالب workflow",Class:Sn},{key:"tasks",icon:"✅",title:"وظایف",desc:"تسک و WBS",Class:yn},{key:"resources",icon:"👷",title:"منابع",desc:"منابع و تخصیص",Class:_n},{key:"members",icon:"👥",title:"اعضا",desc:"تیم پروژه",Class:xn},{key:"messages",icon:"💬",title:"پیام‌ها",desc:"انتقال پیام",Class:wn},{key:"gantt",icon:"📊",title:"گانت",desc:"نمودار گانت",Class:kn},{key:"financials",icon:"💰",title:"مالی",desc:"یکپارچه‌سازی مالی",Class:En}];class Zt extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="projects",this._sections={},this._projectId=null,this._selectedProject=null}async template(){const t=it.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
            </div>
        `).join(""),s=it.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="cpm-header-bar" data-ref="headerBar">
                <div class="cpm-project-badge" data-ref="projectBadge" style="display:none">
                    <span class="cpm-badge-icon">🏗</span>
                    <span data-ref="projectBadgeText">—</span>
                    <button class="cpm-badge-close" data-ref="clearProject" title="برگشت به لیست">✕</button>
                </div>
            </div>
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>this.on(t,"click",()=>this._switch(t.dataset.section))),this.on(this.ref("clearProject"),"click",()=>this._clearProject()),await this._mount(this._active)}selectProject(t){this._projectId=t.id,this._selectedProject=t;const s=this.ref("projectBadge");s.style.display="flex",this.ref("projectBadgeText").textContent=`${t.name} (#${t.id})`,Object.values(this._sections).forEach(a=>{typeof a.onProjectChange=="function"&&a.onProjectChange(t)})}_clearProject(){this._projectId=null,this._selectedProject=null,this.ref("projectBadge").style.display="none",Object.values(this._sections).forEach(t=>{typeof t.onProjectChange=="function"&&t.onProjectChange(null)})}async _switch(t){if(t===this._active)return;this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(a=>a.classList.toggle("sp-nav-card--active",a.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(a=>a.classList.toggle("acc-section--active",a.dataset.panel===t)),this._active=t,await this._mount(t);const s=this._sections[t];s&&this._selectedProject&&typeof s.onProjectChange=="function"&&s.onProjectChange(this._selectedProject)}async _mount(t){if(this._sections[t])return;const s=it.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api,cpmView:this});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(Zt,"title","📊 کنترل پروژه"),E.register("cpm",Zt);class Xt extends C{constructor(e={}){super(e),this.api=e.api,this.state={users:[],filteredUsers:[],selectedUser:null,permissions:[],loadingUsers:!1,loadingPermissions:!1,saving:!1,searchQuery:"",expandedModules:{},userCache:null,permissionCache:{},saveQueue:{},saveTimers:{},roles:[],loadingRoles:!1,selectedRole:null,userFilter:null}}template(){return`

    
    <div class="acc-permission-manager">

    <div class="acc-pm-header">
        <div class="acc-pm-title">
            <h2>مدیریت دسترسی کاربران</h2>
            <p>انتخاب کاربر، مشاهده سطح دسترسی و ویرایش permission ها با ساختار ماژولار</p>
        </div>

        <div class="acc-pm-toolbar">
            <button class="acc-btn" data-ref="expandAllBtn" type="button">باز کردن همه</button>
            <button class="acc-btn" data-ref="collapseAllBtn" type="button">بستن همه</button>
            <button class="acc-btn" data-ref="refreshBtn" type="button">بروزرسانی</button>
        </div>
    </div>

    <div class="acc-layout">
        <div class="acc-sidebar">

            <div class="acc-user-search">
                <input
                    type="text"
                    placeholder="جستجوی کاربر..."
                    data-ref="searchInput"
                />
            </div>

            <div class="acc-user-list" data-ref="userList"></div>
        </div>

        <div class="acc-main">
            <div data-ref="permissionArea"></div>
        </div>
    </div>

</div>
`}async afterRender(){this.$search=this.ref("searchInput"),this.$list=this.ref("userList"),this.$area=this.ref("permissionArea"),this.$expandAllBtn=this.ref("expandAllBtn"),this.$collapseAllBtn=this.ref("collapseAllBtn"),this.$refreshBtn=this.ref("refreshBtn"),this.searchTimer=null,this.on(this.$search,"input",()=>{clearTimeout(this.searchTimer),this.searchTimer=setTimeout(()=>{this.state.searchQuery=this.$search.value.trim().toLowerCase(),this.filterUsers()},180)}),this.on(this.$expandAllBtn,"click",()=>{this.expandAllModules()}),this.on(this.$collapseAllBtn,"click",()=>{this.collapseAllModules()}),this.on(this.$refreshBtn,"click",()=>{var e;(e=this.state.selectedUser)!=null&&e.id?this.loadPermissions(this.state.selectedUser.id,{force:!0}):this.loadUsers({force:!0})}),await this.loadRoles()}async loadRoles(){this.state.loadingRoles=!0,this.$list.innerHTML='<div class="acc-loading">در حال بارگذاری نقش‌ها...</div>';try{const e=await this.api.get("/users/roles");this.state.roles=Array.isArray(e==null?void 0:e.data)?e.data:[],this.renderRoles()}catch(e){console.error(e),this.$list.innerHTML='<div class="acc-error">خطا در دریافت نقش‌ها</div>'}finally{this.state.loadingRoles=!1}}renderRoles(){if(!this.state.roles.length){this.$list.innerHTML='<div class="acc-empty">نقشی یافت نشد</div>';return}this.$list.innerHTML=this.state.roles.map(e=>`
                <div class="acc-user-item ${this.state.selectedRole===e.role?"active":""}" data-role="${e.role}">
                    <div class="acc-user-name">${this.escape(e.role)}</div>
                    <div class="acc-user-meta">${e.total_users} کاربر</div>
                </div>
                `).join(""),this.$list.querySelectorAll("[data-role]").forEach(e=>{this.on(e,"click",()=>{this.selectRole(e.dataset.role)})})}async selectRole(e){this.state.selectedRole=e,this.state.selectedUser=null,this.$area.innerHTML='<div class="acc-empty">یک کاربر را انتخاب کنید</div>',await this.loadUsers({force:!0,role:e})}async loadUsers(e={}){const{force:t=!1,role:s=null}=e;this.state.loadingUsers=!0,this.renderUserListLoading();try{const a=s?`?role=${encodeURIComponent(s)}`:"",i=await this.api.get(`/users${a}`),n=Array.isArray(i==null?void 0:i.data)?i.data:[];this.state.users=n,this.state.filteredUsers=n,this.renderUserList()}catch(a){console.error(a),this.$list.innerHTML='<div class="acc-error">خطا در دریافت کاربران</div>'}finally{this.state.loadingUsers=!1}}filterUsers(){const e=this.state.searchQuery,t=this.state.userFilter;let s=[...this.state.users];e&&(s=s.filter(a=>{const i=(a.name||"").toLowerCase(),n=(a.username||"").toLowerCase(),r=(a.email||"").toLowerCase();return i.includes(e)||n.includes(e)||r.includes(e)})),t==="enabled"&&(s=s.filter(a=>(a.permission_count||0)>0)),t==="modules"&&(s=s.filter(a=>(a.module_count||0)>0)),t==="rows"&&(s=s.filter(a=>(a.row_count||0)>0)),this.state.filteredUsers=s,this.renderUserList()}renderUserListLoading(){this.$list.innerHTML='<div class="acc-loading">در حال بارگذاری کاربران...</div>'}renderUserList(){let e="";if(this.state.selectedRole&&(e=`
                <div class="acc-back-to-roles">
                    <button class="acc-btn acc-btn-sm" data-ref="backToRoles">
                        ← بازگشت به نقش‌ها
                    </button>
                </div>`),!this.state.filteredUsers.length){this.$list.innerHTML=e+'<div class="acc-empty">کاربری یافت نشد</div>';const s=this.$list.querySelector("[data-ref='backToRoles']");s&&this.on(s,"click",async()=>{this.state.selectedRole=null,this.state.selectedUser=null,this.state.users=[],this.state.filteredUsers=[],this.$area.innerHTML='<div class="acc-empty">یک نقش را انتخاب کنید</div>',await this.loadRoles()});return}this.$list.innerHTML=e+this.state.filteredUsers.map(s=>{var i;return`
                <div class="acc-user-item ${String(((i=this.state.selectedUser)==null?void 0:i.id)||"")===String(s.id)?"active":""}" data-user="${s.id}">
                    <div class="acc-user-name">${this.escape(s.name||s.username||`User #${s.id}`)}</div>
                    <div class="acc-user-meta">
                        ${this.escape(s.username||"")}
                        ${s.email?` • ${this.escape(s.email)}`:""}
                    </div>
                </div>
                `}).join(""),this.$list.querySelectorAll("[data-user]").forEach(s=>{this.on(s,"click",()=>{const a=s.dataset.user;this.selectUser(a)})});const t=this.$list.querySelector("[data-ref='backToRoles']");t&&this.on(t,"click",async()=>{this.state.selectedRole=null,this.state.selectedUser=null,this.state.users=[],this.state.filteredUsers=[],this.$area.innerHTML='<div class="acc-empty">یک نقش را انتخاب کنید</div>',await this.loadRoles()})}async selectUser(e){const t=this.state.users.find(s=>String(s.id)===String(e))||null;this.state.selectedUser=t,this.renderUserList(),await this.loadPermissions(e)}async loadPermissions(e,t={}){const{force:s=!1}=t;if(this.state.permissionCache[e]&&!s){this.state.permissions=this.clone(this.state.permissionCache[e]),this.ensureExpandedState(),this.renderPermissions();return}this.state.loadingPermissions=!0,this.$area.innerHTML='<div class="acc-loading">در حال بارگذاری دسترسی‌ها...</div>';try{const a=await this.api.get(`/access/users/${e}`);this.state.selectedUser=a.user||this.state.selectedUser,this.state.permissions=a.permissions||[],this.state.permissionCache[e]=this.clone(this.state.permissions),this.ensureExpandedState(),this.renderPermissions(),this.renderUserList()}catch(a){console.error(a),this.$area.innerHTML='<div class="acc-error">خطا در دریافت دسترسی‌های کاربر</div>'}finally{this.state.loadingPermissions=!1}}ensureExpandedState(){const e=this.getGroupedPermissions();Object.keys(e).forEach(t=>{typeof this.state.expandedModules[t]>"u"&&(this.state.expandedModules[t]=!0)})}getGroupedPermissions(){const e={};return(this.state.permissions||[]).forEach(t=>{const s=t.module||"module";e[s]||(e[s]=[]),e[s].push(t)}),e}renderPermissions(){var s,a,i,n,r,o;if(!this.state.selectedUser){this.$area.innerHTML='<div class="acc-empty">ابتدا یک کاربر را انتخاب کنید</div>';return}if(!this.state.permissions.length){this.$area.innerHTML=`
            <div class="acc-selected-user">
                <div>
                    <h3>${this.escape(((s=this.state.selectedUser)==null?void 0:s.name)||((a=this.state.selectedUser)==null?void 0:a.username)||"کاربر")}</h3>
                    <p>هیچ permission ی برای این کاربر ثبت نشده است.</p>
                </div>
            </div>
            <div class="acc-empty">دسترسی ثبت نشده</div>
            `;return}const e=this.getGroupedPermissions(),t=this.getPermissionSummary();this.$area.innerHTML=`
            <div class="acc-selected-user">
                <div>
                    <h3>${this.escape(((i=this.state.selectedUser)==null?void 0:i.name)||((n=this.state.selectedUser)==null?void 0:n.username)||"کاربر")}</h3>
                    <p>
                        ${this.escape(((r=this.state.selectedUser)==null?void 0:r.email)||((o=this.state.selectedUser)==null?void 0:o.username)||"")}
                    </p>
                </div>

                <div class="acc-save-state" data-ref="saveState">
                    ${this.state.saving?"در حال ذخیره...":""}
                </div>
            </div>

            <div class="acc-summary">
                <div class="acc-summary-card" data-summary="modules">
                    <strong>${t.modules}</strong>
                    <span>ماژول</span>
                </div>
                <div class="acc-summary-card" data-summary="rows">
                    <strong>${t.rows}</strong>
                    <span>رکورد permission</span>
                </div>
                <div class="acc-summary-card" data-summary="enabled">
                    <strong>${t.enabled}</strong>
                    <span>دسترسی فعال</span>
                </div>
            </div>

                    ${Object.entries(e).map(([l,c])=>{const d=this.state.expandedModules[l]!==!1,h=this.countEnabledForModule(c);return`
                    <div class="acc-module" data-module-wrap="${this.escapeAttr(l)}">
                        <div class="acc-module-header" data-module-toggle="${this.escapeAttr(l)}">
                            <div class="acc-module-title">
                                <strong>${this.escape(this.getModuleLabel(l,c))}</strong>
                                <span class="acc-badge green">${h}</span>
                            </div>

                            <div class="acc-module-tools">
                                <button class="acc-mini-btn" type="button" data-select-all="${this.escapeAttr(l)}">فعال‌سازی همه</button>
                                <button class="acc-mini-btn" type="button" data-clear-all="${this.escapeAttr(l)}">غیرفعال‌سازی همه</button>
                                <button class="acc-mini-btn" type="button">${d?"بستن":"باز کردن"}</button>
                            </div>
                        </div>

                        <div class="acc-module-body" style="display:${d?"block":"none"}">
                            ${c.map((u,f)=>this.renderPermissionRow(u,l,f)).join("")}
                        </div>
                    </div>
                    `}).join("")}
        `,this.bindPermissionEvents(),this.el.querySelectorAll("[data-summary]").forEach(l=>{this.on(l,"click",()=>{const c=l.dataset.summary;this.applyUserFilter(c)})})}applyUserFilter(e){this.state.userFilter=e,this.filterUsers()}renderPermissionRow(e,t,s){const a=this.getActionList(e),i=e.permissions||[];return`
            <div class="acc-permission-row">
                <div class="acc-permission-info">
                    <strong>${this.escape(e.label||e.name||e.code||t||`Permission ${s+1}`)}</strong>
                    <small>${this.escape(e.description||e.code||e.module||"")}</small>
                </div>

                    <div class="acc-perm-actions">
                        ${a.map(n=>{const r=i.includes(n);return`
                <label class="${r?"is-on":""}">
                    <input
                        type="checkbox"
                        data-module="${this.escapeAttr(e.module||t)}"
                        data-action="${this.escapeAttr(n)}"
                        data-row-index="${s}"
                        ${r?"checked":""}
                    />
                    ${this.escape(this.getActionLabel(n))}
                </label>
                `}).join("")}
                    </div>
                </div>
                `}bindPermissionEvents(){this.el.querySelectorAll("[data-module-toggle]").forEach(e=>{this.on(e,"click",t=>{if(t.target.closest("button"))return;const s=e.dataset.moduleToggle;this.toggleModule(s)})}),this.el.querySelectorAll("[data-select-all]").forEach(e=>{this.on(e,"click",t=>{t.stopPropagation(),this.bulkSetModule(e.dataset.selectAll,!0)})}),this.el.querySelectorAll("[data-clear-all]").forEach(e=>{this.on(e,"click",t=>{t.stopPropagation(),this.bulkSetModule(e.dataset.clearAll,!1)})}),this.el.querySelectorAll("input[type=checkbox]").forEach(e=>{this.on(e,"change",()=>{const t=e.dataset.module,s=e.dataset.action,a=Number(e.dataset.rowIndex);this.toggleLocalPermission(t,a,s,e.checked),this.queuePermissionSave(t,s,e.checked,a)})})}toggleModule(e){this.state.expandedModules[e]=!this.state.expandedModules[e],this.renderPermissions()}expandAllModules(){const e=this.getGroupedPermissions();Object.keys(e).forEach(t=>{this.state.expandedModules[t]=!0}),this.renderPermissions()}collapseAllModules(){const e=this.getGroupedPermissions();Object.keys(e).forEach(t=>{this.state.expandedModules[t]=!1}),this.renderPermissions()}bulkSetModule(e,t){this.state.permissions.filter(a=>(a.module||"module")===e).forEach((a,i)=>{this.getActionList(a).forEach(r=>{const o=Array.isArray(a.permissions)?a.permissions:[],l=o.includes(r);t&&!l&&(o.push(r),a.permissions=[...new Set(o)],this.queuePermissionSave(e,r,!0,i,!1)),!t&&l&&(a.permissions=o.filter(c=>c!==r),this.queuePermissionSave(e,r,!1,i,!1))})}),this.syncPermissionCache(),this.renderPermissions()}toggleLocalPermission(e,t,s,a){const n=this.state.permissions.filter(o=>(o.module||"module")===e)[t];if(!n)return;const r=Array.isArray(n.permissions)?[...n.permissions]:[];a&&!r.includes(s)&&r.push(s),a?n.permissions=[...new Set(r)]:n.permissions=r.filter(o=>o!==s),this.syncPermissionCache(),this.renderPermissions()}queuePermissionSave(e,t,s,a=0,i=!0){var o;const n=(o=this.state.selectedUser)==null?void 0:o.id;if(!n)return;const r=`${e}:${a}:${t}`;this.state.saveQueue[r]={module:e,action:t,value:s},clearTimeout(this.state.saveTimers[r]),this.setSavingState(!0),this.state.saveTimers[r]=setTimeout(async()=>{const l=this.state.saveQueue[r];delete this.state.saveQueue[r];try{await this.api.post(`/access/users/${n}/permissions`,l),this.setSaveMessage("ذخیره شد")}catch(c){console.error(c),this.setSaveMessage("خطا در ذخیره",!0),await this.loadPermissions(n,{force:!0})}finally{delete this.state.saveTimers[r],Object.keys(this.state.saveTimers).length||this.setSavingState(!1),i&&this.renderPermissions()}},250)}setSavingState(e){this.state.saving=e;const t=this.el.querySelector('[data-ref="saveState"]');t&&(t.classList.remove("error"),t.textContent=e?"در حال ذخیره...":"")}setSaveMessage(e,t=!1){const s=this.el.querySelector('[data-ref="saveState"]');s&&(s.textContent=e,s.classList.toggle("error",!!t),clearTimeout(this.saveMessageTimer),this.saveMessageTimer=setTimeout(()=>{!this.state.saving&&s&&(s.textContent="",s.classList.remove("error"))},1800))}syncPermissionCache(){var t;const e=(t=this.state.selectedUser)==null?void 0:t.id;e&&(this.state.permissionCache[e]=this.clone(this.state.permissions))}getPermissionSummary(){let e=0;return(this.state.permissions||[]).forEach(t=>{e+=(t.permissions||[]).length}),{modules:Object.keys(this.getGroupedPermissions()).length,rows:(this.state.permissions||[]).length,enabled:e}}countEnabledForModule(e=[]){let t=0;return e.forEach(s=>{t+=(s.permissions||[]).length}),t}getModuleLabel(e,t=[]){var s,a;return((s=t[0])==null?void 0:s.moduleLabel)||((a=t[0])==null?void 0:a.groupLabel)||e}getActionList(e){return Array.isArray(e.actions)&&e.actions.length?e.actions:["view","create","edit","delete"]}getActionLabel(e){return{view:"نمایش",create:"ایجاد",edit:"ویرایش",delete:"حذف",export:"خروجی",approve:"تأیید"}[e]||e}clone(e){return JSON.parse(JSON.stringify(e))}escapeAttr(e){return this.escape(String(e??""))}}g(Xt,"title","مدیریت دسترسی کاربران"),E.register("basesetpermission",Xt);const Cn=x,nt={asset:"دارایی",liability:"بدهی",equity:"حقوق صاحبان سهام",revenue:"درآمد",expense:"هزینه",contra:"کنترایی"},Tn={asset:"#3b82f6",liability:"#f59e0b",equity:"#8b5cf6",revenue:"#10b981",expense:"#ef4444",contra:"#64748b"},ce=p=>new Intl.NumberFormat("fa-IR").format(Number(p||0));class es extends Cn{constructor(e={}){super(e),this.api=e.api,this._stack=[],this._accounts=[]}async template(){return`
            <div class="coa-toolbar">
                <nav class="coa-breadcrumb" data-ref="breadcrumb" aria-label="مسیر">
                    <span class="coa-breadcrumb__item" data-id="">ریشه</span>
                </nav>
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">+ افزودن حساب</button>
            </div>
            <div class="coa-grid" data-ref="grid"></div>
        `}async afterRender(){this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),await this._load(null)}async _load(e){const t=this.ref("grid");if(t){t.innerHTML='<div class="coa-loading"><div class="acc-spinner"></div>در حال بارگذاری...</div>';try{const s=e?{parent_id:e}:{},a=await this.api.get("/accounting/accounts",s);this._accounts=(a==null?void 0:a.data)??[],this._renderGrid(t)}catch{t.innerHTML='<div class="acc-error">خطا در دریافت سرفصل‌ها</div>'}}}_renderGrid(e){if(!this._accounts.length){const t=this._stack.length?this._stack[this._stack.length-1].name:"ریشه";e.innerHTML=`<div class="coa-empty">حسابی در «${this.escape(t)}» یافت نشد.</div>`;return}e.innerHTML="",this._accounts.forEach(t=>{const s=this._buildCard(t);e.appendChild(s)})}_buildCard(e){const t=(e.child_count??0)>0,s=Tn[e.account_type]??"#64748b",a=document.createElement("div");return a.className=`coa-card ${t?"coa-card--has-children":"coa-card--leaf"}`,a.dataset.id=e.id,a.style.borderTop=`3px solid ${s}`,a.innerHTML=`
            ${t?`<span class="coa-card__children-badge">${e.child_count}</span>`:""}
            <div class="coa-card__code">${this.escape(e.code??"")}</div>
            <div class="coa-card__name">${this.escape(e.name)}</div>
            <span class="coa-card__type" style="background:${s}1a;color:${s}">${nt[e.account_type]??e.account_type}</span>
            <div class="coa-card__actions">
                <button class="coa-card__action-btn" data-action="detail">جزئیات</button>
                <button class="coa-card__action-btn" data-action="edit">ویرایش</button>
                <button class="coa-card__action-btn coa-card__action-btn--danger" data-action="delete">حذف</button>
            </div>
        `,a.addEventListener("click",i=>{var r;const n=(r=i.target.closest("[data-action]"))==null?void 0:r.dataset.action;if(n==="detail"){i.stopPropagation(),this._openDetail(e);return}if(n==="edit"){i.stopPropagation(),this._openForm(e);return}if(n==="delete"){i.stopPropagation(),this._delete(e);return}t&&this._drillDown(e)}),a}async _openDetail(e){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
            <div class="acc-modal" style="max-width:660px;max-height:90vh;overflow-y:auto;">
                <button class="acc-modal__close" type="button">✕</button>
                <div class="acc-modal__title">${this.escape(e.code??"")} — ${this.escape(e.name??"")}</div>
                <div data-ref="detailBody">
                    <div class="acc-loading"><div class="acc-spinner"></div>در حال بارگذاری...</div>
                </div>
            </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.addEventListener("click",n=>{n.target===t&&s()});const a=t.querySelector("[data-ref='detailBody']"),i=async n=>{a.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال بارگذاری...</div>';try{const[r,o]=await Promise.all([this.api.get(`/accounting/accounts/${e.id}/detail`),this.api.get("/accounting/dimensions")]),l=r==null?void 0:r.data;if(!l)throw new Error("داده‌ای دریافت نشد");this._allDims=(o==null?void 0:o.data)??[],this._renderDetail(a,l,i,n)}catch(r){a.innerHTML=`<div class="acc-error">خطا: ${this.escape((r==null?void 0:r.message)??"")}</div>`}};await i()}_renderDetail(e,t,s,a){var w;const i=t.account,n=t.articles.length?t.articles.map(_=>{const k=_.role==="DR",R=k?'<span class="coa-art-role" style="background:#fee2e2;color:#dc2626">بدهکار</span>':'<span class="coa-art-role" style="background:#dcfce7;color:#059669">بستانکار</span>',H=`${this.escape(_.counterpart.code||"")} ${this.escape(_.counterpart.name||"")}`.trim(),q=k?`<span class="flow-direction__from">${this.escape(i.code)}</span> → <span class="flow-direction__to">${this.escape(H)}</span>`:`<span class="flow-direction__from">${this.escape(H)}</span> → <span class="flow-direction__to">${this.escape(i.code)}</span>`;return`
                <div class="coa-art-row">
                    <div class="coa-art-head">
                        <span class="coa-art-event">⚡ ${this.escape(_.event_type)}</span>
                        ${R}
                        <span class="coa-art-src">[${this.escape(_.source_field||"direct")}]</span>
                    </div>
                    ${_.desc?`<div class="coa-art-desc">${this.escape(_.desc)}</div>`:""}
                    <div class="coa-art-flow">${q}</div>
                </div>`}).join(""):'<div class="acc-empty">این حساب در هیچ آرتیکلِ template‌ای استفاده نشده است.</div>',r=t.balance,o=`
            <div class="coa-bal-grid">
                <div class="coa-bal-box" style="border-color:#dc2626">
                    <div class="coa-bal-v" style="color:#dc2626">${ce(r.total_debit)}</div>
                    <div class="coa-bal-l">جمع بدهکار</div>
                </div>
                <div class="coa-bal-box" style="border-color:#059669">
                    <div class="coa-bal-v" style="color:#059669">${ce(r.total_credit)}</div>
                    <div class="coa-bal-l">جمع بستانکار</div>
                </div>
                <div class="coa-bal-box" style="border-color:#2563eb">
                    <div class="coa-bal-v" style="color:#2563eb">${ce(Math.abs(r.net_balance))}</div>
                    <div class="coa-bal-l">مانده (${Number(r.net_balance)>=0?"بدهکار":"بستانکار"})</div>
                </div>
            </div>
            <div class="coa-art-desc" style="text-align:center;margin-top:10px;">${ce(r.flow_count)} آرتیکلِ تأییدشده</div>`,l=t.account_dims||[],c=new Set(l.map(_=>String(_.dim_id))),d=(this._allDims||[]).filter(_=>!c.has(String(_.id))),h=l.length?l.map(_=>`
            <div class="coa-kv">
                <span>🏷️ ${this.escape(_.dim_name)} <small style="color:#94a3b8">(${this.escape(_.group_name||"")})</small></span>
                <span style="display:flex;align-items:center;gap:8px;">
                    <b style="color:${_.is_required==1?"#dc2626":"#64748b"};font-size:12px;">${_.is_required==1?"الزامی":"اختیاری"}</b>
                    <button class="acc-btn acc-btn--danger acc-btn--sm" data-dim-del="${_.id}">حذف</button>
                </span>
            </div>`).join(""):'<div class="acc-empty">بُعدی به این حساب وصل نشده است.</div>',u=d.length?`
            <div style="display:flex;gap:8px;align-items:center;margin-top:12px;border-top:1px dashed #e2e8f0;padding-top:12px;">
                <select data-ref="dimAddSel" style="flex:1;">${d.map(_=>`<option value="${_.id}">${this.escape((_.dim_name||_.name)+" — "+(_.group_name||_.dim_type||""))}</option>`).join("")}</select>
                <label style="font-size:12px;display:flex;align-items:center;gap:4px;"><input type="checkbox" data-ref="dimAddReq" checked> الزامی</label>
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-dim-add>+ اتصال</button>
            </div>`:this._allDims&&this._allDims.length?'<div style="font-size:12px;color:#94a3b8;margin-top:10px;">همهٔ ابعاد وصل شده‌اند.</div>':'<div style="font-size:12px;color:#94a3b8;margin-top:10px;">ابتدا در تبِ «ابعاد» بُعد تعریف کنید.</div>',f=h+u,m=t.recent_flows.length?`
            <table class="flows-table">
                <thead><tr><th>سند</th><th>رویداد</th><th>جهت</th><th>مبلغ</th><th>تأیید</th><th>تاریخ</th></tr></thead>
                <tbody>
                    ${t.recent_flows.map(_=>{const k=_.direction==="in";return`<tr>
                            <td style="font-family:monospace;font-size:11px;">#${_.event_id}</td>
                            <td>${this.escape(_.event_type||"")}</td>
                            <td style="color:${k?"#059669":"#dc2626"};font-weight:600;">${k?"⬇ بستانکار":"⬆ بدهکار"}</td>
                            <td class="num">${ce(_.amount)}</td>
                            <td><span class="status-badge ${_.is_confirmed==1?"status-badge--confirmed":"status-badge--draft"}">${_.is_confirmed==1?"✓":"⏳"}</span></td>
                            <td style="font-size:11px;color:#64748b;">${_.created_at?String(_.created_at).split("T")[0].split(" ")[0]:""}</td>
                        </tr>`}).join("")}
                </tbody>
            </table>`:'<div class="acc-empty">سندی برای این حساب ثبت نشده است.</div>',b=t.path.length?t.path.map(_=>this.escape(_.name)).join(" › "):"ریشه",v=`
            <div class="coa-kv"><span>کد حساب</span><b style="font-family:monospace">${this.escape(i.code||"")}</b></div>
            <div class="coa-kv"><span>نام حساب</span><b>${this.escape(i.name||"")}</b></div>
            <div class="coa-kv"><span>نوع</span><b>${nt[i.account_type]??this.escape(i.account_type||"")}</b></div>
            <div class="coa-kv"><span>مسیر</span><b>${b}</b></div>
            <div class="coa-kv"><span>شناسهٔ GL (account_id)</span><b style="font-family:monospace">${this.escape(String(i.id))}</b></div>`;e.innerHTML=`
            <div class="coa-tabs">
                <button class="coa-tab coa-tab--active" data-tab="articles">🔗 آرتیکل‌ها (${t.articles.length})</button>
                <button class="coa-tab" data-tab="balance">📊 گردش و مانده</button>
                <button class="coa-tab" data-tab="dims">🏷️ ابعاد (${(t.account_dims||[]).length})</button>
                <button class="coa-tab" data-tab="recent">📄 آخرین اسناد</button>
                <button class="coa-tab" data-tab="info">ℹ️ اطلاعات</button>
            </div>
            <div class="coa-tabpane coa-tabpane--active" data-pane="articles">${n}</div>
            <div class="coa-tabpane" data-pane="balance">${o}</div>
            <div class="coa-tabpane" data-pane="dims">${f}</div>
            <div class="coa-tabpane" data-pane="recent">${m}</div>
            <div class="coa-tabpane" data-pane="info">${v}</div>`;const y=_=>{e.querySelectorAll(".coa-tab").forEach(k=>k.classList.toggle("coa-tab--active",k.dataset.tab===_)),e.querySelectorAll(".coa-tabpane").forEach(k=>k.classList.toggle("coa-tabpane--active",k.dataset.pane===_))};e.querySelectorAll(".coa-tab").forEach(_=>{_.addEventListener("click",()=>y(_.dataset.tab))}),a&&y(a);const $=t.account.id;(w=e.querySelector("[data-dim-add]"))==null||w.addEventListener("click",async()=>{const _=e.querySelector("[data-ref='dimAddSel']"),k=e.querySelector("[data-ref='dimAddReq']");if(_!=null&&_.value)try{await this.api.post(`/accounting/accounts/${$}/dims`,{dim_id:Number(_.value),is_required:k!=null&&k.checked?1:0}),s&&await s("dims")}catch(R){alert("خطا: "+((R==null?void 0:R.message)??""))}}),e.querySelectorAll("[data-dim-del]").forEach(_=>{_.addEventListener("click",async()=>{try{await this.api.delete(`/accounting/account-dims/${_.dataset.dimDel}`),s&&await s("dims")}catch(k){alert("خطا: "+((k==null?void 0:k.message)??""))}})})}_drillDown(e){this._stack.push({id:e.id,name:e.name}),this._refreshBreadcrumb(),this._load(e.id)}_drillUp(e){this._stack=this._stack.slice(0,e),this._refreshBreadcrumb();const t=this._stack.length?this._stack[this._stack.length-1].id:null;this._load(t)}_refreshBreadcrumb(){const e=this.ref("breadcrumb");if(!e)return;const t=[{id:null,name:"ریشه"},...this._stack];e.innerHTML=t.map((s,a)=>a===t.length-1?`<span class="coa-breadcrumb__current">${this.escape(s.name)}</span>`:`
                <span class="coa-breadcrumb__item" data-idx="${a}">${this.escape(s.name)}</span>
                <span class="coa-breadcrumb__sep">›</span>
            `).join(""),e.querySelectorAll(".coa-breadcrumb__item").forEach(s=>{s.addEventListener("click",()=>this._drillUp(Number(s.dataset.idx)))})}_openForm(e=null){const t=!!e,s=this._stack.length?this._stack[this._stack.length-1].id:null,a=Object.entries(nt).map(([r,o])=>`<option value="${r}" ${(e==null?void 0:e.account_type)===r?"selected":""}>${o}</option>`).join(""),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
            <div class="acc-modal">
                <button class="acc-modal__close" type="button">✕</button>
                <div class="acc-modal__title">${t?"ویرایش حساب":"افزودن حساب"}</div>
                <form class="acc-modal-form">
                    <div class="acc-form-group">
                        <label>کد حساب</label>
                        <input name="code" type="text" value="${this.escape((e==null?void 0:e.code)??"")}" placeholder="مثال: 1121" required>
                    </div>
                    <div class="acc-form-group">
                        <label>نام حساب</label>
                        <input name="name" type="text" value="${this.escape((e==null?void 0:e.name)??"")}" required>
                    </div>
                    <div class="acc-form-group">
                        <label>نوع حساب</label>
                        <select name="account_type">${a}</select>
                    </div>
                    <div class="acc-form-group">
                        <label>توضیحات</label>
                        <textarea name="description" rows="2">${this.escape((e==null?void 0:e.description)??"")}</textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary" data-ref="submitBtn">
                            ${t?"ذخیره":"افزودن"}
                        </button>
                    </div>
                </form>
            </div>
        `,document.body.appendChild(i);const n=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",n),i.querySelector("[data-action='cancel']").addEventListener("click",n),i.addEventListener("click",r=>{r.target===i&&n()}),i.querySelector("form").addEventListener("submit",async r=>{r.preventDefault();const o=new FormData(r.target),l={code:o.get("code"),name:o.get("name"),account_type:o.get("account_type"),description:o.get("description"),parent_id:(e==null?void 0:e.parent_id)??s},c=i.querySelector("[data-ref='submitBtn']");c.disabled=!0,c.textContent="در حال ذخیره...";try{t?await this.api.put(`/accounting/accounts/${e.id}`,l):await this.api.post("/accounting/accounts",l),n(),await this._load(s)}catch(d){c.disabled=!1,c.textContent=t?"ذخیره":"افزودن",alert("خطا: "+((d==null?void 0:d.message)??"لطفاً دوباره تلاش کنید"))}})}async _delete(e){if(confirm(`آیا از حذف حساب «${e.name}» اطمینان دارید؟`))try{await this.api.delete(`/accounting/accounts/${e.id}`);const t=this._stack.length?this._stack[this._stack.length-1].id:null;await this._load(t)}catch(t){alert("خطا در حذف: "+((t==null?void 0:t.message)??""))}}}g(es,"title","");const Mn=x,Be=p=>new Intl.NumberFormat("fa-IR").format(Number(p||0));class ts extends Mn{constructor(e={}){super(e),this.api=e.api,this._articles=[],this._accounts=[],this._search="",this._category=""}async template(){return`
            <div class="event-toolbar">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">+ آرتیکل جدید</button>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="extractBtn"
                        title="ساختِ آرتیکل از روی template‌های فعال">⚡ استخراج از template‌ها</button>
                <input class="event-type-filter" data-ref="searchInput" type="text"
                       placeholder="جستجوی آرتیکل..." style="min-width:200px;">
                <select class="event-type-filter" data-ref="catFilter" style="min-width:160px;">
                    <option value="">همه دسته‌ها</option>
                </select>
                <span class="acc-count" data-ref="count" style="font-size:12px;color:#94a3b8;margin-right:auto;"></span>
            </div>

            <div style="background:#eff6ff;border:1px solid #bfdbfe;border-radius:10px;padding:10px 14px;
                        margin-bottom:14px;font-size:12px;color:#1e40af;line-height:1.7;">
                <strong>📌 بانک آرتیکل:</strong> هر آرتیکل یک جفتِ بدهکار→بستانکار است که در یک ردیف ثبت می‌شود
                (توازنِ ساختاری). آرتیکل‌های معتبر اینجا تعریف می‌شوند تا در template‌ها و اسناد استفادهٔ مجدد شوند.
            </div>

            <div class="article-grid" data-ref="grid"></div>
        `}async afterRender(){this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),this.on(this.ref("extractBtn"),"click",()=>this._extract()),this.on(this.ref("searchInput"),"input",e=>{this._search=e.target.value.trim().toLowerCase(),this._render()}),this.on(this.ref("catFilter"),"change",e=>{this._category=e.target.value,this._render()}),await this._loadAll()}async _loadAll(){const e=this.ref("grid");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال بارگذاری...</div>';try{const[t,s]=await Promise.all([this.api.get("/accounting/articles"),this.api.get("/accounting/accounts",{flat:1})]);this._articles=(t==null?void 0:t.data)??[],this._accounts=(s==null?void 0:s.data)??[],this._fillCategoryFilter(),this._render()}catch(t){e.innerHTML=`<div class="acc-error">خطا در دریافت آرتیکل‌ها: ${this.escape((t==null?void 0:t.message)??"")}</div>`}}_fillCategoryFilter(){const e=this.ref("catFilter");if(!e)return;const t=[...new Set(this._articles.map(s=>s.category).filter(Boolean))].sort();e.innerHTML='<option value="">همه دسته‌ها</option>'+t.map(s=>`<option value="${this.escape(s)}" ${s===this._category?"selected":""}>${this.escape(s)}</option>`).join("")}_accName(e){const t=this._accounts.find(s=>String(s.id)===String(e));return t?`${t.code} — ${t.name}`:`#${e}`}_render(){const e=this.ref("grid");if(!e)return;let t=this._articles;this._category&&(t=t.filter(a=>a.category===this._category)),this._search&&(t=t.filter(a=>(a.label||"").toLowerCase().includes(this._search)||(a.code||"").toLowerCase().includes(this._search)));const s=this.ref("count");if(s&&(s.textContent=`${Be(t.length)} آرتیکل`),!t.length){e.innerHTML='<div class="acc-empty">آرتیکلی یافت نشد. «استخراج از template‌ها» یا «آرتیکل جدید» را بزنید.</div>';return}e.innerHTML=t.map(a=>this._cardHtml(a)).join(""),e.querySelectorAll("[data-action='edit']").forEach(a=>{a.addEventListener("click",()=>{const i=this._articles.find(n=>String(n.id)===String(a.dataset.id));i&&this._openForm(i)})}),e.querySelectorAll("[data-action='delete']").forEach(a=>{a.addEventListener("click",()=>{const i=this._articles.find(n=>String(n.id)===String(a.dataset.id));i&&this._delete(i)})})}_cardHtml(e){const t=e.dr_code?`${this.escape(e.dr_code)} ${this.escape(e.dr_name||"")}`:this._accName(e.dr_account_id),s=e.cr_code?`${this.escape(e.cr_code)} ${this.escape(e.cr_name||"")}`:this._accName(e.cr_account_id),a=Number(e.usage_count||0);return`
            <div class="article-card">
                <div class="article-card__head">
                    <span class="article-card__code">${this.escape(e.code||"")}</span>
                    ${e.category?`<span class="article-card__cat">${this.escape(e.category)}</span>`:""}
                    <span class="article-card__usage" title="در چند template استفاده شده">${a?`★ ${Be(a)}`:"بدون استفاده"}</span>
                </div>
                <div class="article-card__label">${this.escape(e.label||"")}</div>
                <div class="article-card__flow">
                    <span class="flow-direction__from">${t}</span>
                    <span class="article-card__arrow">→</span>
                    <span class="flow-direction__to">${s}</span>
                </div>
                <div class="article-card__foot">
                    <span class="article-card__src">[${this.escape(e.amount_source||"amount")}]</span>
                    <span style="display:flex;gap:6px;">
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit" data-id="${e.id}">ویرایش</button>
                        <button class="acc-btn acc-btn--danger acc-btn--sm" data-action="delete" data-id="${e.id}">حذف</button>
                    </span>
                </div>
            </div>`}async _extract(){const e=this.ref("extractBtn");e.disabled=!0,e.textContent="⏳ در حال استخراج...";try{const t=await this.api.post("/accounting/articles/extract",{}),s=(t==null?void 0:t.created)??0,a=(t==null?void 0:t.skipped)??0;this._toast(`✅ ${Be(s)} آرتیکلِ جدید ساخته شد (${Be(a)} تکراری رد شد)`),await this._loadAll()}catch(t){alert("خطا در استخراج: "+((t==null?void 0:t.message)??""))}finally{e.disabled=!1,e.textContent="⚡ استخراج از template‌ها"}}_openForm(e=null){const t=!!e,s=n=>this._accounts.map(r=>`<option value="${r.id}" ${String(n)===String(r.id)?"selected":""}>${this.escape(r.code+" — "+r.name)}</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
            <div class="acc-modal" style="max-width:560px;">
                <button class="acc-modal__close" type="button">✕</button>
                <div class="acc-modal__title">${t?"ویرایش آرتیکل":"آرتیکل جدید"}</div>
                <form id="art-form">
                    <div class="acc-form-group">
                        <label>برچسب معنایی *</label>
                        <input name="label" value="${this.escape((e==null?void 0:e.label)??"")}" placeholder="مثال: شناسایی درآمد فروش" required>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>حساب بدهکار (DR) *</label>
                            <select name="dr_account_id" required><option value="">— انتخاب —</option>${s(e==null?void 0:e.dr_account_id)}</select>
                        </div>
                        <div class="acc-form-group">
                            <label>حساب بستانکار (CR) *</label>
                            <select name="cr_account_id" required><option value="">— انتخاب —</option>${s(e==null?void 0:e.cr_account_id)}</select>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>فیلدِ مبلغ (source_field)</label>
                            <input name="amount_source" value="${this.escape((e==null?void 0:e.amount_source)??"amount")}" placeholder="amount">
                        </div>
                        <div class="acc-form-group">
                            <label>دسته‌بندی</label>
                            <input name="category" value="${this.escape((e==null?void 0:e.category)??"")}" placeholder="مثال: SALES_INVOICE">
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>توضیحات</label>
                        <input name="description" value="${this.escape((e==null?void 0:e.description)??"")}">
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary" id="art-submit">${t?"ذخیره":"ایجاد"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action='cancel']").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("#art-form").addEventListener("submit",async n=>{n.preventDefault();const r=new FormData(n.target),o={label:(r.get("label")||"").trim(),dr_account_id:Number(r.get("dr_account_id"))||0,cr_account_id:Number(r.get("cr_account_id"))||0,amount_source:(r.get("amount_source")||"amount").trim(),category:(r.get("category")||"").trim(),description:(r.get("description")||"").trim()};if(!o.label||!o.dr_account_id||!o.cr_account_id){alert("برچسب، حساب بدهکار و بستانکار الزامی‌اند.");return}if(o.dr_account_id===o.cr_account_id){alert("حساب بدهکار و بستانکار نباید یکی باشند.");return}const l=a.querySelector("#art-submit");l.disabled=!0,l.textContent="در حال ذخیره...";try{t?await this.api.put(`/accounting/articles/${e.id}`,o):await this.api.post("/accounting/articles",o),i(),await this._loadAll()}catch(c){l.disabled=!1,l.textContent=t?"ذخیره":"ایجاد",alert("خطا: "+((c==null?void 0:c.message)??""))}})}async _delete(e){if(confirm(`حذف آرتیکل «${e.label}»؟`))try{await this.api.delete(`/accounting/articles/${e.id}`),await this._loadAll()}catch(t){alert("خطا در حذف: "+((t==null?void 0:t.message)??""))}}_toast(e){const t=document.createElement("div");t.style.cssText="position:fixed;bottom:24px;right:24px;background:#059669;color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;box-shadow:0 4px 20px rgba(0,0,0,.15);",t.textContent=e,document.body.appendChild(t),setTimeout(()=>t.remove(),3200)}}g(ts,"title","");const Rn=x,qn=["STRING","INT","BIGINT","DECIMAL"];class ss extends Rn{constructor(e={}){super(e),this.api=e.api,this._tree=[]}async template(){return`
            <div class="event-toolbar">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-act="add-group">+ گروه جدید</button>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="reloadBtn">🔄 بازخوانی</button>
                <span style="font-size:12px;color:#94a3b8;margin-right:auto;">گروه ← بُعد ← مقدار</span>
            </div>
            <div style="background:#f0fdf4;border:1px solid #bbf7d0;border-radius:10px;padding:10px 14px;
                        margin-bottom:14px;font-size:12px;color:#166534;line-height:1.7;">
                <strong>📌 ساختار:</strong> هر <b>گروه</b> چند <b>بُعد</b> دارد (مثلاً گروهِ «طرف حساب» → بُعدِ «مشتری»)،
                و هر بُعد چند <b>مقدار</b> (مثلاً «مشتری الف»). بُعدها را در «سرفصل‌ها» به حساب‌ها وصل می‌کنی.
            </div>
            <div class="dim-tree" data-ref="tree"></div>
        `}async afterRender(){this.on(this.ref("reloadBtn"),"click",()=>this._load()),this.on(this.container,"click",e=>this._onClick(e)),await this._load()}async _load(){const e=this.ref("tree");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال بارگذاری...</div>';try{const t=await this.api.get("/accounting/dimension-tree");this._tree=(t==null?void 0:t.data)??[],this._render()}catch(t){e.innerHTML=`<div class="acc-error">خطا: ${this.escape((t==null?void 0:t.message)??"")}</div>`}}_render(){const e=this.ref("tree");if(!this._tree.length){e.innerHTML='<div class="acc-empty">گروهی نیست. «+ گروه جدید» را بزنید.</div>';return}e.innerHTML=this._tree.map(t=>this._groupHtml(t)).join("")}_groupHtml(e){const t=e.dimensions||[];return`
            <div class="dim-grp">
                <div class="dim-grp__head">
                    <span class="dim-grp__name">🗂️ ${this.escape(e.group_name)}
                        <small style="font-family:monospace;color:#94a3b8;">${this.escape(e.group_code)}</small>
                        <small style="color:#94a3b8;">(${t.length} بُعد)</small>
                    </span>
                    <span class="dim-actions">
                        <button class="acc-btn acc-btn--primary acc-btn--sm" data-act="add-dim" data-gid="${e.id}">+ بُعد</button>
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-act="edit-group" data-id="${e.id}">ویرایش</button>
                        <button class="acc-btn acc-btn--danger acc-btn--sm" data-act="del-group" data-id="${e.id}">حذف</button>
                    </span>
                </div>
                <div class="dim-grp__body">
                    ${t.length?t.map(s=>this._dimHtml(s,e.id)).join(""):'<div class="dim-empty">بُعدی ندارد. «+ بُعد» را بزنید.</div>'}
                </div>
            </div>`}_dimHtml(e,t){const s=e.values||[];return`
            <div class="dim-def">
                <div class="dim-def__head">
                    <span class="dim-def__name">🏷️ ${this.escape(e.dim_name||e.name)}
                        <small style="font-family:monospace;color:#94a3b8;">${this.escape(e.dim_code)}</small>
                        <small style="color:#64748b;">· ${this.escape(e.data_type||"STRING")} · ${s.length} مقدار</small>
                    </span>
                    <span class="dim-actions">
                        <button class="acc-btn acc-btn--primary acc-btn--sm" data-act="add-val" data-did="${e.id}">+ مقدار</button>
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-act="edit-dim" data-id="${e.id}" data-gid="${t}">ویرایش</button>
                        <button class="acc-btn acc-btn--danger acc-btn--sm" data-act="del-dim" data-id="${e.id}">حذف</button>
                    </span>
                </div>
                <div class="dim-vals">
                    ${s.length?s.map(a=>`
                        <div class="dim-val">
                            <span>▫️ ${this.escape(a.value_name)} <small style="font-family:monospace;color:#cbd5e1;">${this.escape(a.value_code)}</small></span>
                            <span class="dim-actions">
                                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-act="edit-val" data-id="${a.id}" data-did="${e.id}">ویرایش</button>
                                <button class="acc-btn acc-btn--danger acc-btn--sm" data-act="del-val" data-id="${a.id}">حذف</button>
                            </span>
                        </div>`).join(""):'<div class="dim-empty">مقداری ندارد.</div>'}
                </div>
            </div>`}_find(e,t){if(e==="group")return this._tree.find(s=>String(s.id)===String(t));for(const s of this._tree){if(e==="dim"){const a=(s.dimensions||[]).find(i=>String(i.id)===String(t));if(a)return a}if(e==="val")for(const a of s.dimensions||[]){const i=(a.values||[]).find(n=>String(n.id)===String(t));if(i)return i}}return null}_onClick(e){var i,n,r;const t=e.target.closest("[data-act]");if(!t)return;const s=t.dataset.act,a=t.dataset.id;s==="add-group"?this._openForm("groups",null,{}):s==="edit-group"?this._openForm("groups",this._find("group",a),{}):s==="del-group"?this._delete("dimension-groups",a,(i=this._find("group",a))==null?void 0:i.group_name):s==="add-dim"?this._openForm("dimensions",null,{group_id:t.dataset.gid}):s==="edit-dim"?this._openForm("dimensions",this._find("dim",a),{group_id:t.dataset.gid}):s==="del-dim"?this._delete("dimensions",a,(n=this._find("dim",a))==null?void 0:n.dim_name):s==="add-val"?this._openForm("values",null,{dim_id:t.dataset.did}):s==="edit-val"?this._openForm("values",this._find("val",a),{dim_id:t.dataset.did}):s==="del-val"&&this._delete("dimension-values",a,(r=this._find("val",a))==null?void 0:r.value_name)}_openForm(e,t,s){const a=!!t;let i="";e==="groups"?i=`
                <div class="acc-form-group"><label>کد گروه *</label>
                    <input name="group_code" value="${this.escape((t==null?void 0:t.group_code)??"")}" ${a?"readonly style='background:#f1f5f9'":""} placeholder="مثال: REGION" required></div>
                <div class="acc-form-group"><label>نام گروه *</label>
                    <input name="group_name" value="${this.escape((t==null?void 0:t.group_name)??"")}" required></div>
                <div class="acc-form-group"><label>توضیحات</label>
                    <input name="description" value="${this.escape((t==null?void 0:t.description)??"")}"></div>`:e==="dimensions"?i=`
                <div class="acc-form-group"><label>نام بُعد *</label>
                    <input name="dim_name" value="${this.escape((t==null?void 0:t.dim_name)??(t==null?void 0:t.name)??"")}" placeholder="مثال: مشتری" required></div>
                <div class="acc-form-group"><label>کد (اختیاری)</label>
                    <input name="dim_code" value="${this.escape((t==null?void 0:t.dim_code)??"")}" placeholder="خودکار اگر خالی"></div>
                <div class="acc-form-group"><label>نوع داده</label>
                    <select name="data_type">${qn.map(l=>`<option value="${l}" ${(t==null?void 0:t.data_type)===l?"selected":""}>${l}</option>`).join("")}</select></div>`:i=`
                <div class="acc-form-group"><label>نام مقدار *</label>
                    <input name="value_name" value="${this.escape((t==null?void 0:t.value_name)??"")}" placeholder="مثال: مشتری الف" required></div>
                <div class="acc-form-group"><label>کد (اختیاری)</label>
                    <input name="value_code" value="${this.escape((t==null?void 0:t.value_code)??"")}" placeholder="خودکار اگر خالی"></div>`;const n=(a?"ویرایش ":"افزودن ")+(e==="groups"?"گروه":e==="dimensions"?"بُعد":"مقدار"),r=document.createElement("div");r.className="acc-modal-overlay",r.innerHTML=`
            <div class="acc-modal" style="max-width:460px;">
                <button class="acc-modal__close" type="button">✕</button>
                <div class="acc-modal__title">${n}</div>
                <form id="dim-form">${i}
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary" id="dim-submit">${a?"ذخیره":"ایجاد"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(r);const o=()=>r.remove();r.querySelector(".acc-modal__close").addEventListener("click",o),r.querySelector("[data-action='cancel']").addEventListener("click",o),r.addEventListener("click",l=>{l.target===r&&o()}),r.querySelector("#dim-form").addEventListener("submit",async l=>{l.preventDefault();const c=new FormData(l.target),d={};c.forEach((f,m)=>d[m]=typeof f=="string"?f.trim():f),e==="dimensions"&&s.group_id&&(d.group_id=Number(s.group_id)),e==="values"&&s.dim_id&&(d.dim_id=Number(s.dim_id));const h=e==="groups"?"dimension-groups":e==="dimensions"?"dimensions":"dimension-values",u=r.querySelector("#dim-submit");u.disabled=!0,u.textContent="در حال ذخیره...";try{a?await this.api.put(`/accounting/${h}/${t.id}`,d):await this.api.post(`/accounting/${h}`,d),o(),await this._load()}catch(f){u.disabled=!1,u.textContent=a?"ذخیره":"ایجاد",alert("خطا: "+((f==null?void 0:f.message)??""))}})}async _delete(e,t,s){if(confirm(`حذف «${s??""}»؟`))try{await this.api.delete(`/accounting/${e}/${t}`),await this._load()}catch(a){alert("خطا در حذف: "+((a==null?void 0:a.message)??""))}}}g(ss,"title","");const Hn=x,Bn={pairs:[{dr_gl_id:null,cr_gl_id:null,source_field:"amount",desc:""}]};class as extends Hn{constructor(e={}){super(e),this.api=e.api,this._templates=[],this._accounts=[],this._filterType=""}async template(){return`
            <div class="event-toolbar">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">
                    + Template جدید
                </button>
                <input class="event-type-filter" data-ref="typeFilter" type="text"
                       placeholder="جستجوی نوع رویداد..." style="min-width:200px;">
                <label style="font-size:12px;display:flex;align-items:center;gap:6px;margin-right:auto;">
                    <input type="checkbox" data-ref="activeOnly"> فقط فعال
                </label>
            </div>

            <!-- راهنمای ساختار Template -->
            <div style="background:#f0fdf4;border:1px solid #bbf7d0;border-radius:10px;padding:12px 16px;
                        margin-bottom:16px;font-size:12px;color:#166534;line-height:1.7;">
                <strong>📌 ساختار mapping_logic:</strong> هر template از آرایه‌ای از
                <code>pairs</code> تشکیل می‌شود. هر pair یک جفت بدهکار/بستانکار است.
                مقدار <code>source_field</code> نام فیلد متناظر در
                <code>event_payload</code> است (مثلاً <code>net_amount</code>).
                اگر ندانید، مستقیماً <code>amount</code> را وارد کنید.
            </div>

            <div data-ref="templatesList"></div>
        `}async afterRender(){this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),this.on(this.ref("typeFilter"),"input",e=>{this._filterType=e.target.value.trim().toLowerCase(),this._renderList()}),this.on(this.ref("activeOnly"),"change",()=>this._renderList()),await this._loadAll()}async _loadAll(){const e=this.ref("templatesList");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال بارگذاری...</div>';try{const[t,s]=await Promise.all([this.api.get("/accounting/templates"),this.api.get("/accounting/accounts",{flat:1})]);this._templates=(t==null?void 0:t.data)??[],this._accounts=(s==null?void 0:s.data)??[],this._renderList()}catch{e.innerHTML='<div class="acc-error">خطا در دریافت اطلاعات</div>'}}_renderList(){var i;const e=this.ref("templatesList"),t=((i=this.ref("activeOnly"))==null?void 0:i.checked)??!1;let s=this._templates;if(this._filterType&&(s=s.filter(n=>(n.event_type??"").toLowerCase().includes(this._filterType))),t&&(s=s.filter(n=>n.is_active==1)),!s.length){e.innerHTML='<div class="acc-empty">Template‌ای یافت نشد.</div>';return}const a={};s.forEach(n=>{const r=n.event_type||"نامشخص";a[r]||(a[r]=[]),a[r].push(n)}),e.innerHTML=Object.entries(a).map(([n,r])=>`
            <div class="event-type-group">
                <div class="event-type-group__header">
                    ⚡ ${this.escape(n)}
                    <small style="font-weight:400;margin-right:8px;color:#6b7280;">(${r.length} نسخه)</small>
                </div>
                ${r.map(o=>this._templateRowHtml(o)).join("")}
            </div>
        `).join(""),e.querySelectorAll("[data-action='edit']").forEach(n=>{const r=Number(n.closest(".rule-row").dataset.id),o=this._templates.find(l=>l.id===r);n.addEventListener("click",()=>this._openForm(o))}),e.querySelectorAll("[data-action='toggle']").forEach(n=>{const r=Number(n.closest(".rule-row").dataset.id),o=this._templates.find(l=>l.id===r);n.addEventListener("click",()=>this._toggleActive(o))}),e.querySelectorAll("[data-action='delete']").forEach(n=>{const r=Number(n.closest(".rule-row").dataset.id),o=this._templates.find(l=>l.id===r);n.addEventListener("click",()=>this._delete(o))})}_templateRowHtml(e){const t=typeof e.mapping_logic=="string"?JSON.parse(e.mapping_logic):e.mapping_logic??{},a=((t==null?void 0:t.pairs)??[]).map(i=>{const n=this._accountLabel(i.dr_gl_id),r=this._accountLabel(i.cr_gl_id);return`
                <span class="flow-direction" style="font-size:11px;gap:4px;">
                    <span class="flow-direction__from" style="font-size:10px;">${this.escape(n)}</span>
                    <span class="flow-direction__arrow">→</span>
                    <span class="flow-direction__to"   style="font-size:10px;">${this.escape(r)}</span>
                    <span style="font-size:10px;color:#94a3b8;">[${this.escape(i.source_field||"direct")}]</span>
                </span>
            `}).join("");return`
            <div class="rule-row" data-id="${e.id}">
                <div class="rule-row__main">
                    <div class="rule-row__title" style="display:flex;align-items:center;gap:8px;">
                        ${this.escape(e.template_name||`Template #${e.id}`)}
                        <span style="font-size:11px;background:#e0f2fe;color:#0369a1;padding:1px 8px;border-radius:8px;">
                            v${e.version}
                        </span>
                        <span class="status-badge ${e.is_active?"status-badge--confirmed":"status-badge--cancelled"}">
                            ${e.is_active?"فعال":"غیرفعال"}
                        </span>
                    </div>
                    <div class="rule-row__meta" style="margin-top:6px;flex-direction:column;gap:4px;">
                        ${a||'<span style="color:#94a3b8;font-size:11px;">بدون pair</span>'}
                        ${e.description?`<span style="color:#64748b;font-size:11px;">${this.escape(e.description)}</span>`:""}
                    </div>
                </div>
                <div class="rule-row__actions">
                    <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit">ویرایش</button>
                    <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="toggle">
                        ${e.is_active?"غیرفعال":"فعال"} کن
                    </button>
                    <button class="acc-btn acc-btn--danger acc-btn--sm" data-action="delete">حذف</button>
                </div>
            </div>
        `}_accountLabel(e){if(!e)return"?";const t=this._accounts.find(s=>String(s.id)===String(e)||String(s.account_id)===String(e));return t?`${t.code??t.account_code} — ${t.name??t.account_name}`:`#${e}`}_openForm(e=null){var d;const t=!!e,s=this._accounts.map(h=>`<option value="${h.id??h.account_id}">
                ${this.escape((h.code??h.account_code)+" — "+(h.name??h.account_name))}
             </option>`).join(""),a=t?typeof e.mapping_logic=="string"?e.mapping_logic:JSON.stringify(e.mapping_logic,null,2):JSON.stringify(Bn,null,2),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
            <div class="acc-modal" style="max-width:680px;max-height:90vh;overflow-y:auto;">
                <button class="acc-modal__close" type="button">✕</button>
                <div class="acc-modal__title">
                    ${t?`ویرایش Template — v${e.version}`:"Template جدید"}
                </div>
                <form id="tpl-form">
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>نوع رویداد (event_type) *</label>
                            <input name="event_type" value="${this.escape((e==null?void 0:e.event_type)??"")}"
                                   placeholder="مثال: SALES_INVOICE" required
                                   ${t?"readonly style='background:#f8fafc'":""}>
                        </div>
                        <div class="acc-form-group">
                            <label>نام Template</label>
                            <input name="template_name" value="${this.escape((e==null?void 0:e.template_name)??"")}">
                        </div>
                    </div>

                    <div class="acc-form-group">
                        <label>توضیحات</label>
                        <input name="description" value="${this.escape((e==null?void 0:e.description)??"")}">
                    </div>

                    <!-- ساخت بصری Pairs -->
                    <div style="margin-bottom:8px;font-size:13px;font-weight:600;color:#374151;">
                        🔗 Pairs (بدهکار / بستانکار)
                    </div>
                    <div id="pairs-builder" style="margin-bottom:12px;"></div>
                    <button type="button" id="add-pair-btn"
                            class="acc-btn acc-btn--secondary acc-btn--sm">+ افزودن Pair</button>

                    <!-- JSON پیشرفته -->
                    <details style="margin-top:16px;">
                        <summary style="cursor:pointer;font-size:12px;color:#64748b;padding:8px 0;">
                            ⚙️ ویرایش JSON مستقیم (پیشرفته)
                        </summary>
                        <div class="acc-form-group" style="margin-top:8px;">
                            <textarea id="logic-json" rows="10"
                                      style="font-family:monospace;font-size:12px;">${this.escape(a)}</textarea>
                            <small style="color:#94a3b8;">ساختار: { "pairs": [{ "dr_gl_id":N, "cr_gl_id":N, "source_field":"...", "desc":"..." }] }</small>
                        </div>
                    </details>

                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary" id="tpl-submit">
                            ${t?"ذخیره":"ایجاد Template"}
                        </button>
                    </div>
                </form>
            </div>
        `,document.body.appendChild(i);let n=[];try{n=((d=JSON.parse(a))==null?void 0:d.pairs)??[]}catch{}const r=i.querySelector("#pairs-builder"),o=i.querySelector("#logic-json"),l=()=>{r.innerHTML="",n.forEach((h,u)=>{const f=document.createElement("div");f.style.cssText="display:grid;grid-template-columns:1fr 1fr 1fr 80px auto;gap:8px;margin-bottom:8px;align-items:end;",f.innerHTML=`
                    <div class="acc-form-group" style="margin:0">
                        <label style="font-size:11px;">بدهکار (DR)</label>
                        <select class="pair-dr">${s}</select>
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label style="font-size:11px;">بستانکار (CR)</label>
                        <select class="pair-cr">${s}</select>
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label style="font-size:11px;">source_field</label>
                        <input class="pair-src" type="text" value="${this.escape(h.source_field||"amount")}" placeholder="amount">
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label style="font-size:11px;">شرح</label>
                        <input class="pair-desc" type="text" value="${this.escape(h.desc||"")}">
                    </div>
                    <button type="button" class="acc-btn acc-btn--danger acc-btn--sm pair-del" style="margin-top:20px;">✕</button>
                `,f.querySelector(".pair-dr").value=h.dr_gl_id??"",f.querySelector(".pair-cr").value=h.cr_gl_id??"";const m=()=>{n[u]={dr_gl_id:Number(f.querySelector(".pair-dr").value)||null,cr_gl_id:Number(f.querySelector(".pair-cr").value)||null,source_field:f.querySelector(".pair-src").value.trim()||"amount",desc:f.querySelector(".pair-desc").value.trim()},o.value=JSON.stringify({pairs:n},null,2)};f.querySelectorAll("select, input").forEach(b=>b.addEventListener("change",m)),f.querySelectorAll("input").forEach(b=>b.addEventListener("input",m)),f.querySelector(".pair-del").addEventListener("click",()=>{n.splice(u,1),l(),o.value=JSON.stringify({pairs:n},null,2)}),r.appendChild(f)})};l(),i.querySelector("#add-pair-btn").addEventListener("click",()=>{n.push({dr_gl_id:null,cr_gl_id:null,source_field:"amount",desc:""}),l()}),o.addEventListener("change",()=>{try{const h=JSON.parse(o.value);n=(h==null?void 0:h.pairs)??[],l()}catch{}});const c=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",c),i.querySelector("[data-action='cancel']").addEventListener("click",c),i.addEventListener("click",h=>{h.target===i&&c()}),i.querySelector("#tpl-form").addEventListener("submit",async h=>{h.preventDefault();const u=i.querySelector("#tpl-form");let f=o.value.trim();try{if(!JSON.parse(f).pairs)throw new Error("کلید pairs وجود ندارد")}catch(v){alert("mapping_logic نامعتبر: "+v.message);return}const m={event_type:u.querySelector("[name='event_type']").value.trim(),template_name:u.querySelector("[name='template_name']").value.trim(),description:u.querySelector("[name='description']").value.trim(),mapping_logic:JSON.parse(f),is_active:1},b=i.querySelector("#tpl-submit");b.disabled=!0,b.textContent="در حال ذخیره...";try{t?await this.api.put(`/accounting/templates/${e.id}`,m):await this.api.post("/accounting/templates",m),c(),await this._loadAll()}catch(v){b.disabled=!1,b.textContent=t?"ذخیره":"ایجاد Template",alert("خطا: "+((v==null?void 0:v.message)??""))}})}async _toggleActive(e){try{await this.api.put(`/accounting/templates/${e.id}`,{is_active:e.is_active?0:1}),await this._loadAll()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}async _delete(e){if(confirm(`حذف (غیرفعال) template «${e.template_name||e.event_type} v${e.version}»؟`))try{await this.api.delete(`/accounting/templates/${e.id}`),await this._loadAll()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}}g(as,"title","");const zn=x;class is extends zn{constructor(e={}){super(e),this.api=e.api,this._events=[],this._accounts=[],this._dimensions=[],this._page=1,this._pageSize=20,this._stateFilter="",this._suggest=null,this._suggestTimer=null}async template(){return`
            <div class="doc-layout">

                <!-- فرم ثبت رویداد جدید -->
                <div class="doc-form" data-ref="createForm">
                    <div class="doc-form__title">➕ ثبت رویداد مالی جدید</div>

                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>نوع رویداد</label>
                            <input data-ref="fEventType" type="text" list="evtTypesList"
                                   placeholder="مثال: SALES_INVOICE" required autocomplete="off">
                            <datalist id="evtTypesList" data-ref="evtTypesList"></datalist>
                        </div>
                        <div class="acc-form-group">
                            <label>مبلغ پایه</label>
                            <input data-ref="fAmount" type="number" min="0" step="any"
                                   placeholder="0" required>
                        </div>
                    </div>

                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>حساب مرجع (اختیاری)</label>
                            <select data-ref="fAccount">
                                <option value="">— انتخاب کنید —</option>
                            </select>
                        </div>
                        <div class="acc-form-group">
                            <label>بُعد (Dimension)</label>
                            <select data-ref="fDimension">
                                <option value="">— انتخاب کنید —</option>
                            </select>
                        </div>
                    </div>

                    <!-- پنلِ پیشنهاد + پیش‌نمایشِ بدهکار/بستانکار -->
                    <div class="doc-suggest" data-ref="suggestPanel" style="display:none;"></div>

                    <div class="doc-metadata">
                        <div class="doc-metadata__title">متادیتا (مقادیر اضافه)</div>
                        <div data-ref="metaRows"></div>
                        <button type="button" class="acc-btn acc-btn--secondary acc-btn--sm"
                                data-ref="addMetaBtn" style="margin-top:8px;">+ افزودن فیلد</button>
                    </div>

                    <div style="margin-top:16px;display:flex;gap:10px;align-items:center;">
                        <button class="acc-btn acc-btn--primary" data-ref="submitEventBtn">
                            ثبت و صدور جریان‌ها
                        </button>
                        <span class="acc-loading" data-ref="createSpinner" style="display:none;padding:0;gap:6px;">
                            <span class="acc-spinner"></span> در حال ثبت...
                        </span>
                    </div>
                </div>

                <!-- لیست رویدادها -->
                <div>
                    <div style="display:flex;align-items:center;gap:10px;margin-bottom:14px;flex-wrap:wrap;">
                        <strong style="font-size:14px;">📋 رویدادهای ثبت‌شده</strong>
                        <select class="event-type-filter" data-ref="stateFilter">
                            <option value="">همه وضعیت‌ها</option>
                            <option value="pending">در انتظار</option>
                            <option value="posted">ثبت‌شده</option>
                            <option value="confirmed">تأییدشده</option>
                            <option value="cancelled">لغوشده</option>
                            <option value="failed">خطا</option>
                        </select>
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄 بارگذاری مجدد</button>
                    </div>
                    <div data-ref="eventsList"></div>
                    <div data-ref="pagination" style="display:flex;gap:8px;margin-top:14px;justify-content:center;"></div>
                </div>

            </div>
        `}async afterRender(){await this._loadLookups(),await this._loadEventTypes(),this.on(this.ref("addMetaBtn"),"click",()=>this._addMetaRow()),this.on(this.ref("submitEventBtn"),"click",()=>this._submitEvent()),this.on(this.ref("refreshBtn"),"click",()=>this._loadEvents()),this.on(this.ref("stateFilter"),"change",e=>{this._stateFilter=e.target.value,this._page=1,this._loadEvents()}),this.on(this.ref("fEventType"),"input",e=>{const t=e.target.value.trim();clearTimeout(this._suggestTimer),this._suggestTimer=setTimeout(()=>this._loadSuggestion(t),350)}),this.on(this.ref("fAmount"),"input",()=>this._recalcPreview()),await this._loadEvents()}async _loadEventTypes(){try{const e=await this.api.get("/accounting/event-types"),t=this.ref("evtTypesList");if(!t)return;t.innerHTML=((e==null?void 0:e.data)??[]).map(s=>`<option value="${this.escape(s)}">`).join("")}catch{}}async _loadLookups(){try{const[e,t]=await Promise.all([this.api.get("/accounting/accounts"),this.api.get("/accounting/dimensions")]),s=(e==null?void 0:e.data)??[],a=(t==null?void 0:t.data)??[],i=this.ref("fAccount");s.forEach(r=>{const o=document.createElement("option");o.value=r.id,o.textContent=`${r.code} — ${r.name}`,i.appendChild(o)});const n=this.ref("fDimension");a.forEach(r=>{const o=document.createElement("option");o.value=r.id;const l=r.group_name||r.dim_type||"بُعد";o.textContent=`${l}: ${r.name??"#"+(r.entity_id??"")}`,n.appendChild(o)}),this._accounts=s,this._dimensions=a}catch{}}_addMetaRow(e="",t="",s=!1){const a=this.ref("metaRows"),i=document.createElement("div");i.className="doc-metadata-row",i.innerHTML=`
            <input type="text"  placeholder="کلید (مثال: vat_amount)" value="${this.escape(e)}"
                   class="meta-key" ${s?"readonly style='background:#f1f5f9'":""}>
            <input type="number" placeholder="مقدار" value="${this.escape(t)}"
                   class="meta-val" step="any">
        `,i.querySelector(".meta-val").addEventListener("input",()=>this._recalcPreview()),a.appendChild(i)}_collectMeta(){const e={};return this.ref("metaRows").querySelectorAll(".doc-metadata-row").forEach(t=>{const s=t.querySelector(".meta-key").value.trim(),a=t.querySelector(".meta-val").value.trim();s&&(e[s]=Number(a)||a)}),Object.keys(e).length?e:null}_currentPayload(){var s,a;const e={},t=parseFloat((s=this.ref("fAmount"))==null?void 0:s.value);return isNaN(t)||(e.amount=t),(a=this.ref("metaRows"))==null||a.querySelectorAll(".doc-metadata-row").forEach(i=>{const n=i.querySelector(".meta-key").value.trim(),r=i.querySelector(".meta-val").value.trim();n&&r!==""&&(e[n]=Number(r)||0)}),e}async _loadSuggestion(e){const t=this.ref("suggestPanel");if(!e){this._suggest=null,this._lastTplKey=null,t&&(t.style.display="none");return}try{const i=await this.api.get("/accounting/suggest",{event_type:e});this._suggest=(i==null?void 0:i.data)??null}catch{this._suggest=null}if(!this._suggest){t&&(t.style.display="none");return}const s=this._suggest.template,a=s?`tpl:${s.id}`:`none:${e}`;a!==this._lastTplKey&&(this._lastTplKey=a,s&&(this.ref("metaRows").innerHTML="",(this._suggest.source_fields||[]).forEach(i=>{i!=="amount"&&this._addMetaRow(i,"",!0)}))),this._renderSuggest(),this._recalcPreview()}_renderSuggest(){const e=this.ref("suggestPanel");if(!e||!this._suggest)return;const t=this._suggest;if(e.style.display="block",t.template){const s=t.template,a=s.pairs.map(n=>`
                <div class="doc-sg-art">
                    <span class="flow-direction__from">${this.escape(n.dr_code)} ${this.escape(n.dr_name)}</span>
                    <span style="color:#94a3b8">→</span>
                    <span class="flow-direction__to">${this.escape(n.cr_code)} ${this.escape(n.cr_name)}</span>
                    <span class="doc-sg-src">[${this.escape(n.source_field||"amount")}]</span>
                    ${n.article_code?`<span class="doc-sg-link" title="${this.escape(n.article_label||"")}">🔗 ${this.escape(n.article_code)}</span>`:""}
                </div>`).join(""),i=t.history.posted_count?`${new Intl.NumberFormat("fa-IR").format(t.history.posted_count)} بار قبلاً ثبت شده`:"تا حالا ثبت نشده";e.innerHTML=`
                <div class="doc-sg-head">🔮 ${this.escape(s.template_name||t.event_type||"")} <small>v${s.version} · ${i}</small></div>
                <div class="doc-sg-arts">${a}</div>
                <div data-ref="docPreview"></div>`}else{const s=t.suggested_articles||[],a=s.length?`<div class="doc-sg-arts">${s.map(i=>`<div class="doc-sg-art"><b>${this.escape(i.code)}</b> ${this.escape(i.label)} <span class="doc-sg-src">[${this.escape(i.amount_source)}]</span></div>`).join("")}</div>`:"";e.innerHTML=`
                <div class="doc-sg-head" style="color:#b45309">⚠️ برای «${this.escape(t.event_type)}» template فعالی نیست.</div>
                <div style="font-size:12px;color:#64748b;margin:4px 0 8px;">مقادیر را با «متادیتا» دستی وارد کنید، یا یک template بسازید.${s.length?" آرتیکل‌های پیشنهادیِ هم‌دسته:":""}</div>
                ${a}`}}_recalcPreview(){var r;const e=this.ref("suggestPanel");if(!e)return;const t=e.querySelector("[data-ref='docPreview']");if(!t||!((r=this._suggest)!=null&&r.template))return;const s=this._currentPayload(),a=o=>new Intl.NumberFormat("fa-IR").format(Number(o||0));let i=0;const n=[];if(this._suggest.template.pairs.forEach(o=>{const l=o.source_field&&o.source_field!==""?Number(s[o.source_field]||0):Number(s.amount||0);l&&(i+=l,n.push(`<tr>
                <td><span class="flow-direction__from">${this.escape(o.dr_code)}</span> ${this.escape(o.dr_name)}</td>
                <td><span class="flow-direction__to">${this.escape(o.cr_code)}</span> ${this.escape(o.cr_name)}</td>
                <td class="num">${a(l)}</td>
            </tr>`))}),!n.length){t.innerHTML='<div style="font-size:12px;color:#94a3b8;padding:8px 0;">مبالغ را وارد کنید تا پیش‌نمایشِ آرتیکل‌ها بیاید.</div>';return}t.innerHTML=`
            <table class="flows-table" style="margin-top:8px;">
                <thead><tr><th>حساب بدهکار</th><th>حساب بستانکار</th><th>مبلغ</th></tr></thead>
                <tbody>${n.join("")}</tbody>
                <tfoot><tr style="font-weight:700;background:#f8fafc;"><td colspan="2">جمع</td><td class="num">${a(i)}</td></tr></tfoot>
            </table>
            <div style="font-size:11px;color:#059669;margin-top:4px;">✓ هر آرتیکل در یک ردیف، ذاتاً تراز (بدهکار = بستانکار).</div>`}async _submitEvent(){var o;const e=this.ref("fEventType").value.trim(),t=parseFloat(this.ref("fAmount").value),s=this.ref("fAccount").value||null,a=this.ref("fDimension").value||null,i=this._collectMeta();if(!e){alert("نوع رویداد الزامی است.");return}if(isNaN(t)||t<=0){alert("مبلغ معتبر وارد کنید.");return}const n=this.ref("submitEventBtn"),r=this.ref("createSpinner");n.disabled=!0,r.style.display="flex";try{const l={event_type:e,amount:t,account_id:s?Number(s):null,dimension_id:a?Number(a):null,metadata:i},c=await this.api.post("/accounting/events",l),d=(o=c==null?void 0:c.data)==null?void 0:o.id;this.ref("fEventType").value="",this.ref("fAmount").value="",this.ref("fAccount").value="",this.ref("fDimension").value="",this.ref("metaRows").innerHTML="",this._suggest=null,this._lastTplKey=null;const h=this.ref("suggestPanel");h&&(h.style.display="none",h.innerHTML=""),this._loadEventTypes(),await this._loadEvents(),d&&this._highlightEvent(d)}catch(l){alert("خطا: "+((l==null?void 0:l.message)??"لطفاً دوباره تلاش کنید"))}finally{n.disabled=!1,r.style.display="none"}}async _loadEvents(){const e=this.ref("eventsList");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t={page:this._page,per_page:this._pageSize};this._stateFilter&&(t.state=this._stateFilter);const s=this._stateFilter?await this.api.get("/accounting/events",t):await this.api.get("/accounting/events",t);this._events=(s==null?void 0:s.data)??[];const a=(s==null?void 0:s.total)??this._events.length;this._renderEvents(e),this._renderPagination(a)}catch{e.innerHTML='<div class="acc-error">خطا در دریافت رویدادها</div>'}}_renderEvents(e){if(!this._events.length){e.innerHTML='<div class="acc-empty">رویدادی یافت نشد.</div>';return}e.innerHTML="",this._events.forEach(t=>{const s=this._buildEventCard(t);e.appendChild(s)})}_buildEventCard(e){var r,o,l,c,d;const t={draft:"status-badge--draft",pending:"status-badge--draft",processing:"status-badge--pending",posted:"status-badge--confirmed",confirmed:"status-badge--confirmed",cancelled:"status-badge--cancelled",failed:"status-badge--cancelled"}[e.workflow_state]??"status-badge--pending",s={draft:"پیش‌نویس",pending:"در انتظار",processing:"در پردازش",posted:"ثبت‌شده",confirmed:"تأییدشده",cancelled:"لغوشده",failed:"خطا"}[e.workflow_state]??e.workflow_state,a=document.createElement("div");a.className="doc-event-card",a.dataset.eventId=e.id,a.style.cssText="background:#fff;border:1.5px solid #e2e8f0;border-radius:12px;padding:16px 18px;margin-bottom:10px;";const i=e.reverses_event_id?`<span class="status-badge status-badge--pending" title="برگشت رویداد #${e.reverses_event_id}">↩ برگشتی</span>`:e.reversed_by_event_id?`<span class="status-badge status-badge--cancelled" title="برگشت خورده — سند #${e.reversed_by_event_id}">⊘ خنثی‌شده</span>`:"",n=["posted","confirmed"].includes(e.workflow_state)&&!e.reversed_by_event_id;return a.innerHTML=`
            <div style="display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;">
                <div>
                    <span style="font-size:12px;color:#94a3b8;font-family:monospace;">#${e.id}</span>
                    <span style="font-size:14px;font-weight:700;color:#1e293b;margin-right:8px;">${this.escape(e.event_type)}</span>
                    <span class="status-badge ${t}">${s}</span>
                    ${i}
                </div>
                <div style="font-size:13px;color:#475569;">
                    ${new Intl.NumberFormat("fa-IR").format(e.amount)} ریال
                </div>
            </div>
            <div style="margin-top:8px;display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="flows">
                    🔍 نمایش جریان‌ها
                </button>
                ${["draft","pending","failed"].includes(e.workflow_state)?`
                    <button class="acc-btn acc-btn--primary acc-btn--sm" data-action="post"
                            title="پست رویداد با Acc_Event_Engine">🔁 ثبت در دفتر</button>
                `:""}
                ${e.workflow_state==="posted"?`
                    <button class="acc-btn acc-btn--success acc-btn--sm" data-action="confirm">✅ تأیید نهایی</button>
                    <button class="acc-btn acc-btn--danger  acc-btn--sm" data-action="cancel">❌ لغو</button>
                `:""}
                ${n?`
                    <button class="acc-btn acc-btn--warning acc-btn--sm" data-action="reverse"
                            title="صدور سند برگشتی (storno)">↩ سند برگشتی</button>
                `:""}
            </div>
            <div class="flows-panel" data-ref="flows-${e.id}" style="display:none;margin-top:12px;"></div>
        `,(r=a.querySelector("[data-action='flows']"))==null||r.addEventListener("click",()=>this._toggleFlows(e.id,a)),(o=a.querySelector("[data-action='post']"))==null||o.addEventListener("click",()=>this._postToLedger(e.id,a)),(l=a.querySelector("[data-action='confirm']"))==null||l.addEventListener("click",()=>this._confirmEvent(e.id)),(c=a.querySelector("[data-action='reverse']"))==null||c.addEventListener("click",()=>this._reverseEvent(e.id)),(d=a.querySelector("[data-action='cancel']"))==null||d.addEventListener("click",()=>this._cancelEvent(e.id)),a}async _toggleFlows(e,t){const s=t.querySelector(".flows-panel");if(s){if(s.style.display!=="none"){s.style.display="none";return}s.style.display="block",s.innerHTML='<div class="acc-loading" style="padding:16px 0;"><div class="acc-spinner"></div></div>';try{const a=await this.api.get("/accounting/flows",{event_id:e}),i=(a==null?void 0:a.data)??[];this._renderFlowsPanel(s,i)}catch{s.innerHTML='<div class="acc-error">خطا در دریافت جریان‌ها</div>'}}}_renderFlowsPanel(e,t){if(!t.length){e.innerHTML='<div class="acc-empty" style="padding:16px 0;">جریانی تولید نشده است.</div>';return}e.innerHTML=`
            <div class="flows-preview">
                <div class="flows-preview__title">
                    جریان‌های مالی
                    <span class="flows-preview__badge">${t.length} جریان</span>
                </div>
                <table class="flows-table">
                    <thead>
                        <tr>
                            <th>از حساب</th>
                            <th>به حساب</th>
                            <th>مبلغ (ریال)</th>
                            <th>وضعیت</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${t.map(s=>`
                            <tr>
                                <td>
                                    <div class="flow-direction__from">
                                        ${this.escape(s.from_account_name??"#"+s.from_account_id)}
                                    </div>
                                </td>
                                <td>
                                    <div class="flow-direction__to">
                                        ${this.escape(s.to_account_name??"#"+s.to_account_id)}
                                    </div>
                                </td>
                                <td class="flow-amount num">
                                    ${new Intl.NumberFormat("fa-IR").format(s.amount)}
                                </td>
                                <td>
                                    <span class="status-badge ${s.is_confirmed?"status-badge--confirmed":"status-badge--draft"}">
                                        ${s.is_confirmed?"تأیید":"پیش‌نویس"}
                                    </span>
                                </td>
                            </tr>
                        `).join("")}
                    </tbody>
                </table>
            </div>
        `}async _postToLedger(e,t){const s=t.querySelector("[data-action='post']");s&&(s.disabled=!0,s.textContent="⏳ در حال ثبت...");try{const a=await this.api.post(`/accounting/events/${e}/post`,{});if(a!=null&&a.success){const i=a.message??"ثبت موفق",n=document.createElement("div");n.style.cssText="position:fixed;bottom:24px;right:24px;background:#059669;color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;box-shadow:0 4px 20px rgba(0,0,0,.15);",n.textContent="✅ "+i,document.body.appendChild(n),setTimeout(()=>n.remove(),3e3),await this._loadEvents()}else{const i=(a==null?void 0:a.message)??"خطای نامشخص";alert(`خطا در ثبت سند:
${i}`),s&&(s.disabled=!1,s.textContent="🔁 ثبت در دفتر")}}catch(a){alert("خطا: "+((a==null?void 0:a.message)??"")),s&&(s.disabled=!1,s.textContent="🔁 ثبت در دفتر")}}async _confirmEvent(e){if(confirm("تأیید این رویداد؟ پس از تأیید قابل لغو نیست."))try{await this.api.post(`/accounting/events/${e}/confirm`,{}),await this._loadEvents()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}async _reverseEvent(e){if(confirm("صدور سند برگشتی (storno) برای این رویداد؟"))try{const t=await this.api.post(`/accounting/events/${e}/reverse`,{});alert((t==null?void 0:t.message)||(t!=null&&t.success?"سند برگشتی صادر شد":"خطا")),await this._loadEvents()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}async _cancelEvent(e){if(confirm("لغو این رویداد؟"))try{await this.api.post(`/accounting/events/${e}/cancel`,{}),await this._loadEvents()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}_renderPagination(e){const t=Math.ceil(e/this._pageSize),s=this.ref("pagination");if(!s||t<=1){s&&(s.innerHTML="");return}s.innerHTML="";for(let a=1;a<=t;a++){const i=document.createElement("button");i.className=`acc-btn acc-btn--sm ${a===this._page?"acc-btn--primary":"acc-btn--secondary"}`,i.textContent=a,i.addEventListener("click",()=>{this._page=a,this._loadEvents()}),s.appendChild(i)}}_highlightEvent(e){setTimeout(()=>{var s;const t=(s=this.ref("eventsList"))==null?void 0:s.querySelector(`[data-event-id="${e}"]`);t&&(t.style.borderColor="#2563eb",t.scrollIntoView({behavior:"smooth",block:"nearest"}),setTimeout(()=>{t.style.borderColor=""},2e3))},300)}}g(is,"title","");const jn=x,ns=[{key:"trial_balance",label:"📊 تراز آزمایشی"},{key:"income",label:"📈 سود و زیان"},{key:"balance_sheet",label:"⚖️ ترازنامه"},{key:"ledger",label:"📒 دفتر کل"},{key:"flow_journal",label:"📝 ژورنال جریان"}];class rs extends jn{constructor(e={}){super(e),this.api=e.api,this._activeTab="trial_balance",this._accounts=[]}async template(){const e=ns.map(s=>`
            <button class="reports-tab-btn ${s.key===this._activeTab?"reports-tab-btn--active":""}"
                    data-tab="${s.key}">${s.label}</button>
        `).join(""),t=ns.map(s=>`
            <div class="reports-content ${s.key===this._activeTab?"reports-content--active":""}"
                 data-panel="${s.key}" data-ref="panel-${s.key}"></div>
        `).join("");return`
            <div class="reports-tabs" data-ref="tabBar">${e}</div>
            ${t}
        `}async afterRender(){this.ref("tabBar").querySelectorAll(".reports-tab-btn").forEach(e=>{this.on(e,"click",()=>this._switchTab(e.dataset.tab))});try{const e=await this.api.get("/accounting/accounts");this._accounts=(e==null?void 0:e.data)??[]}catch{}await this._loadActiveTab()}async _switchTab(e){e!==this._activeTab&&(this.ref("tabBar").querySelectorAll(".reports-tab-btn").forEach(t=>{t.classList.toggle("reports-tab-btn--active",t.dataset.tab===e)}),this.container.querySelectorAll(".reports-content").forEach(t=>{t.classList.toggle("reports-content--active",t.dataset.panel===e)}),this._activeTab=e,await this._loadActiveTab())}async _loadActiveTab(){const e=this.ref(`panel-${this._activeTab}`);if(e)switch(this._activeTab){case"trial_balance":await this._renderTrialBalance(e);break;case"income":await this._renderIncomeStatement(e);break;case"balance_sheet":await this._renderBalanceSheet(e);break;case"ledger":this._renderLedgerShell(e);break;case"flow_journal":await this._renderFlowJournal(e);break}}async _renderTrialBalance(e){e.innerHTML=`
            <div class="report-filter-bar">
                <label>از تاریخ</label>
                <input type="date" data-ref="tbFrom">
                <label>تا تاریخ</label>
                <input type="date" data-ref="tbTo">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="tbRun">اجرا</button>
            </div>
            <div data-ref="tbResult"></div>
        `;const t=e.querySelector("[data-ref='tbFrom']"),s=e.querySelector("[data-ref='tbTo']"),a=e.querySelector("[data-ref='tbRun']"),i=e.querySelector("[data-ref='tbResult']");a.addEventListener("click",async()=>{await this._fetchTrialBalance(i,t.value,s.value)}),await this._fetchTrialBalance(i,"","")}async _fetchTrialBalance(e,t,s){e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال محاسبه...</div>';try{const a={};t&&(a.date_from=t),s&&(a.date_to=s);const i=await this.api.get("/accounting/reports/trial-balance",a),n=(i==null?void 0:i.data)??[];if(!n.length){e.innerHTML='<div class="acc-empty">داده‌ای یافت نشد.</div>';return}let r=0,o=0,l=0;n.forEach(c=>{r+=Number(c.total_debit??0),o+=Number(c.total_credit??0),l+=Number(c.net_balance??0)}),e.innerHTML=`
                <table class="tb-table">
                    <thead>
                        <tr>
                            <th>کد</th>
                            <th>نام حساب</th>
                            <th>جمع بدهکار</th>
                            <th>جمع بستانکار</th>
                            <th>مانده خالص</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${n.map(c=>`
                            <tr>
                                <td style="font-family:monospace;font-size:12px;color:#94a3b8;">${this.escape(c.code??"")}</td>
                                <td>${this.escape(c.name)}</td>
                                <td class="num">${this._fmt(c.total_debit)}</td>
                                <td class="num">${this._fmt(c.total_credit)}</td>
                                <td class="num ${Number(c.net_balance)>=0?"tb-positive":"tb-negative"}">
                                    ${this._fmt(c.net_balance)}
                                </td>
                            </tr>
                        `).join("")}
                    </tbody>
                    <tfoot>
                        <tr class="tb-table__footer">
                            <td colspan="2">جمع کل</td>
                            <td class="num">${this._fmt(r)}</td>
                            <td class="num">${this._fmt(o)}</td>
                            <td class="num ${l>=0?"tb-positive":"tb-negative"}">${this._fmt(l)}</td>
                        </tr>
                    </tfoot>
                </table>
            `}catch{e.innerHTML='<div class="acc-error">خطا در دریافت تراز آزمایشی</div>'}}async _renderIncomeStatement(e){e.innerHTML=`
            <div class="report-filter-bar">
                <label>از تاریخ</label><input type="date" data-ref="isFrom">
                <label>تا تاریخ</label><input type="date" data-ref="isTo">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="isRun">اجرا</button>
            </div>
            <div data-ref="isResult"></div>`;const t=e.querySelector("[data-ref='isFrom']"),s=e.querySelector("[data-ref='isTo']"),a=e.querySelector("[data-ref='isRun']"),i=e.querySelector("[data-ref='isResult']");a.addEventListener("click",()=>this._fetchIncome(i,t.value,s.value)),await this._fetchIncome(i,"","")}async _fetchIncome(e,t,s){e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال محاسبه...</div>';try{const a={};t&&(a.date_from=t),s&&(a.date_to=s);const i=await this.api.get("/accounting/reports/income-statement",a),n=i==null?void 0:i.data;if(!n){e.innerHTML='<div class="acc-empty">داده‌ای یافت نشد.</div>';return}const r=(l,c,d,h)=>`
                <tr class="is-section"><td colspan="2">${l}</td></tr>
                ${c.length?c.map(u=>`<tr><td>${this.escape(u.code)} ${this.escape(u.name)}</td><td class="num">${this._fmt(u.amount)}</td></tr>`).join(""):'<tr><td colspan="2" style="color:#94a3b8;font-size:12px;">—</td></tr>'}
                <tr class="is-subtotal"><td>جمع ${l}</td><td class="num" style="color:${h}">${this._fmt(d)}</td></tr>`,o=Number(n.net_income)>=0?"#059669":"#dc2626";e.innerHTML=`
                <table class="tb-table"><tbody>
                    ${r("درآمد",n.revenue,n.revenue_total,"#059669")}
                    ${n.contra.length?r("کسوراتِ فروش",n.contra,n.contra_total,"#dc2626"):""}
                    <tr class="is-net"><td>خالص فروش</td><td class="num">${this._fmt(n.net_sales)}</td></tr>
                    ${r("هزینه‌ها",n.expense,n.expense_total,"#dc2626")}
                    <tr class="is-final"><td>${Number(n.net_income)>=0?"سود":"زیان"} خالص دوره</td>
                        <td class="num" style="color:${o};font-weight:800;">${this._fmt(Math.abs(n.net_income))}</td></tr>
                </tbody></table>`}catch{e.innerHTML='<div class="acc-error">خطا در دریافت صورت سود و زیان</div>'}}async _renderBalanceSheet(e){e.innerHTML=`
            <div class="report-filter-bar">
                <label>تا تاریخ</label><input type="date" data-ref="bsTo">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="bsRun">اجرا</button>
            </div>
            <div data-ref="bsResult"></div>`;const t=e.querySelector("[data-ref='bsTo']"),s=e.querySelector("[data-ref='bsRun']"),a=e.querySelector("[data-ref='bsResult']");s.addEventListener("click",()=>this._fetchBalanceSheet(a,t.value)),await this._fetchBalanceSheet(a,"")}async _fetchBalanceSheet(e,t){e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال محاسبه...</div>';try{const s={};t&&(s.date_to=t);const a=await this.api.get("/accounting/reports/balance-sheet",s),i=a==null?void 0:a.data;if(!i){e.innerHTML='<div class="acc-empty">داده‌ای یافت نشد.</div>';return}const n=(l,c,d)=>`
                <tr class="is-section"><td colspan="2">${l}</td></tr>
                ${c.length?c.map(h=>`<tr><td>${this.escape(h.code)} ${this.escape(h.name)}</td><td class="num">${this._fmt(h.amount)}</td></tr>`).join(""):'<tr><td colspan="2" style="color:#94a3b8;font-size:12px;">—</td></tr>'}
                <tr class="is-subtotal"><td>جمع ${l}</td><td class="num">${this._fmt(d)}</td></tr>`,r=Number(i.net_income)>=0?"#059669":"#dc2626",o=i.balanced?'<span class="status-badge status-badge--confirmed">✓ تراز است</span>':`<span class="status-badge status-badge--cancelled">✗ اختلاف: ${this._fmt(i.difference)}</span>`;e.innerHTML=`
                <div style="display:flex;gap:16px;flex-wrap:wrap;">
                    <div style="flex:1;min-width:280px;">
                        <table class="tb-table"><tbody>${n("دارایی‌ها",i.asset,i.asset_total)}</tbody></table>
                    </div>
                    <div style="flex:1;min-width:280px;">
                        <table class="tb-table"><tbody>
                            ${n("بدهی‌ها",i.liability,i.liability_total)}
                            ${n("حقوق صاحبان سهام",i.equity,i.equity_total)}
                            <tr><td>${Number(i.net_income)>=0?"سود":"زیان"} انباشتهٔ دوره</td>
                                <td class="num" style="color:${r}">${this._fmt(Math.abs(i.net_income))}</td></tr>
                            <tr class="is-final"><td>جمع بدهی + حقوق</td><td class="num">${this._fmt(i.liab_equity_total)}</td></tr>
                        </tbody></table>
                    </div>
                </div>
                <div style="text-align:center;margin-top:14px;font-size:14px;">
                    دارایی ${this._fmt(i.asset_total)} = بدهی+حقوق ${this._fmt(i.liab_equity_total)} &nbsp; ${o}
                </div>`}catch{e.innerHTML='<div class="acc-error">خطا در دریافت ترازنامه</div>'}}_renderLedgerShell(e){const t=this._accounts.map(o=>`<option value="${o.id}">${this.escape(o.code+" — "+o.name)}</option>`).join("");e.innerHTML=`
            <div class="report-filter-bar">
                <label>حساب</label>
                <select data-ref="ldgAccount" style="min-width:200px;">
                    <option value="">انتخاب کنید...</option>
                    ${t}
                </select>
                <label>از</label>
                <input type="date" data-ref="ldgFrom">
                <label>تا</label>
                <input type="date" data-ref="ldgTo">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="ldgRun">نمایش</button>
            </div>
            <div data-ref="ldgResult"></div>
        `;const s=e.querySelector("[data-ref='ldgAccount']"),a=e.querySelector("[data-ref='ldgFrom']"),i=e.querySelector("[data-ref='ldgTo']"),n=e.querySelector("[data-ref='ldgRun']"),r=e.querySelector("[data-ref='ldgResult']");n.addEventListener("click",async()=>{const o=s.value;if(!o){alert("لطفاً یک حساب انتخاب کنید.");return}await this._fetchLedger(r,o,a.value,i.value)})}async _fetchLedger(e,t,s,a){var i,n;e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال بارگذاری...</div>';try{const r={account_id:t};s&&(r.date_from=s),a&&(r.date_to=a);const o=await this.api.get("/accounting/reports/ledger",r),l=(o==null?void 0:o.data)??[];if(!l.length){e.innerHTML='<div class="acc-empty">تراکنشی در این بازه یافت نشد.</div>';return}const c=((i=this._accounts.find(h=>String(h.id)===String(t)))==null?void 0:i.name)??"",d=((n=l[l.length-1])==null?void 0:n.running_balance)??0;e.innerHTML=`
                <div class="ledger-header">
                    <span class="ledger-header__title">دفتر کل — ${this.escape(c)}</span>
                    <span class="ledger-header__balance">مانده نهایی: ${this._fmt(d)} ریال</span>
                </div>
                <table class="flows-table" style="border-radius:0 0 10px 10px;overflow:hidden;">
                    <thead>
                        <tr>
                            <th>#</th>
                            <th>نوع رویداد</th>
                            <th>مبلغ</th>
                            <th>جهت</th>
                            <th>مانده</th>
                            <th>تاریخ</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${l.map((h,u)=>{const f=h.direction==="in"?"⬇ ورودی":"⬆ خروجی",m=h.direction==="in"?"#059669":"#dc2626";return`
                                <tr>
                                    <td style="font-size:11px;color:#94a3b8;">${u+1}</td>
                                    <td>${this.escape(h.event_type??"")}</td>
                                    <td class="num">${this._fmt(h.amount)}</td>
                                    <td style="color:${m};font-weight:600;">${f}</td>
                                    <td class="num">${this._fmt(h.running_balance)}</td>
                                    <td style="font-size:12px;color:#64748b;">${h.created_at?h.created_at.split("T")[0]:""}</td>
                                </tr>
                            `}).join("")}
                    </tbody>
                </table>
            `}catch{e.innerHTML='<div class="acc-error">خطا در دریافت دفتر کل</div>'}}async _renderFlowJournal(e){e.innerHTML=`
            <div class="report-filter-bar">
                <label>از تاریخ</label>
                <input type="date" data-ref="jFrom">
                <label>تا تاریخ</label>
                <input type="date" data-ref="jTo">
                <label>وضعیت تأیید</label>
                <select data-ref="jConfirmed">
                    <option value="">همه</option>
                    <option value="1">تأییدشده</option>
                    <option value="0">پیش‌نویس</option>
                </select>
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="jRun">اجرا</button>
            </div>
            <div data-ref="jResult"></div>
        `;const t=e.querySelector("[data-ref='jFrom']"),s=e.querySelector("[data-ref='jTo']"),a=e.querySelector("[data-ref='jConfirmed']"),i=e.querySelector("[data-ref='jRun']"),n=e.querySelector("[data-ref='jResult']");i.addEventListener("click",()=>this._fetchJournal(n,t.value,s.value,a.value)),await this._fetchJournal(n,"","","")}async _fetchJournal(e,t,s,a){e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال بارگذاری...</div>';try{const i={};t&&(i.date_from=t),s&&(i.date_to=s),a!==""&&(i.is_confirmed=a);const n=await this.api.get("/accounting/reports/flow-journal",i),r=(n==null?void 0:n.data)??[];if(!r.length){e.innerHTML='<div class="acc-empty">جریانی یافت نشد.</div>';return}e.innerHTML=`
                <table class="flows-table">
                    <thead>
                        <tr>
                            <th>#</th>
                            <th>رویداد</th>
                            <th>نوع</th>
                            <th>از حساب</th>
                            <th>به حساب</th>
                            <th>مبلغ (ریال)</th>
                            <th>تأیید</th>
                            <th>تاریخ</th>
                        </tr>
                    </thead>
                    <tbody>
                        ${r.map((o,l)=>`
                            <tr>
                                <td style="font-size:11px;color:#94a3b8;">${l+1}</td>
                                <td style="font-family:monospace;font-size:12px;">#${o.event_id}</td>
                                <td>${this.escape(o.event_type??"")}</td>
                                <td>
                                    <span class="flow-direction__from" style="font-size:11px;">
                                        ${this.escape(o.from_account_name??"#"+o.from_account_id)}
                                    </span>
                                </td>
                                <td>
                                    <span class="flow-direction__to" style="font-size:11px;">
                                        ${this.escape(o.to_account_name??"#"+o.to_account_id)}
                                    </span>
                                </td>
                                <td class="num flow-amount">${this._fmt(o.amount)}</td>
                                <td>
                                    <span class="status-badge ${o.is_confirmed?"status-badge--confirmed":"status-badge--draft"}">
                                        ${o.is_confirmed?"✓":"⏳"}
                                    </span>
                                </td>
                                <td style="font-size:11px;color:#64748b;">${o.created_at?o.created_at.split("T")[0]:""}</td>
                            </tr>
                        `).join("")}
                    </tbody>
                </table>
            `}catch{e.innerHTML='<div class="acc-error">خطا در دریافت ژورنال</div>'}}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Number(e??0))}}g(rs,"title","");const An=x,ze={ok:{label:"سالم",color:"#059669",bg:"#dcfce7",icon:"✓"},warn:{label:"هشدار",color:"#b45309",bg:"#fef3c7",icon:"⚠"},fail:{label:"خطا",color:"#dc2626",bg:"#fee2e2",icon:"✗"}};class os extends An{constructor(e={}){super(e),this.api=e.api,this._data=null}async template(){return`
            <div class="event-toolbar">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="runBtn">🔄 اجرای کنترل‌ها</button>
                <span class="audit-overall" data-ref="overall" style="margin-right:auto;"></span>
            </div>
            <div style="background:#eff6ff;border:1px solid #bfdbfe;border-radius:10px;padding:10px 14px;
                        margin-bottom:14px;font-size:12px;color:#1e40af;line-height:1.7;">
                <strong>📌 حسابرسیِ پیوسته:</strong> چون هر آرتیکل اتمی و تراز است و از بانکِ آرتیکل می‌آید،
                بیشترِ کنترل‌های حسابرسی به کوئریِ زنده تبدیل می‌شوند — نه نمونه‌گیریِ پایان‌سال.
            </div>
            <div data-ref="grid"></div>
        `}async afterRender(){this.on(this.ref("runBtn"),"click",()=>this._load()),await this._load()}async _load(){const e=this.ref("grid");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div>در حال اجرای کنترل‌ها...</div>';try{const t=await this.api.get("/accounting/audit");if(this._data=(t==null?void 0:t.data)??null,!this._data)throw new Error("داده‌ای دریافت نشد");this._render()}catch(t){e.innerHTML=`<div class="acc-error">خطا در اجرای حسابرسی: ${this.escape((t==null?void 0:t.message)??"")}</div>`}}_render(){const e=this._data,t=e.summary,s=ze[t.overall]??ze.ok,a=this.ref("overall");a&&(a.innerHTML=`<span class="status-badge" style="background:${s.bg};color:${s.color};">
                ${s.icon} وضعیتِ کلی: ${s.label}</span>
                <small style="color:#94a3b8;margin-right:8px;">
                ${(t.confirmed_flows??0).toLocaleString("fa-IR")} آرتیکلِ تأییدشده · ${t.fails} خطا · ${t.warns} هشدار</small>`),this.ref("grid").innerHTML=`<div class="audit-grid">${e.controls.map((i,n)=>this._cardHtml(i,n)).join("")}</div>`,this.ref("grid").querySelectorAll(".audit-card__head").forEach(i=>{i.addEventListener("click",()=>{i.closest(".audit-card").classList.toggle("audit-card--open")})})}_cardHtml(e,t){const s=ze[e.severity]??ze.ok,a=(e.rows||[]).length>0,i=a?`
            <div class="audit-card__body">
                <table class="flows-table">
                    <thead><tr>${e.headers.map(n=>`<th>${this.escape(n)}</th>`).join("")}</tr></thead>
                    <tbody>
                        ${e.rows.map(n=>`<tr>${n.map(r=>`<td>${this.escape(String(r))}</td>`).join("")}</tr>`).join("")}
                    </tbody>
                </table>
                ${e.count>e.rows.length?`<div style="font-size:11px;color:#94a3b8;padding:6px 0;">نمایش ${e.rows.length} از ${e.count} مورد</div>`:""}
            </div>`:"";return`
            <div class="audit-card ${t===0&&a?"audit-card--open":""}" style="border-color:${s.color}33;">
                <div class="audit-card__head">
                    <span class="audit-card__title">${this.escape(e.title)}</span>
                    <span class="status-badge" style="background:${s.bg};color:${s.color};">${s.icon} ${s.label}${e.count?" · "+e.count:""}</span>
                    ${a?'<span class="audit-card__toggle">▾</span>':""}
                </div>
                <div class="audit-card__summary">${this.escape(e.summary||"")}</div>
                ${i}
            </div>`}}g(os,"title","");const ls={asset:"#3b82f6",liability:"#f59e0b",equity:"#8b5cf6",revenue:"#10b981",expense:"#ef4444",contra:"#64748b"},cs={asset:"دارایی",liability:"بدهی",equity:"حقوق صاحبان",revenue:"درآمد",expense:"هزینه",contra:"کنترایی"};class Fn{constructor(e,t,s,a){this.W=s,this.H=a;const i={asset:{x:s*.25,y:a*.45},liability:{x:s*.75,y:a*.35},equity:{x:s*.75,y:a*.65},revenue:{x:s*.5,y:a*.15},expense:{x:s*.5,y:a*.8},contra:{x:s*.5,y:a*.5}};this.nodes=e.map(n=>{const r=i[n.type]??{x:s/2,y:a/2};return{...n,x:r.x+(Math.random()-.5)*180,y:r.y+(Math.random()-.5)*180,vx:0,vy:0}}),this.edges=t,this.nodeMap={},this.nodes.forEach(n=>{this.nodeMap[n.id]=n})}tick(){this.nodes.forEach(r=>{r.fx=0,r.fy=0});for(let r=0;r<this.nodes.length;r++)for(let o=r+1;o<this.nodes.length;o++){const l=this.nodes[r],c=this.nodes[o],d=c.x-l.x,h=c.y-l.y,u=d*d+h*h+.01,f=4500/u,m=Math.sqrt(u);l.fx-=f*d/m,l.fy-=f*h/m,c.fx+=f*d/m,c.fy+=f*h/m}this.edges.forEach(r=>{const o=this.nodeMap[r.from],l=this.nodeMap[r.to];if(!o||!l)return;const c=l.x-o.x,d=l.y-o.y,h=Math.sqrt(c*c+d*d)+.01,u=(h-140)*.08;o.fx+=u*c/h,o.fy+=u*d/h,l.fx-=u*c/h,l.fy-=u*d/h});const i=this.W/2,n=this.H/2;this.nodes.forEach(r=>{r.vx=(r.vx+r.fx)*.82-(r.x-i)*.012,r.vy=(r.vy+r.fy)*.82-(r.y-n)*.012,r.x=Math.max(50,Math.min(this.W-50,r.x+r.vx)),r.y=Math.max(40,Math.min(this.H-40,r.y+r.vy))})}run(e=180){for(let t=0;t<e;t++)this.tick()}}class In extends x{constructor(e={}){super(e),this._mode="template",this._data=null,this._tooltip=null}async template(){return`
        <div class="acc-graph-wrap" data-ref="wrap">
            <div class="acc-graph-toolbar">
                <div class="acc-graph-mode-toggle">
                    <button class="acc-graph-mode-btn acc-graph-mode-btn--active" data-mode="template">
                        📐 روابط Template
                    </button>
                    <button class="acc-graph-mode-btn" data-mode="flow">
                        💸 جریان‌های واقعی
                    </button>
                </div>
                <div class="acc-graph-legend" data-ref="legend"></div>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="reloadBtn">🔄 بارگذاری مجدد</button>
            </div>
            <div class="acc-graph-canvas" data-ref="canvas"></div>
            <div class="acc-graph-info" data-ref="info"></div>
        </div>`}async afterRender(){this._buildLegend(),this.ref("wrap").querySelectorAll(".acc-graph-mode-btn").forEach(e=>{this.on(e,"click",()=>{this._mode=e.dataset.mode,this.ref("wrap").querySelectorAll(".acc-graph-mode-btn").forEach(t=>t.classList.toggle("acc-graph-mode-btn--active",t.dataset.mode===this._mode)),this._data&&this._draw()})}),this.on(this.ref("reloadBtn"),"click",()=>this._load()),await this._load()}_buildLegend(){this.ref("legend").innerHTML=Object.entries(cs).map(([e,t])=>`<span class="acc-graph-legend-dot" style="background:${ls[e]}"></span><span>${t}</span>`).join("")}async _load(){const e=this.ref("canvas");e.innerHTML='<div class="acc-graph-loading"><div class="acc-spinner"></div><span>در حال محاسبه گراف...</span></div>',this.ref("info").textContent="";try{const t=await this.api.get("/accounting/graph");this._data=t,this._draw()}catch(t){e.innerHTML=`<div class="acc-empty">خطا در بارگذاری گراف: ${this.escape((t==null?void 0:t.message)??"")}</div>`}}_draw(){const e=this.ref("canvas"),t=e.clientWidth||900,s=e.clientHeight||560,{nodes:a,template_edges:i,flow_edges:n}=this._data,r=this._mode==="template"?i:n,o=new Set;r.forEach(w=>{o.add(String(w.from)),o.add(String(w.to))});const l=a.filter(w=>o.has(String(w.id)));if(!l.length){e.innerHTML=`<div class="acc-empty">
                ${this._mode==="template"?"هیچ Template فعالی با pair تعریف‌شده یافت نشد.":"هیچ جریان تأییدشده‌ای یافت نشد. ابتدا سندها را تأیید کنید."}
            </div>`;return}const c=new Fn(l,r,t,s);c.run(200);const d={};c.nodes.forEach(w=>{d[w.id]=w});const h="http://www.w3.org/2000/svg",u=document.createElementNS(h,"svg");u.setAttribute("width",t),u.setAttribute("height",s),u.setAttribute("viewBox",`0 0 ${t} ${s}`),u.style.cssText="display:block;width:100%;height:100%;";const f=(w,_)=>{const k=document.createElementNS(h,w);return Object.entries(_).forEach(([R,H])=>k.setAttribute(R,H)),k},m=f("defs",{}),b=f("marker",{id:"arrowhead",markerWidth:"8",markerHeight:"6",refX:"8",refY:"3",orient:"auto"});b.appendChild(f("polygon",{points:"0 0, 8 3, 0 6",fill:"#94a3b8"})),m.appendChild(b),u.appendChild(m);const v=r.length?Math.max(...r.map(w=>parseFloat(w.total_amount??w.count??1))):1;r.forEach(w=>{const _=d[w.from],k=d[w.to];if(!_||!k)return;const R=26,H=k.x-_.x,q=k.y-_.y,P=Math.sqrt(H*H+q*q)||1,J=_.x+H/P*R,S=_.y+q/P*R,Dt=k.x-H/P*(R+8),$e=k.y-q/P*(R+8),vl=(J+Dt)/2-q/P*25,bl=(S+$e)/2+H/P*25,gl=this._mode==="flow"?Math.max(1,Math.round(parseFloat(w.total_amount)/v*5)):Math.max(1,Math.min(4,w.count??1)),ke=f("path",{d:`M${J},${S} Q${vl},${bl} ${Dt},${$e}`,stroke:"#94a3b8","stroke-width":gl,fill:"none","marker-end":"url(#arrowhead)",opacity:"0.75","stroke-dasharray":this._mode==="template"?"5 3":"none"});ke.style.cursor="pointer";const yl=this._mode==="flow"?`${(w.total_amount/1).toLocaleString("fa-IR")} | ${w.flow_count} تراکنش`:(w.labels??[]).filter((Ee,_l,xl)=>xl.indexOf(Ee)===_l).join(" / ");ke.addEventListener("mouseover",Ee=>this._showTip(Ee,yl)),ke.addEventListener("mousemove",Ee=>this._moveTip(Ee)),ke.addEventListener("mouseout",()=>this._hideTip()),u.appendChild(ke)}),c.nodes.forEach(w=>{var J;const _=f("g",{transform:`translate(${w.x},${w.y})`,cursor:"pointer"}),k=ls[w.type]||"#64748b",R=w.total_in+w.total_out>0;_.appendChild(f("circle",{r:R?28:22,fill:k,opacity:"0.18",stroke:k,"stroke-width":"2"})),_.appendChild(f("circle",{r:R?18:14,fill:k}));const H=f("text",{"text-anchor":"middle","dominant-baseline":"middle",fill:"#fff","font-size":"9","font-weight":"700"});H.textContent=w.code??"",_.appendChild(H);const q=f("text",{"text-anchor":"middle","dominant-baseline":"hanging",y:R?30:24,fill:"#1e293b","font-size":"10","font-weight":"600"});q.textContent=((J=w.name)==null?void 0:J.length)>14?w.name.slice(0,13)+"…":w.name??"",_.appendChild(q);const P=`${w.name} (${cs[w.type]??w.type})`+(R?`
ورودی: ${Number(w.total_in).toLocaleString("fa-IR")}
خروجی: ${Number(w.total_out).toLocaleString("fa-IR")}`:"");_.addEventListener("mouseover",S=>this._showTip(S,P)),_.addEventListener("mousemove",S=>this._moveTip(S)),_.addEventListener("mouseout",()=>this._hideTip()),u.appendChild(_)}),e.innerHTML="",e.appendChild(u);const y=r.length,$=c.nodes.length;this.ref("info").textContent=`${$} حساب | ${y} رابطه${this._mode==="flow"?" (تأییدشده)":" (Template)"}`}_showTip(e,t){this._tooltip||(this._tooltip=document.createElement("div"),this._tooltip.className="acc-graph-tooltip",document.body.appendChild(this._tooltip)),this._tooltip.style.display="block",this._tooltip.textContent=t,this._moveTip(e)}_moveTip(e){this._tooltip&&(this._tooltip.style.left=e.clientX+14+"px",this._tooltip.style.top=e.clientY-10+"px")}_hideTip(){this._tooltip&&(this._tooltip.style.display="none")}destroy(){this._hideTip(),this._tooltip&&(this._tooltip.remove(),this._tooltip=null),super.destroy()}}const rt=[{key:"coa",icon:"🗂",title:"سرفصل‌ها",desc:"مدیریت درخت حساب‌ها",Class:es},{key:"articles",icon:"🔗",title:"بانک آرتیکل",desc:"جفت‌های بدهکار/بستانکار",Class:ts},{key:"dimensions",icon:"🏷️",title:"ابعاد",desc:"تفصیلی: مشتری/پروژه/...",Class:ss},{key:"events",icon:"⚙️",title:"Template رویداد",desc:"نگاشت pair-based",Class:as},{key:"documents",icon:"📄",title:"صدور سند",desc:"ثبت و تأیید رویداد",Class:is},{key:"reports",icon:"📊",title:"گزارش مالی",desc:"تراز و دفتر کل",Class:rs},{key:"audit",icon:"🛡️",title:"حسابرسیِ پیوسته",desc:"کنترل‌های آنلاین",Class:os},{key:"graph",icon:"🕸",title:"گراف حسابداری",desc:"نمودار جریان حساب‌ها",Class:In}];class ds extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="coa",this._sections={}}async template(){const t=rt.map(a=>`
            <div class="acc-nav-card ${a.key===this._active?"acc-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0"
                 aria-label="${a.title}">
                <span class="acc-nav-card__icon">${a.icon}</span>
                <div class="acc-nav-card__title">${a.title}</div>
                <div class="acc-nav-card__desc">${a.desc}</div>
            </div>
        `).join(""),s=rt.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}">
            </div>
        `).join("");return`
            <div class="acc-nav" data-ref="navBar">${t}</div>
            <div class="acc-panels">${s}</div>
        `}async afterRender(){this._bindNav(),await this._mountSection(this._active)}_bindNav(){const t=this.ref("navBar");t&&t.querySelectorAll(".acc-nav-card").forEach(s=>{this.on(s,"click",()=>this._switchSection(s.dataset.section)),this.on(s,"keydown",a=>{(a.key==="Enter"||a.key===" ")&&this._switchSection(s.dataset.section)})})}async _switchSection(t){var a;if(t===this._active)return;const s=this.ref("navBar");s==null||s.querySelectorAll(".acc-nav-card").forEach(i=>{i.classList.toggle("acc-nav-card--active",i.dataset.section===t)}),(a=this.container)==null||a.querySelectorAll(".acc-section").forEach(i=>{i.classList.toggle("acc-section--active",i.dataset.panel===t)}),this._active=t,await this._mountSection(t)}async _mountSection(t){if(this._sections[t])return;const s=rt.find(n=>n.key===t);if(!s)return;const a=this.ref(`panel-${t}`);if(!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(ds,"title","حسابداری هوشمند"),E.register("accounting",ds);class de{static async open(e){let t=[],s=[];try{const[d,h]=await Promise.all([e.api.get("/ship/methods"),e.api.get("/ship/carriers")]);t=(d==null?void 0:d.data)??[],s=(h==null?void 0:h.data)??[]}catch{}const a=e.source==="sale",i=e.invoiceItems??[],n=t.map(d=>`<option value="${d.id}">${d.icon} ${this._esc(d.name)} (~${d.avg_days} روز)</option>`).join(""),r='<option value="">— انتخاب —</option>'+s.map(d=>`<option value="${d.id}">${this._esc(d.name)}</option>`).join(""),o=document.createElement("div");o.className="acc-modal-overlay",o.innerHTML=`
        <div class="acc-modal" style="max-width:680px;max-height:92vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🚚 ایجاد محموله ${a?"(فروش)":"(خرید)"}</div>

            <div style="background:#eff6ff;padding:10px;border-radius:6px;font-size:12px;color:#1e40af;margin-bottom:12px;">
                💡 هر آیتم می‌تواند روش حمل متفاوت داشته باشد. آیتم‌هایی که می‌خواهید در همین محموله باشند را تیک بزنید.
            </div>

            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>روش حمل *</label>
                        <select name="method_id" required>
                            <option value="">انتخاب...</option>${n}
                        </select>
                    </div>
                    <div class="acc-form-group"><label>شرکت حمل</label>
                        <select name="carrier_id">${r}</select>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تاریخ برنامه تحویل</label>
                        <input name="planned_delivery_date" type="date" value="${new Date(Date.now()+864e5*3).toISOString().split("T")[0]}">
                    </div>
                    <div class="acc-form-group"><label>کد رهگیری</label>
                        <input name="tracking_code" placeholder="(اختیاری)" dir="ltr">
                    </div>
                </div>
                ${a?`
                <div class="acc-form-group"><label>آدرس مقصد</label>
                    <textarea name="destination_address" rows="2" placeholder="آدرس مشتری..."></textarea>
                </div>`:""}
                <div class="acc-form-group"><label>یادداشت</label>
                    <input name="notes" placeholder="یادداشت محموله">
                </div>

                <h4 style="margin:14px 0 8px 0;font-size:13px;color:#475569;">📦 آیتم‌های محموله</h4>
                <table class="acc-table" style="font-size:12px;">
                    <thead><tr>
                        <th style="width:30px;"><input type="checkbox" data-ref-pk="checkAll" checked></th>
                        <th>محصول</th><th>تعداد فاکتور</th><th>تعداد در این محموله</th>
                    </tr></thead>
                    <tbody>
                    ${i.map(d=>`
                    <tr>
                        <td><input type="checkbox" name="item_${d.id}" value="1" checked></td>
                        <td>${de._esc(d.product_name??d.description??"—")}</td>
                        <td>${d.quantity} ${de._esc(d.unit??"")}</td>
                        <td><input type="number" name="qty_${d.id}" value="${d.quantity}" min="0" step="any" style="width:80px;"></td>
                    </tr>
                    `).join("")}
                    </tbody>
                </table>

                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">🚚 ایجاد محموله</button>
                </div>
            </form>
        </div>`,document.body.appendChild(o);const l=()=>o.remove();o.querySelector(".acc-modal__close").addEventListener("click",l),o.querySelector("[data-action=cancel]").addEventListener("click",l),o.addEventListener("click",d=>{d.target===o&&l()});const c=o.querySelector('[data-ref-pk="checkAll"]');c.addEventListener("change",()=>{o.querySelectorAll('input[name^="item_"]').forEach(d=>d.checked=c.checked)}),o.querySelector("form").addEventListener("submit",async d=>{var m;d.preventDefault();const h=new FormData(d.target),u={method_id:h.get("method_id"),carrier_id:h.get("carrier_id")||null,planned_delivery_date:h.get("planned_delivery_date"),tracking_code:h.get("tracking_code")??"",notes:h.get("notes")??"",items:[]};if(a&&(u.destination_address=h.get("destination_address")),i.forEach(b=>{h.get(`item_${b.id}`)&&u.items.push({ref_item_id:b.id,qty_planned:parseFloat(h.get(`qty_${b.id}`)??b.quantity)})}),!u.items.length){alert("حداقل یک آیتم انتخاب کنید");return}if(!u.method_id){alert("روش حمل را انتخاب کنید");return}const f=d.target.querySelector("[type=submit]");f.disabled=!0;try{const b=a?`/ship/from-sale/${e.invoiceId}`:`/ship/from-purchase/${e.invoiceId}`,v=await e.api.post(b,u);l(),(m=e.onCreated)==null||m.call(e,v==null?void 0:v.shipment_no),alert(`✅ محموله ${v==null?void 0:v.shipment_no} ایجاد شد`)}catch(b){alert("خطا: "+((b==null?void 0:b.message)??"")),f.disabled=!1}})}static _esc(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}}class Dn extends x{constructor(e={}){super(e),this._view="list",this._editInvoice=null,this._customers=[],this._products=[],this._warehouses=[],this._invoices=[],this._items=[],this._totals={},this._page=1,this._statusFilter=""}async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._loadLookups(),await this._showList()}async _loadLookups(){try{const[e,t,s]=await Promise.all([this.api.get("/sales/customers"),this.api.get("/sales/products"),this.api.get("/inv/warehouses").catch(()=>({data:[]}))]);this._customers=(e==null?void 0:e.data)??[],this._products=(t==null?void 0:t.data)??[],this._warehouses=(s==null?void 0:s.data)??[]}catch{}}async _showList(){this._view="list";const e=this.ref("root");e.innerHTML=`
            <div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--primary" data-ref="newBtn" data-perm="sales.invoices.create">➕ فاکتور جدید</button>
                <select class="event-type-filter" data-ref="statusSel" style="min-width:140px;">
                    <option value="">همه وضعیت‌ها</option>
                    <option value="draft">پیش‌نویس</option>
                    <option value="finalized">نهایی‌شده</option>
                    <option value="cancelled">لغوشده</option>
                </select>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
                <span style="margin-right:auto;font-size:12px;color:#94a3b8;" data-ref="countLbl"></span>
            </div>
            <div data-ref="listBody"></div>
            <div data-ref="pagination" style="display:flex;gap:8px;margin-top:14px;justify-content:center;"></div>
        `,this._bindRef(),this.on(this.ref("newBtn"),"click",()=>this._showForm(null)),this.on(this.ref("refreshBtn"),"click",()=>this._loadList()),this.on(this.ref("statusSel"),"change",t=>{this._statusFilter=t.target.value,this._page=1,this._loadList()}),await this._loadList()}_bindRef(){const e=this.ref("root");e&&e.querySelectorAll("[data-ref]").forEach(t=>{this.refs[t.dataset.ref]=t})}async _loadList(){const e=this.ref("listBody");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t={page:this._page,per_page:20};this._statusFilter&&(t.status=this._statusFilter);const s=await this.api.get("/sales/invoices",t);this._invoices=(s==null?void 0:s.data)??[];const a=(s==null?void 0:s.total)??this._invoices.length;this.ref("countLbl").textContent=`${a} فاکتور`,this._renderList(e),this._renderPagination(a,20)}catch{e.innerHTML='<div class="acc-error">خطا در دریافت فاکتورها</div>'}}_renderList(e){if(!this._invoices.length){e.innerHTML='<div class="acc-empty">فاکتوری یافت نشد.</div>';return}e.innerHTML="",this._invoices.forEach(t=>{const s=this._buildCard(t);e.appendChild(s)})}_buildCard(e){var i,n,r,o,l;const t={draft:"draft",finalized:"finalized",cancelled:"cancelled"}[e.status]??"draft",s={draft:"پیش‌نویس",finalized:"نهایی‌شده",cancelled:"لغوشده"}[e.status]??e.status,a=document.createElement("div");return a.className=`invoice-card invoice-card--${t}`,a.innerHTML=`
            <div style="flex:1;min-width:0;">
                <div class="invoice-card__no">${this.escape(e.invoice_no)}</div>
                <div class="invoice-card__party">${this.escape(e.customer_name||"—")}</div>
                <div class="invoice-card__date">
                    📅 ${e.invoice_date}
                    <span class="status-badge status-badge--${t==="finalized"?"confirmed":t==="cancelled"?"cancelled":"draft"}"
                          style="margin-right:8px;">${s}</span>
                    ${e.acc_event_id?`<span class="acc-link-badge">🔗 رویداد #${e.acc_event_id}</span>`:""}
                </div>
            </div>
            <div style="text-align:left;">
                <div class="invoice-card__amount">${this._fmt(e.total_amount)} ﷼</div>
                <div class="invoice-card__actions" style="margin-top:8px;">
                    ${e.status==="draft"?`
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit">ویرایش</button>
                        <button class="acc-btn acc-btn--primary   acc-btn--sm" data-action="finalize">✅ نهایی‌سازی</button>
                        <button class="acc-btn acc-btn--danger    acc-btn--sm" data-action="delete">حذف</button>
                    `:""}
                    ${e.status==="finalized"?`
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="view">مشاهده</button>
                        <button class="acc-btn acc-btn--sm" data-action="ship" style="background:#dbeafe;color:#1e40af;">🚚 ارسال به مشتری</button>
                    `:""}
                </div>
            </div>
        `,(i=a.querySelector("[data-action='edit']"))==null||i.addEventListener("click",c=>{c.stopPropagation(),this._showForm(e)}),(n=a.querySelector("[data-action='finalize']"))==null||n.addEventListener("click",c=>{c.stopPropagation(),this._finalize(e.id)}),(r=a.querySelector("[data-action='delete']"))==null||r.addEventListener("click",c=>{c.stopPropagation(),this._delete(e.id)}),(o=a.querySelector("[data-action='view']"))==null||o.addEventListener("click",c=>{c.stopPropagation(),this._showForm(e,!0)}),(l=a.querySelector("[data-action='ship']"))==null||l.addEventListener("click",async c=>{var h;c.stopPropagation();const d=await this.api.get(`/sales/invoices/${e.id}`);de.open({api:this.api,source:"sale",invoiceId:e.id,invoiceItems:((h=d==null?void 0:d.data)==null?void 0:h.items)??[]})}),a}_renderPagination(e,t){const s=this.ref("pagination"),a=Math.ceil(e/t);if(!s||a<=1){s&&(s.innerHTML="");return}s.innerHTML="";for(let i=1;i<=a;i++){const n=document.createElement("button");n.className=`acc-btn acc-btn--sm ${i===this._page?"acc-btn--primary":"acc-btn--secondary"}`,n.textContent=i,n.addEventListener("click",()=>{this._page=i,this._loadList()}),s.appendChild(n)}}async _showForm(e=null,t=!1){var n;this._view="form",this._editInvoice=e,this._items=[];const s=this.ref("root"),a='<option value="">— انتخاب مشتری —</option>'+this._customers.map(r=>`<option value="${r.id}">${this.escape(r.name)}</option>`).join(""),i='<option value="">— انتخاب انبار خروج —</option>'+this._warehouses.map(r=>`<option value="${r.id}">${this.escape(r.name)}</option>`).join("");if(s.innerHTML=`
            <div class="inv-page">
                <!-- Header -->
                <div class="inv-header inv-header--sales">
                    <div class="acc-form-group" style="margin:0">
                        <label>مشتری</label>
                        <select data-ref="fCustomer" ${t?"disabled":""}>
                            ${a}
                        </select>
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label>🏭 انبار خروج کالا</label>
                        <select data-ref="fWarehouse" ${t?"disabled":""}>
                            ${i}
                        </select>
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label>تاریخ فاکتور</label>
                        <input type="date" data-ref="fDate" value="${(e==null?void 0:e.invoice_date)||this._today()}" ${t?"readonly":""}>
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label>تاریخ سررسید</label>
                        <input type="date" data-ref="fDue" value="${(e==null?void 0:e.due_date)||""}" ${t?"readonly":""}>
                    </div>
                    <div class="acc-form-group" style="margin:0;grid-column:1/-1;">
                        <label>شرح کلی</label>
                        <input type="text" data-ref="fDesc" value="${this.escape((e==null?void 0:e.description)||"")}" ${t?"readonly":""}>
                    </div>
                </div>

                <!-- Items -->
                <div class="inv-items-wrapper">
                    <div class="inv-items-title">
                        📋 ردیف‌های فاکتور
                        ${t?"":'<button type="button" class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="addItemBtn">+ ردیف</button>'}
                    </div>
                    <table class="inv-items-table">
                        <thead>
                            <tr>
                                <th style="width:28px">#</th>
                                <th style="min-width:160px">محصول/خدمت</th>
                                <th style="min-width:130px">شرح</th>
                                <th style="width:70px">تعداد</th>
                                <th style="width:110px">قیمت واحد</th>
                                <th style="width:60px">تخفیف%</th>
                                <th style="width:60px">مالیات%</th>
                                <th style="width:110px">جمع ردیف</th>
                                ${t?"":"<th style='width:30px'></th>"}
                            </tr>
                        </thead>
                        <tbody data-ref="itemsBody"></tbody>
                    </table>
                </div>

                <!-- Totals -->
                <div class="inv-totals">
                    <table class="inv-totals-table">
                        <tr><td>جمع کل قبل از تخفیف</td><td data-ref="tSubtotal">0</td></tr>
                        <tr><td>تخفیف</td><td data-ref="tDiscount" style="color:#dc2626;">0</td></tr>
                        <tr><td>مبلغ خالص</td><td data-ref="tNet">0</td></tr>
                        <tr><td>مالیات ارزش افزوده</td><td data-ref="tVat">0</td></tr>
                        <tr class="inv-total-main"><td>مبلغ قابل پرداخت</td><td data-ref="tTotal">0</td></tr>
                    </table>
                </div>

                <!-- Actions -->
                ${t?`
                <div class="inv-actions">
                    <button class="acc-btn acc-btn--secondary" data-ref="backBtn">← بازگشت</button>
                </div>
                `:`
                <div class="inv-actions">
                    <button class="acc-btn acc-btn--secondary" data-ref="backBtn">← بازگشت</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="saveDraftBtn" data-perm="sales.invoices.create">💾 ذخیره پیش‌نویس</button>
                    <button class="acc-btn acc-btn--primary"   data-ref="finalizeBtn"  data-perm="sales.invoices.finalize">
                        ✅ نهایی‌سازی + ثبت حسابداری
                    </button>
                    <span data-ref="formSpinner" style="display:none;" class="acc-loading" style="padding:0;gap:6px;">
                        <span class="acc-spinner"></span>
                    </span>
                </div>
                `}
            </div>
        `,this._bindRef(),this.on(this.ref("backBtn"),"click",()=>this._showList()),t||(this.on(this.ref("addItemBtn"),"click",()=>this._addItemRow()),this.on(this.ref("saveDraftBtn"),"click",()=>this._saveInvoice("draft")),this.on(this.ref("finalizeBtn"),"click",()=>this._saveAndFinalize())),e!=null&&e.customer_id&&(this.ref("fCustomer").value=e.customer_id),e!=null&&e.warehouse_id&&(this.ref("fWarehouse").value=e.warehouse_id),e!=null&&e.id)try{const r=await this.api.get(`/sales/invoices/${e.id}`);(((n=r==null?void 0:r.data)==null?void 0:n.items)??[]).forEach(l=>this._addItemRow(l))}catch{}!this._items.length&&!t&&this._addItemRow(),this._updateTotals()}_addItemRow(e={}){const t=this.ref("itemsBody"),s=t.querySelectorAll("tr").length,a='<option value="">— انتخاب —</option>'+this._products.map(n=>`<option value="${n.id}" data-price="${n.sale_price||n.unit_price||0}" data-vat="${n.vat_rate||9}">${this.escape(n.name)}</option>`).join(""),i=document.createElement("tr");i.innerHTML=`
            <td style="text-align:center;color:#94a3b8;font-size:12px;" class="row-num">${s+1}</td>
            <td><select class="item-product">${a}</select></td>
            <td><input class="item-desc" type="text" value="${this.escape(e.description||"")}" placeholder="شرح ردیف"></td>
            <td><input class="item-qty" type="number" value="${e.quantity||1}" min="0.001" step="any"></td>
            <td><input class="item-price" type="number" value="${e.unit_price||0}" min="0" step="any"></td>
            <td><input class="item-disc" type="number" value="${e.discount_pct||0}" min="0" max="100" step="0.1"></td>
            <td><input class="item-vat" type="number" value="${e.vat_rate||9}" min="0" max="100" step="0.1"></td>
            <td class="inv-line-total">0</td>
            <td><button type="button" class="acc-btn acc-btn--danger acc-btn--sm" style="padding:3px 8px;">×</button></td>
        `,e.product_id&&(i.querySelector(".item-product").value=e.product_id),i.querySelector(".item-product").addEventListener("change",n=>{const r=n.target.selectedOptions[0];r!=null&&r.dataset.price&&(i.querySelector(".item-price").value=r.dataset.price),r!=null&&r.dataset.vat&&(i.querySelector(".item-vat").value=r.dataset.vat),!i.querySelector(".item-desc").value&&(r!=null&&r.textContent)&&(i.querySelector(".item-desc").value=r.textContent.trim()),this._calcRow(i),this._updateTotals()}),i.querySelectorAll("input").forEach(n=>{n.addEventListener("input",()=>{this._calcRow(i),this._updateTotals()})}),i.querySelector("button").addEventListener("click",()=>{i.remove(),this._renumberRows(),this._updateTotals()}),t.appendChild(i),this._calcRow(i),this._updateTotals()}_calcRow(e){var d,h,u,f;const t=parseFloat((d=e.querySelector(".item-qty"))==null?void 0:d.value)||0,s=parseFloat((h=e.querySelector(".item-price"))==null?void 0:h.value)||0,a=parseFloat((u=e.querySelector(".item-disc"))==null?void 0:u.value)||0,i=parseFloat((f=e.querySelector(".item-vat"))==null?void 0:f.value)||0,n=t*s,r=n*(a/100),o=n-r,l=o*(i/100),c=o+l;return e.querySelector(".inv-line-total").textContent=this._fmt(c),{base:n,dAmt:r,net:o,vatAmt:l,total:c}}_renumberRows(){var e;(e=this.ref("itemsBody"))==null||e.querySelectorAll("tr").forEach((t,s)=>{const a=t.querySelector(".row-num");a&&(a.textContent=s+1)})}_updateTotals(){var i;let e=0,t=0,s=0,a=0;(i=this.ref("itemsBody"))==null||i.querySelectorAll("tr").forEach(n=>{const r=this._calcRow(n);e+=r.base,t+=r.dAmt,s+=r.net,a+=r.vatAmt}),this._totals={subtotal:e,discount_amount:t,net_amount:s,vat_amount:a,total_amount:s+a},this._setRef("tSubtotal",this._fmt(e)),this._setRef("tDiscount",this._fmt(t)),this._setRef("tNet",this._fmt(s)),this._setRef("tVat",this._fmt(a)),this._setRef("tTotal",this._fmt(s+a))}_setRef(e,t){const s=this.ref(e);s&&(s.textContent=t)}_collectItems(){var t;const e=[];return(t=this.ref("itemsBody"))==null||t.querySelectorAll("tr").forEach(s=>{var a,i,n,r,o,l;e.push({product_id:((a=s.querySelector(".item-product"))==null?void 0:a.value)||null,description:((i=s.querySelector(".item-desc"))==null?void 0:i.value)||"",quantity:parseFloat((n=s.querySelector(".item-qty"))==null?void 0:n.value)||0,unit_price:parseFloat((r=s.querySelector(".item-price"))==null?void 0:r.value)||0,discount_pct:parseFloat((o=s.querySelector(".item-disc"))==null?void 0:o.value)||0,vat_rate:parseFloat((l=s.querySelector(".item-vat"))==null?void 0:l.value)||9})}),e.filter(s=>s.quantity>0)}_buildPayload(){var e,t,s,a,i;return{customer_id:((e=this.ref("fCustomer"))==null?void 0:e.value)||null,warehouse_id:((t=this.ref("fWarehouse"))==null?void 0:t.value)||null,invoice_date:((s=this.ref("fDate"))==null?void 0:s.value)||this._today(),due_date:((a=this.ref("fDue"))==null?void 0:a.value)||null,description:((i=this.ref("fDesc"))==null?void 0:i.value)||"",items:this._collectItems()}}async _saveInvoice(e="draft"){var a;if(!this._collectItems().length)return alert("حداقل یک ردیف وارد کنید."),null;const s=this._buildPayload();this._setFormBusy(!0);try{let i;return(a=this._editInvoice)!=null&&a.id?(i=await this.api.put(`/sales/invoices/${this._editInvoice.id}`,s),this._editInvoice.id):(i=await this.api.post("/sales/invoices",s),this._editInvoice={id:i==null?void 0:i.id},i==null?void 0:i.id)}catch(i){return alert("خطا: "+((i==null?void 0:i.message)??"")),null}finally{this._setFormBusy(!1)}}async _saveAndFinalize(){const e=await this._saveInvoice("draft");e&&await this._finalize(e)}async _finalize(e){this._setFormBusy(!0);try{const t=await this.api.post(`/sales/invoices/${e}/finalize`,{});t!=null&&t.success?(this._toast(`✅ فاکتور نهایی شد — رویداد حسابداری #${t.event_id} ثبت گردید`),await this._showList()):alert("خطا: "+((t==null?void 0:t.message)??""))}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}finally{this._setFormBusy(!1)}}async _delete(e){if(confirm("حذف این فاکتور؟"))try{await this.api.delete(`/sales/invoices/${e}`),await this._loadList()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}_setFormBusy(e){const t=this.ref("formSpinner"),s=this.ref("saveDraftBtn"),a=this.ref("finalizeBtn");t&&(t.style.display=e?"flex":"none"),s&&(s.disabled=e),a&&(a.disabled=e)}_today(){return new Date().toISOString().slice(0,10)}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}_toast(e){const t=document.createElement("div");t.style.cssText="position:fixed;bottom:24px;right:24px;background:#059669;color:#fff;padding:13px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;box-shadow:0 4px 20px rgba(0,0,0,.15);max-width:360px;",t.textContent=e,document.body.appendChild(t),setTimeout(()=>t.remove(),4e3)}}let Pn=class extends x{constructor(e={}){super(e),this._customers=[]}async template(){return`
            <div style="display:flex;gap:10px;margin-bottom:14px;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">+ مشتری جدید</button>
                <input type="text" data-ref="searchIn" placeholder="جستجو..." style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;min-width:200px;">
            </div>
            <div class="entity-grid" data-ref="grid"></div>
        `}async afterRender(){this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),this.on(this.ref("searchIn"),"input",e=>this._load(e.target.value)),await this._load()}async _load(e=""){const t=this.ref("grid");t.innerHTML='<div class="acc-loading" style="grid-column:1/-1"><div class="acc-spinner"></div></div>';try{const s=await this.api.get("/sales/customers",e?{search:e}:{});this._customers=(s==null?void 0:s.data)??[],this._render(t)}catch{t.innerHTML='<div class="acc-error" style="grid-column:1/-1">خطا</div>'}}_render(e){if(!this._customers.length){e.innerHTML='<div class="acc-empty" style="grid-column:1/-1">مشتری‌ای یافت نشد.</div>';return}e.innerHTML="",this._customers.forEach(t=>{const s=document.createElement("div");s.className="entity-card",s.innerHTML=`
                <div class="entity-card__code">${this.escape(t.code||"")}</div>
                <div class="entity-card__name">${this.escape(t.name)}</div>
                <div class="entity-card__meta">
                    ${t.phone?`📞 ${this.escape(t.phone)}<br>`:""}
                    ${t.tax_id?`🪪 ${this.escape(t.tax_id)}<br>`:""}
                    ${t.credit_limit>0?`💳 سقف اعتبار: ${new Intl.NumberFormat("fa-IR").format(t.credit_limit)}`:""}
                </div>
                <div class="entity-card__actions">
                    <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit">ویرایش</button>
                    <button class="acc-btn acc-btn--sm" data-action="loc" style="background:#dbeafe;color:#1e40af;">📍 موقعیت</button>
                    <button class="acc-btn acc-btn--danger    acc-btn--sm" data-action="del">حذف</button>
                </div>
            `,s.querySelector("[data-action='edit']").addEventListener("click",()=>this._openForm(t)),s.querySelector("[data-action='del']").addEventListener("click",()=>this._delete(t)),s.querySelector("[data-action='loc']").addEventListener("click",()=>z.openModal({api:this.api,entityType:"customer",entityId:t.id,entityName:t.name})),e.appendChild(s)})}_openForm(e=null){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
            <div class="acc-modal">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${e?"ویرایش مشتری":"مشتری جدید"}</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>کد</label><input name="code" value="${this.escape((e==null?void 0:e.code)||"")}"></div>
                        <div class="acc-form-group"><label>نام *</label><input name="name" value="${this.escape((e==null?void 0:e.name)||"")}" required></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>تلفن</label><input name="phone" value="${this.escape((e==null?void 0:e.phone)||"")}"></div>
                        <div class="acc-form-group"><label>ایمیل</label><input name="email" type="email" value="${this.escape((e==null?void 0:e.email)||"")}"></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>شناسه مالیاتی</label><input name="tax_id" value="${this.escape((e==null?void 0:e.tax_id)||"")}"></div>
                        <div class="acc-form-group"><label>سقف اعتبار (ریال)</label><input name="credit_limit" type="number" value="${(e==null?void 0:e.credit_limit)||0}"></div>
                    </div>
                    <div class="acc-form-group"><label>آدرس</label><textarea name="address" rows="2">${this.escape((e==null?void 0:e.address)||"")}</textarea></div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${e?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector("[data-action='cancel']").addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=new FormData(a.target),n=Object.fromEntries(i.entries());try{e?await this.api.put(`/sales/customers/${e.id}`,n):await this.api.post("/sales/customers",n),s(),await this._load()}catch(r){alert("خطا: "+((r==null?void 0:r.message)??""))}})}async _delete(e){if(confirm(`حذف مشتری «${e.name}»؟`))try{await this.api.delete(`/sales/customers/${e.id}`),await this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}};const ot=[{value:"product",label:"کالا"},{value:"service",label:"خدمات"},{value:"other",label:"سایر"}];class ps extends x{constructor(e={}){super(e),this._products=[],this._invProducts=[]}async template(){return`
            <div style="display:flex;gap:10px;margin-bottom:14px;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">+ محصول / خدمت جدید</button>
                <input type="text" data-ref="searchIn" placeholder="جستجو..." style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;min-width:200px;">
                <select data-ref="typeFilter" style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;">
                    <option value="">همه نوع‌ها</option>
                    ${ot.map(e=>`<option value="${e.value}">${e.label}</option>`).join("")}
                </select>
            </div>
            <div class="entity-grid" data-ref="grid"></div>
        `}async afterRender(){this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),this.on(this.ref("searchIn"),"input",()=>this._load()),this.on(this.ref("typeFilter"),"change",()=>this._load()),await this._loadInvProducts(),await this._load()}async _loadInvProducts(){try{const e=await this.api.get("/inv/products");this._invProducts=(e==null?void 0:e.data)??[]}catch{this._invProducts=[]}}async _load(){const e=this.ref("grid"),t=this.ref("searchIn").value.trim(),s=this.ref("typeFilter").value;e.innerHTML='<div class="acc-loading" style="grid-column:1/-1"><div class="acc-spinner"></div></div>';try{const a={};t&&(a.search=t),s&&(a.type=s);const i=await this.api.get("/sales/products",a);this._products=(i==null?void 0:i.data)??[],this._render(e)}catch{e.innerHTML='<div class="acc-error" style="grid-column:1/-1">خطا در بارگذاری</div>'}}_render(e){if(!this._products.length){e.innerHTML='<div class="acc-empty" style="grid-column:1/-1">محصولی یافت نشد.</div>';return}e.innerHTML="",this._products.forEach(t=>{var i;const s=((i=ot.find(n=>n.value===t.type))==null?void 0:i.label)??t.type??"",a=document.createElement("div");a.className="entity-card",a.innerHTML=`
                <div class="entity-card__code">${this.escape(t.sku||t.code||"")}</div>
                <div class="entity-card__name">${this.escape(t.name)}</div>
                <div class="entity-card__meta">
                    <span style="display:inline-block;background:#eff6ff;color:#2563eb;border-radius:6px;padding:1px 7px;font-size:11px;font-weight:600;margin-bottom:4px;">${this.escape(s)}</span><br>
                    ${t.sale_price?`💰 فروش: ${new Intl.NumberFormat("fa-IR").format(t.sale_price)}<br>`:""}
                    ${t.cost_price?`📥 خرید: ${new Intl.NumberFormat("fa-IR").format(t.cost_price)}<br>`:""}
                    ${t.vat_rate?`🧾 مالیات: ${t.vat_rate}%<br>`:""}
                    ${t.stock_qty!=null?`📦 موجودی: ${t.stock_qty}<br>`:""}
                    ${t.inv_product_id?'🔗 <span style="color:#10b981;font-weight:600;">متصل به انبار</span>':'<span style="color:#94a3b8;">بدون اتصال انبار</span>'}
                </div>
                <div class="entity-card__actions">
                    <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit">ویرایش</button>
                    <button class="acc-btn acc-btn--danger    acc-btn--sm" data-action="del">حذف</button>
                </div>
            `,a.querySelector("[data-action='edit']").addEventListener("click",()=>this._openForm(t)),a.querySelector("[data-action='del']").addEventListener("click",()=>this._delete(t)),e.appendChild(a)})}_openForm(e=null){const t=ot.map(i=>`<option value="${i.value}" ${(e==null?void 0:e.type)===i.value?"selected":""}>${i.label}</option>`).join(""),s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
            <div class="acc-modal" style="max-width:540px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${e?"ویرایش محصول":"محصول / خدمت جدید"}</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>کد / SKU</label><input name="sku" value="${this.escape((e==null?void 0:e.sku)||"")}"></div>
                        <div class="acc-form-group"><label>نام *</label><input name="name" value="${this.escape((e==null?void 0:e.name)||"")}" required></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>نوع</label>
                            <select name="type">${t}</select>
                        </div>
                        <div class="acc-form-group"><label>واحد</label><input name="unit" value="${this.escape((e==null?void 0:e.unit)||"")}"></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>قیمت فروش (ریال)</label><input name="sale_price" type="number" step="1" value="${(e==null?void 0:e.sale_price)||0}"></div>
                        <div class="acc-form-group"><label>قیمت خرید (ریال)</label><input name="cost_price" type="number" step="1" value="${(e==null?void 0:e.cost_price)||0}"></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>نرخ مالیات (%)</label><input name="vat_rate" type="number" step="0.01" min="0" max="100" value="${(e==null?void 0:e.vat_rate)||0}"></div>
                        <div class="acc-form-group"><label>موجودی اولیه</label><input name="stock_qty" type="number" step="1" value="${(e==null?void 0:e.stock_qty)??0}"></div>
                    </div>
                    <div class="acc-form-group">
                        <label>🏭 اتصال به محصول انبار (برای ثبت خودکار حرکت)</label>
                        <select name="inv_product_id">
                            <option value="">— بدون اتصال (فقط حسابداری) —</option>
                            ${this._invProducts.map(i=>`<option value="${i.id}" ${(e==null?void 0:e.inv_product_id)==i.id?"selected":""}>${this.escape(i.code)} — ${this.escape(i.name)}</option>`).join("")}
                        </select>
                        <small style="color:#94a3b8;font-size:11px;">اگر متصل شود، با نهایی‌شدن فاکتور خودکار سند انبار صادر می‌شود</small>
                    </div>
                    <div class="acc-form-group"><label>توضیحات</label><textarea name="description" rows="2">${this.escape((e==null?void 0:e.description)||"")}</textarea></div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${e?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action='cancel']").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=new FormData(i.target),r=Object.fromEntries(n.entries()),o=i.target.querySelector("[type='submit']");o.disabled=!0,o.textContent="در حال ذخیره...";try{e?await this.api.put(`/sales/products/${e.id}`,r):await this.api.post("/sales/products",r),a(),await this._load()}catch(l){alert("خطا: "+((l==null?void 0:l.message)??"")),o.disabled=!1,o.textContent=e?"ذخیره":"افزودن"}})}async _delete(e){if(confirm(`حذف «${e.name}»؟`))try{await this.api.delete(`/sales/products/${e.id}`),await this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}}const lt=[{key:"invoices",icon:"🧾",title:"فاکتورها",desc:"صدور و پیگیری",Class:Dn},{key:"customers",icon:"👥",title:"مشتریان",desc:"مدیریت مشتریان",Class:Pn},{key:"products",icon:"📦",title:"محصولات",desc:"کالا و خدمات",Class:ps}];class hs extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="invoices",this._sections={}}async template(){const t=lt.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
            </div>
        `).join(""),s=lt.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=lt.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(hs,"title","فروش"),E.register("sales",hs);class On extends x{constructor(e={}){super(e),this._view="list",this._editInvoice=null,this._suppliers=[],this._products=[],this._projects=[],this._warehouses=[],this._invoices=[],this._totals={},this._page=1,this._statusFilter=""}async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._loadLookups(),await this._showList()}async _loadLookups(){try{const[e,t,s,a]=await Promise.all([this.api.get("/purchase/suppliers"),this.api.get("/sales/products"),this.api.get("/pc/projects",{per_page:200}).catch(()=>null),this.api.get("/inv/warehouses").catch(()=>({data:[]}))]);this._suppliers=(e==null?void 0:e.data)??[],this._products=(t==null?void 0:t.data)??[],this._projects=(s==null?void 0:s.data)??[],this._warehouses=(a==null?void 0:a.data)??[]}catch{}}async _showList(){this._view="list";const e=this.ref("root");e.innerHTML=`
            <div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--primary" data-ref="newBtn">➕ فاکتور خرید جدید</button>
                <select class="event-type-filter" data-ref="statusSel" style="min-width:140px;">
                    <option value="">همه وضعیت‌ها</option>
                    <option value="draft">پیش‌نویس</option>
                    <option value="finalized">نهایی‌شده</option>
                    <option value="cancelled">لغوشده</option>
                </select>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
                <span style="margin-right:auto;font-size:12px;color:#94a3b8;" data-ref="countLbl"></span>
            </div>
            <div data-ref="listBody"></div>
            <div data-ref="pagination" style="display:flex;gap:8px;margin-top:14px;justify-content:center;"></div>
        `,this._bindRef(),this.on(this.ref("newBtn"),"click",()=>this._showForm(null)),this.on(this.ref("refreshBtn"),"click",()=>this._loadList()),this.on(this.ref("statusSel"),"change",t=>{this._statusFilter=t.target.value,this._page=1,this._loadList()}),await this._loadList()}_bindRef(){const e=this.ref("root");e&&e.querySelectorAll("[data-ref]").forEach(t=>{this.refs[t.dataset.ref]=t})}async _loadList(){const e=this.ref("listBody");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t={page:this._page,per_page:20};this._statusFilter&&(t.status=this._statusFilter);const s=await this.api.get("/purchase/invoices",t);this._invoices=(s==null?void 0:s.data)??[];const a=(s==null?void 0:s.total)??this._invoices.length;this.ref("countLbl").textContent=`${a} فاکتور خرید`,this._renderList(e),this._renderPagination(a,20)}catch{e.innerHTML='<div class="acc-error">خطا در دریافت فاکتورها</div>'}}_renderList(e){if(!this._invoices.length){e.innerHTML='<div class="acc-empty">فاکتور خریدی یافت نشد.</div>';return}e.innerHTML="",this._invoices.forEach(t=>{const s=this._buildCard(t);e.appendChild(s)})}_buildCard(e){var i,n,r,o,l;const t={draft:"draft",finalized:"finalized",cancelled:"cancelled"}[e.status]??"draft",s={draft:"پیش‌نویس",finalized:"نهایی‌شده",cancelled:"لغوشده"}[e.status]??e.status,a=document.createElement("div");return a.className=`invoice-card invoice-card--${t}`,a.style.borderRight=e.status==="finalized"?"4px solid #7c3aed":"",a.innerHTML=`
            <div style="flex:1;min-width:0;">
                <div class="invoice-card__no">${this.escape(e.invoice_no)}</div>
                <div class="invoice-card__party">${this.escape(e.supplier_name||"—")}</div>
                <div class="invoice-card__date">
                    📅 ${e.invoice_date}
                    <span class="status-badge status-badge--${t==="finalized"?"confirmed":t==="cancelled"?"cancelled":"draft"}"
                          style="margin-right:8px;">${s}</span>
                    ${e.acc_event_id?`<span class="acc-link-badge">🔗 رویداد #${e.acc_event_id}</span>`:""}
                </div>
                ${e.ref_number?`<div style="font-size:11px;color:#94a3b8;margin-top:2px;">شماره فاکتور تأمین‌کننده: ${this.escape(e.ref_number)}</div>`:""}
                ${e.project_name?`<div style="font-size:11px;color:#4f46e5;margin-top:2px;">🏗 پروژه: ${this.escape(e.project_name)}</div>`:""}
            </div>
            <div style="text-align:left;">
                <div class="invoice-card__amount">${this._fmt(e.total_amount)} ﷼</div>
                <div class="invoice-card__actions" style="margin-top:8px;">
                    ${e.status==="draft"?`
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit">ویرایش</button>
                        <button class="acc-btn acc-btn--primary   acc-btn--sm" data-action="finalize">✅ نهایی‌سازی</button>
                        <button class="acc-btn acc-btn--danger    acc-btn--sm" data-action="delete">حذف</button>
                    `:""}
                    ${e.status==="finalized"?`
                        <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="view">مشاهده</button>
                        <button class="acc-btn acc-btn--sm" data-action="ship" style="background:#dbeafe;color:#1e40af;">🚚 ایجاد محموله</button>
                    `:""}
                </div>
            </div>
        `,(i=a.querySelector("[data-action='edit']"))==null||i.addEventListener("click",c=>{c.stopPropagation(),this._showForm(e)}),(n=a.querySelector("[data-action='finalize']"))==null||n.addEventListener("click",c=>{c.stopPropagation(),this._finalize(e.id)}),(r=a.querySelector("[data-action='delete']"))==null||r.addEventListener("click",c=>{c.stopPropagation(),this._delete(e.id)}),(o=a.querySelector("[data-action='view']"))==null||o.addEventListener("click",c=>{c.stopPropagation(),this._showForm(e,!0)}),(l=a.querySelector("[data-action='ship']"))==null||l.addEventListener("click",async c=>{var h;c.stopPropagation();const d=await this.api.get(`/purchase/invoices/${e.id}`);de.open({api:this.api,source:"purchase",invoiceId:e.id,invoiceItems:((h=d==null?void 0:d.data)==null?void 0:h.items)??[]})}),a}_renderPagination(e,t){const s=this.ref("pagination"),a=Math.ceil(e/t);if(!s||a<=1){s&&(s.innerHTML="");return}s.innerHTML="";for(let i=1;i<=a;i++){const n=document.createElement("button");n.className=`acc-btn acc-btn--sm ${i===this._page?"acc-btn--primary":"acc-btn--secondary"}`,n.textContent=i,n.addEventListener("click",()=>{this._page=i,this._loadList()}),s.appendChild(n)}}async _showForm(e=null,t=!1){var n;this._view="form",this._editInvoice=e;const s=this.ref("root"),a='<option value="">— انتخاب تأمین‌کننده —</option>'+this._suppliers.map(r=>`<option value="${r.id}">${this.escape(r.name)}</option>`).join(""),i='<option value="">— انتخاب انبار ورود —</option>'+this._warehouses.map(r=>`<option value="${r.id}">${this.escape(r.name)}</option>`).join("");if(s.innerHTML=`
            <div class="inv-page">
                <!-- Header -->
                <div class="inv-header inv-header--purchase">
                    <div class="acc-form-group" style="margin:0">
                        <label>تأمین‌کننده</label>
                        <select data-ref="fSupplier" ${t?"disabled":""}>
                            ${a}
                        </select>
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label>🏭 انبار ورود کالا</label>
                        <select data-ref="fWarehouse" ${t?"disabled":""}>
                            ${i}
                        </select>
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label>تاریخ فاکتور</label>
                        <input type="date" data-ref="fDate" value="${(e==null?void 0:e.invoice_date)||this._today()}" ${t?"readonly":""}>
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label>تاریخ سررسید</label>
                        <input type="date" data-ref="fDue" value="${(e==null?void 0:e.due_date)||""}" ${t?"readonly":""}>
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label>شماره فاکتور تأمین‌کننده</label>
                        <input type="text" data-ref="fRef" value="${this.escape((e==null?void 0:e.ref_number)||"")}" ${t?"readonly":""} placeholder="اختیاری">
                    </div>
                    <div class="acc-form-group" style="margin:0">
                        <label>سررسید پرداخت (روز)</label>
                        <input type="number" data-ref="fPayTerm" value="${(e==null?void 0:e.payment_terms)||30}" min="0" ${t?"readonly":""}>
                    </div>
                    <div class="acc-form-group" style="margin:0;grid-column:1/-1;">
                        <label>شرح کلی</label>
                        <input type="text" data-ref="fDesc" value="${this.escape((e==null?void 0:e.description)||"")}" ${t?"readonly":""}>
                    </div>
                    ${this._projects.length?`
                    <div class="acc-form-group" style="margin:0;">
                        <label>پروژه (اختیاری)</label>
                        <select data-ref="fProject" ${t?"disabled":""}>
                            <option value="">— بدون پروژه —</option>
                            ${this._projects.map(r=>`<option value="${r.id}" ${(e==null?void 0:e.project_id)==r.id?"selected":""}>${this.escape(r.name)}</option>`).join("")}
                        </select>
                    </div>`:""}
                </div>

                <!-- Items -->
                <div class="inv-items-wrapper">
                    <div class="inv-items-title">
                        📋 ردیف‌های فاکتور خرید
                        ${t?"":'<button type="button" class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="addItemBtn">+ ردیف</button>'}
                    </div>
                    <table class="inv-items-table">
                        <thead>
                            <tr>
                                <th style="width:28px">#</th>
                                <th style="min-width:160px">محصول/خدمت</th>
                                <th style="min-width:130px">شرح</th>
                                <th style="width:70px">تعداد</th>
                                <th style="width:110px">قیمت خرید</th>
                                <th style="width:60px">تخفیف%</th>
                                <th style="width:60px">مالیات%</th>
                                <th style="width:110px">جمع ردیف</th>
                                ${t?"":"<th style='width:30px'></th>"}
                            </tr>
                        </thead>
                        <tbody data-ref="itemsBody"></tbody>
                    </table>
                </div>

                <!-- Totals -->
                <div class="inv-totals">
                    <table class="inv-totals-table">
                        <tr><td>جمع کل قبل از تخفیف</td><td data-ref="tSubtotal">0</td></tr>
                        <tr><td>تخفیف</td><td data-ref="tDiscount" style="color:#dc2626;">0</td></tr>
                        <tr><td>مبلغ خالص</td><td data-ref="tNet">0</td></tr>
                        <tr><td>مالیات ارزش افزوده</td><td data-ref="tVat">0</td></tr>
                        <tr class="inv-total-main"><td>مبلغ قابل پرداخت</td>
                            <td data-ref="tTotal" style="color:#7c3aed !important;">0</td>
                        </tr>
                    </table>
                </div>

                <!-- Actions -->
                ${t?`
                <div class="inv-actions">
                    <button class="acc-btn acc-btn--secondary" data-ref="backBtn">← بازگشت</button>
                </div>
                `:`
                <div class="inv-actions">
                    <button class="acc-btn acc-btn--secondary" data-ref="backBtn">← بازگشت</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="saveDraftBtn">💾 ذخیره پیش‌نویس</button>
                    <button class="acc-btn acc-btn--primary"   data-ref="finalizeBtn"
                            style="background:#7c3aed;border-color:#7c3aed;">
                        ✅ نهایی‌سازی + ثبت حسابداری
                    </button>
                    <span data-ref="formSpinner" style="display:none;" class="acc-loading">
                        <span class="acc-spinner"></span>
                    </span>
                </div>
                `}
            </div>
        `,this._bindRef(),this.on(this.ref("backBtn"),"click",()=>this._showList()),t||(this.on(this.ref("addItemBtn"),"click",()=>this._addItemRow()),this.on(this.ref("saveDraftBtn"),"click",()=>this._saveInvoice("draft")),this.on(this.ref("finalizeBtn"),"click",()=>this._saveAndFinalize())),e!=null&&e.supplier_id&&(this.ref("fSupplier").value=e.supplier_id),e!=null&&e.warehouse_id&&(this.ref("fWarehouse").value=e.warehouse_id),e!=null&&e.id)try{const r=await this.api.get(`/purchase/invoices/${e.id}`);(((n=r==null?void 0:r.data)==null?void 0:n.items)??[]).forEach(l=>this._addItemRow(l))}catch{}!this.ref("itemsBody").querySelectorAll("tr").length&&!t&&this._addItemRow(),this._updateTotals()}_addItemRow(e={}){const t=this.ref("itemsBody"),s=t.querySelectorAll("tr").length,a='<option value="">— انتخاب —</option>'+this._products.map(n=>`<option value="${n.id}" data-price="${n.cost_price||n.sale_price||0}" data-vat="${n.vat_rate||0}">${this.escape(n.name)}</option>`).join(""),i=document.createElement("tr");i.innerHTML=`
            <td style="text-align:center;color:#94a3b8;font-size:12px;" class="row-num">${s+1}</td>
            <td><select class="item-product">${a}</select></td>
            <td><input class="item-desc" type="text" value="${this.escape(e.description||"")}" placeholder="شرح ردیف"></td>
            <td><input class="item-qty" type="number" value="${e.quantity||1}" min="0.001" step="any"></td>
            <td><input class="item-price" type="number" value="${e.unit_price||0}" min="0" step="any"></td>
            <td><input class="item-disc" type="number" value="${e.discount_pct||0}" min="0" max="100" step="0.1"></td>
            <td><input class="item-vat" type="number" value="${e.vat_rate||9}" min="0" max="100" step="0.1"></td>
            <td class="inv-line-total">0</td>
            <td><button type="button" class="acc-btn acc-btn--danger acc-btn--sm" style="padding:3px 8px;">×</button></td>
        `,e.product_id&&(i.querySelector(".item-product").value=e.product_id),i.querySelector(".item-product").addEventListener("change",n=>{const r=n.target.selectedOptions[0];r!=null&&r.dataset.price&&(i.querySelector(".item-price").value=r.dataset.price),r!=null&&r.dataset.vat&&(i.querySelector(".item-vat").value=r.dataset.vat),!i.querySelector(".item-desc").value&&(r!=null&&r.textContent)&&(i.querySelector(".item-desc").value=r.textContent.trim()),this._calcRow(i),this._updateTotals()}),i.querySelectorAll("input").forEach(n=>{n.addEventListener("input",()=>{this._calcRow(i),this._updateTotals()})}),i.querySelector("button").addEventListener("click",()=>{i.remove(),this._renumberRows(),this._updateTotals()}),t.appendChild(i),this._calcRow(i),this._updateTotals()}_calcRow(e){var d,h,u,f;const t=parseFloat((d=e.querySelector(".item-qty"))==null?void 0:d.value)||0,s=parseFloat((h=e.querySelector(".item-price"))==null?void 0:h.value)||0,a=parseFloat((u=e.querySelector(".item-disc"))==null?void 0:u.value)||0,i=parseFloat((f=e.querySelector(".item-vat"))==null?void 0:f.value)||0,n=t*s,r=n*(a/100),o=n-r,l=o*(i/100),c=o+l;return e.querySelector(".inv-line-total").textContent=this._fmt(c),{base:n,dAmt:r,net:o,vatAmt:l,total:c}}_renumberRows(){var e;(e=this.ref("itemsBody"))==null||e.querySelectorAll("tr").forEach((t,s)=>{const a=t.querySelector(".row-num");a&&(a.textContent=s+1)})}_updateTotals(){var i;let e=0,t=0,s=0,a=0;(i=this.ref("itemsBody"))==null||i.querySelectorAll("tr").forEach(n=>{const r=this._calcRow(n);e+=r.base,t+=r.dAmt,s+=r.net,a+=r.vatAmt}),this._totals={subtotal:e,discount_amount:t,net_amount:s,vat_amount:a,total_amount:s+a},this._setRef("tSubtotal",this._fmt(e)),this._setRef("tDiscount",this._fmt(t)),this._setRef("tNet",this._fmt(s)),this._setRef("tVat",this._fmt(a)),this._setRef("tTotal",this._fmt(s+a))}_setRef(e,t){const s=this.ref(e);s&&(s.textContent=t)}_collectItems(){var t;const e=[];return(t=this.ref("itemsBody"))==null||t.querySelectorAll("tr").forEach(s=>{var a,i,n,r,o,l;e.push({product_id:((a=s.querySelector(".item-product"))==null?void 0:a.value)||null,description:((i=s.querySelector(".item-desc"))==null?void 0:i.value)||"",quantity:parseFloat((n=s.querySelector(".item-qty"))==null?void 0:n.value)||0,unit_price:parseFloat((r=s.querySelector(".item-price"))==null?void 0:r.value)||0,discount_pct:parseFloat((o=s.querySelector(".item-disc"))==null?void 0:o.value)||0,vat_rate:parseFloat((l=s.querySelector(".item-vat"))==null?void 0:l.value)||9})}),e.filter(s=>s.quantity>0)}_buildPayload(){var t,s,a,i,n,r,o,l;const e=(t=this.ref("fProject"))==null?void 0:t.value;return{supplier_id:((s=this.ref("fSupplier"))==null?void 0:s.value)||null,warehouse_id:((a=this.ref("fWarehouse"))==null?void 0:a.value)||null,invoice_date:((i=this.ref("fDate"))==null?void 0:i.value)||this._today(),due_date:((n=this.ref("fDue"))==null?void 0:n.value)||null,ref_number:((r=this.ref("fRef"))==null?void 0:r.value)||"",payment_terms:parseInt(((o=this.ref("fPayTerm"))==null?void 0:o.value)??30),description:((l=this.ref("fDesc"))==null?void 0:l.value)||"",project_id:e?parseInt(e):null,items:this._collectItems()}}async _saveInvoice(e="draft"){var a;if(!this._collectItems().length)return alert("حداقل یک ردیف وارد کنید."),null;const s=this._buildPayload();this._setFormBusy(!0);try{let i;return(a=this._editInvoice)!=null&&a.id?(i=await this.api.put(`/purchase/invoices/${this._editInvoice.id}`,s),this._editInvoice.id):(i=await this.api.post("/purchase/invoices",s),this._editInvoice={id:i==null?void 0:i.id},i==null?void 0:i.id)}catch(i){return alert("خطا: "+((i==null?void 0:i.message)??"")),null}finally{this._setFormBusy(!1)}}async _saveAndFinalize(){const e=await this._saveInvoice("draft");e&&await this._finalize(e)}async _finalize(e){this._setFormBusy(!0);try{const t=await this.api.post(`/purchase/invoices/${e}/finalize`,{});t!=null&&t.success?(this._toast(`✅ فاکتور خرید نهایی شد — رویداد حسابداری #${t.event_id} ثبت گردید`),await this._showList()):alert("خطا: "+((t==null?void 0:t.message)??""))}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}finally{this._setFormBusy(!1)}}async _delete(e){if(confirm("حذف این فاکتور خرید؟"))try{await this.api.delete(`/purchase/invoices/${e}`),await this._loadList()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}_setFormBusy(e){const t=this.ref("formSpinner"),s=this.ref("saveDraftBtn"),a=this.ref("finalizeBtn");t&&(t.style.display=e?"flex":"none"),s&&(s.disabled=e),a&&(a.disabled=e)}_today(){return new Date().toISOString().slice(0,10)}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}_toast(e){const t=document.createElement("div");t.style.cssText="position:fixed;bottom:24px;right:24px;background:#7c3aed;color:#fff;padding:13px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;box-shadow:0 4px 20px rgba(0,0,0,.15);max-width:360px;",t.textContent=e,document.body.appendChild(t),setTimeout(()=>t.remove(),4e3)}}class Nn extends x{constructor(e={}){super(e),this._suppliers=[]}async template(){return`
            <div style="display:flex;gap:10px;margin-bottom:14px;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">+ تأمین‌کننده جدید</button>
                <input type="text" data-ref="searchIn" placeholder="جستجو..." style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;min-width:200px;">
            </div>
            <div class="entity-grid" data-ref="grid"></div>
        `}async afterRender(){this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),this.on(this.ref("searchIn"),"input",()=>this._load(this.ref("searchIn").value)),await this._load()}async _load(e=""){const t=this.ref("grid");t.innerHTML='<div class="acc-loading" style="grid-column:1/-1"><div class="acc-spinner"></div></div>';try{const s=await this.api.get("/purchase/suppliers",e?{search:e}:{});this._suppliers=(s==null?void 0:s.data)??[],this._render(t)}catch{t.innerHTML='<div class="acc-error" style="grid-column:1/-1">خطا در بارگذاری</div>'}}_render(e){if(!this._suppliers.length){e.innerHTML='<div class="acc-empty" style="grid-column:1/-1">تأمین‌کننده‌ای یافت نشد.</div>';return}e.innerHTML="",this._suppliers.forEach(t=>{const s=document.createElement("div");s.className="entity-card",s.innerHTML=`
                <div class="entity-card__code">${this.escape(t.code||"")}</div>
                <div class="entity-card__name">${this.escape(t.name)}</div>
                <div class="entity-card__meta">
                    ${t.phone?`📞 ${this.escape(t.phone)}<br>`:""}
                    ${t.tax_id?`🪪 ${this.escape(t.tax_id)}<br>`:""}
                    ${t.bank_iban?`🏦 ${this.escape(t.bank_iban)}<br>`:""}
                    ${t.contact_person?`👤 ${this.escape(t.contact_person)}`:""}
                </div>
                <div class="entity-card__actions">
                    <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit">ویرایش</button>
                    <button class="acc-btn acc-btn--sm" data-action="loc" style="background:#dbeafe;color:#1e40af;">📍 موقعیت</button>
                    <button class="acc-btn acc-btn--danger    acc-btn--sm" data-action="del">حذف</button>
                </div>
            `,s.querySelector("[data-action='edit']").addEventListener("click",()=>this._openForm(t)),s.querySelector("[data-action='del']").addEventListener("click",()=>this._delete(t)),s.querySelector("[data-action='loc']").addEventListener("click",()=>z.openModal({api:this.api,entityType:"supplier",entityId:t.id,entityName:t.name})),e.appendChild(s)})}_openForm(e=null){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
            <div class="acc-modal" style="max-width:540px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${e?"ویرایش تأمین‌کننده":"تأمین‌کننده جدید"}</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>کد</label><input name="code" value="${this.escape((e==null?void 0:e.code)||"")}"></div>
                        <div class="acc-form-group"><label>نام شرکت / شخص *</label><input name="name" value="${this.escape((e==null?void 0:e.name)||"")}" required></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>تلفن</label><input name="phone" value="${this.escape((e==null?void 0:e.phone)||"")}"></div>
                        <div class="acc-form-group"><label>ایمیل</label><input name="email" type="email" value="${this.escape((e==null?void 0:e.email)||"")}"></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>شناسه مالیاتی</label><input name="tax_id" value="${this.escape((e==null?void 0:e.tax_id)||"")}"></div>
                        <div class="acc-form-group"><label>نام رابط</label><input name="contact_person" value="${this.escape((e==null?void 0:e.contact_person)||"")}"></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>شماره شبا / IBAN</label><input name="bank_iban" value="${this.escape((e==null?void 0:e.bank_iban)||"")}"></div>
                        <div class="acc-form-group"><label>نام بانک</label><input name="bank_name" value="${this.escape((e==null?void 0:e.bank_name)||"")}"></div>
                    </div>
                    <div class="acc-form-group"><label>آدرس</label><textarea name="address" rows="2">${this.escape((e==null?void 0:e.address)||"")}</textarea></div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${e?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector("[data-action='cancel']").addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=new FormData(a.target),n=Object.fromEntries(i.entries()),r=a.target.querySelector("[type='submit']");r.disabled=!0,r.textContent="در حال ذخیره...";try{e?await this.api.put(`/purchase/suppliers/${e.id}`,n):await this.api.post("/purchase/suppliers",n),s(),await this._load()}catch(o){alert("خطا: "+((o==null?void 0:o.message)??"")),r.disabled=!1,r.textContent=e?"ذخیره":"افزودن"}})}async _delete(e){if(confirm(`حذف تأمین‌کننده «${e.name}»؟`))try{await this.api.delete(`/purchase/suppliers/${e.id}`),await this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}}const ct=[{key:"invoices",icon:"🛒",title:"فاکتورهای خرید",desc:"ثبت و پیگیری",Class:On},{key:"suppliers",icon:"🏭",title:"تأمین‌کنندگان",desc:"مدیریت تأمین",Class:Nn},{key:"products",icon:"📦",title:"محصولات",desc:"کالا و خدمات",Class:ps}];class us extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="invoices",this._sections={}}async template(){const t=ct.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
            </div>
        `).join(""),s=ct.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=ct.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(us,"title","خرید"),E.register("purchase",us);const Vn=["","فروردین","اردیبهشت","خرداد","تیر","مرداد","شهریور","مهر","آبان","آذر","دی","بهمن","اسفند"],je={draft:{label:"پیش‌نویس",cls:"status-badge--draft",color:"#f59e0b"},generated:{label:"فیش‌تولیدشده",cls:"status-badge--pending",color:"#3b82f6"},finalized:{label:"نهایی‌شده",cls:"status-badge--confirmed",color:"#059669"},paid:{label:"پرداخت‌شده",cls:"status-badge--confirmed",color:"#7c3aed"}};class Wn extends x{constructor(e={}){super(e),this._view="list",this._periods=[],this._projects=[],this._selectedPeriod=null,this._slips=[]}async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._loadProjects(),await this._showList()}async _loadProjects(){try{const e=await this.api.get("/pc/projects",{per_page:200}).catch(()=>null);this._projects=(e==null?void 0:e.data)??[]}catch{}}async _showList(){this._view="list";const e=this.ref("root");e.innerHTML=`
            <div style="display:flex;gap:10px;align-items:center;margin-bottom:16px;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--primary" data-ref="newBtn">➕ دوره حقوقی جدید</button>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
            </div>
            <div data-ref="listBody"></div>
        `,this._bindRef(),this.on(this.ref("newBtn"),"click",()=>this._openCreatePeriod()),this.on(this.ref("refreshBtn"),"click",()=>this._loadList()),await this._loadList()}_bindRef(){var e;(e=this.ref("root"))==null||e.querySelectorAll("[data-ref]").forEach(t=>{this.refs[t.dataset.ref]=t})}async _loadList(){const e=this.ref("listBody");if(e){e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t=await this.api.get("/payroll/periods");this._periods=(t==null?void 0:t.data)??[],this._renderList(e)}catch{e.innerHTML='<div class="acc-error">خطا در بارگذاری دوره‌ها</div>'}}}_renderList(e){if(!this._periods.length){e.innerHTML='<div class="acc-empty">هیچ دوره حقوقی‌ای ثبت نشده است. با دکمه بالا شروع کنید.</div>';return}e.innerHTML="",this._periods.forEach(t=>{e.appendChild(this._buildPeriodCard(t))})}_buildPeriodCard(e){var a,i,n;const t=je[e.status]??je.draft,s=document.createElement("div");return s.className="payroll-period-card",s.style.borderRight=`4px solid ${t.color}`,s.innerHTML=`
            <div style="flex:1;min-width:0;">
                <div style="display:flex;align-items:center;gap:10px;flex-wrap:wrap;">
                    <div style="font-size:16px;font-weight:800;color:#1e293b;">${this.escape(e.period_name)}</div>
                    <span class="status-badge ${t.cls}">${t.label}</span>
                    ${e.project_name?`<span style="font-size:11px;background:#ede9fe;color:#4f46e5;border-radius:8px;padding:2px 9px;font-weight:600;">🏗 ${this.escape(e.project_name)}</span>`:""}
                    ${e.recognition_event_id?`<span class="acc-link-badge">🔗 شناخت #${e.recognition_event_id}</span>`:""}
                    ${e.payment_event_id?`<span class="acc-link-badge" style="background:#ede9fe;color:#5b21b6;">💳 پرداخت #${e.payment_event_id}</span>`:""}
                </div>
                ${e.slip_count>0?`
                <div class="sp-kpi-row" style="margin-top:12px;margin-bottom:0;">
                    <div class="sp-kpi sp-kpi--blue"  style="padding:10px 14px;"><div class="sp-kpi__value">${e.slip_count}</div><div class="sp-kpi__label">پرسنل</div></div>
                    <div class="sp-kpi sp-kpi--green" style="padding:10px 14px;"><div class="sp-kpi__value">${this._fmt(e.total_gross)}</div><div class="sp-kpi__label">ناخالص ﷼</div></div>
                    <div class="sp-kpi sp-kpi--orange" style="padding:10px 14px;"><div class="sp-kpi__value">${this._fmt(e.total_deductions)}</div><div class="sp-kpi__label">کسورات ﷼</div></div>
                    <div class="sp-kpi sp-kpi--purple" style="padding:10px 14px;"><div class="sp-kpi__value">${this._fmt(e.total_net)}</div><div class="sp-kpi__label">خالص ﷼</div></div>
                </div>`:""}
            </div>
            <div style="display:flex;flex-direction:column;gap:6px;align-items:flex-end;min-width:130px;">
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="detail">📋 مشاهده جزئیات</button>
                ${e.status==="draft"?'<button class="acc-btn acc-btn--primary acc-btn--sm" data-action="generate">⚙️ تولید فیش‌ها</button>':""}
                ${e.status==="generated"?'<button class="acc-btn acc-btn--primary acc-btn--sm" data-action="generate" style="background:#3b82f6;border-color:#3b82f6;">🔄 بازتولید فیش‌ها</button><button class="acc-btn acc-btn--primary acc-btn--sm" data-action="finalize" style="background:#059669;border-color:#059669;">✅ نهایی‌سازی</button>':""}
                ${e.status==="finalized"?'<button class="acc-btn acc-btn--primary acc-btn--sm" data-action="pay" style="background:#7c3aed;border-color:#7c3aed;">💳 ثبت پرداخت</button>':""}
            </div>
        `,s.querySelector("[data-action='detail']").addEventListener("click",()=>this._showDetail(e)),(a=s.querySelector("[data-action='generate']"))==null||a.addEventListener("click",r=>{r.stopPropagation(),this._generate(e.id,s)}),(i=s.querySelector("[data-action='finalize']"))==null||i.addEventListener("click",r=>{r.stopPropagation(),this._finalize(e.id)}),(n=s.querySelector("[data-action='pay']"))==null||n.addEventListener("click",r=>{r.stopPropagation(),this._pay(e.id)}),s}_openCreatePeriod(){const e=Vn.slice(1).map((i,n)=>`<option value="${n+1}">${i}</option>`).join(""),t=this._projects.length?'<option value="">— بدون پروژه —</option>'+this._projects.map(i=>`<option value="${i.id}">${this.escape(i.name)}</option>`).join(""):null,s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
            <div class="acc-modal" style="max-width:420px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">ایجاد دوره حقوقی جدید</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>سال شمسی *</label>
                            <input name="year" type="number" min="1390" max="1450" value="1403" required>
                        </div>
                        <div class="acc-form-group">
                            <label>ماه *</label>
                            <select name="month">${e}</select>
                        </div>
                    </div>
                    ${t?`
                    <div class="acc-form-group">
                        <label>پروژه (اختیاری)</label>
                        <select name="project_id">${t}</select>
                    </div>`:""}
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">ایجاد دوره</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action='cancel']").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries()),r={year:n.year,month:n.month};n.project_id&&(r.project_id=parseInt(n.project_id));const o=i.target.querySelector("[type='submit']");o.disabled=!0,o.textContent="در حال ایجاد...";try{await this.api.post("/payroll/periods",r),a(),await this._loadList()}catch(l){alert("خطا: "+((l==null?void 0:l.message)??"")),o.disabled=!1,o.textContent="ایجاد دوره"}})}async _generate(e,t){if(!confirm("فیش‌های حقوقی تولید شود؟ اگر قبلاً تولید شده بودند بازنویسی می‌شوند."))return;const s=t==null?void 0:t.querySelector("[data-action='generate']");s&&(s.disabled=!0,s.textContent="⏳ در حال محاسبه...");try{const a=await this.api.post(`/payroll/periods/${e}/generate`,{});this._toast(`✅ ${a.slip_count} فیش تولید شد — خالص کل: ${this._fmt(a.total_net)} ﷼`),await this._loadList()}catch(a){alert("خطا: "+((a==null?void 0:a.message)??"")),s&&(s.disabled=!1,s.textContent="⚙️ تولید فیش‌ها")}}async _finalize(e){if(confirm("دوره را نهایی کنید؟ رویداد حسابداری «شناخت حقوق» ثبت می‌شود."))try{const t=await this.api.post(`/payroll/periods/${e}/finalize`,{});t!=null&&t.success?(this._toast(`✅ دوره نهایی شد — رویداد #${t.event_id} ثبت گردید`),await this._loadList()):alert("خطا: "+((t==null?void 0:t.message)??""))}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}async _pay(e){if(confirm("پرداخت حقوق ثبت شود؟ رویداد حسابداری «پرداخت حقوق» صادر می‌گردد."))try{const t=await this.api.post(`/payroll/periods/${e}/pay`,{});t!=null&&t.success?(this._toast(`💳 پرداخت حقوق ثبت شد — رویداد #${t.event_id}`,"#7c3aed"),await this._loadList()):alert("خطا: "+((t==null?void 0:t.message)??""))}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}async _showDetail(e){this._view="detail",this._selectedPeriod=e;const t=this.ref("root"),s=je[e.status]??je.draft;t.innerHTML=`
            <div style="display:flex;align-items:center;gap:12px;margin-bottom:20px;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--secondary" data-ref="backBtn">← بازگشت به لیست</button>
                <h2 style="margin:0;font-size:18px;font-weight:800;color:#1e293b;">${this.escape(e.period_name)}</h2>
                <span class="status-badge ${s.cls}">${s.label}</span>
            </div>

            <!-- KPI Row -->
            <div class="sp-kpi-row" style="margin-bottom:20px;">
                <div class="sp-kpi sp-kpi--blue">
                    <div class="sp-kpi__value" data-ref="kpiSlips">${e.slip_count||0}</div>
                    <div class="sp-kpi__label">تعداد فیش</div>
                </div>
                <div class="sp-kpi sp-kpi--green">
                    <div class="sp-kpi__value" data-ref="kpiGross">${this._fmt(e.total_gross)}</div>
                    <div class="sp-kpi__label">ناخالص (ریال)</div>
                </div>
                <div class="sp-kpi sp-kpi--orange">
                    <div class="sp-kpi__value" data-ref="kpiDed">${this._fmt(e.total_deductions)}</div>
                    <div class="sp-kpi__label">کسورات (ریال)</div>
                </div>
                <div class="sp-kpi sp-kpi--purple">
                    <div class="sp-kpi__value" data-ref="kpiNet">${this._fmt(e.total_net)}</div>
                    <div class="sp-kpi__label">خالص (ریال)</div>
                </div>
            </div>

            <!-- Action bar -->
            <div style="display:flex;gap:10px;margin-bottom:16px;flex-wrap:wrap;" data-ref="actionBar"></div>

            <!-- Slips table -->
            <div data-ref="slipsWrap">
                <div class="acc-loading"><div class="acc-spinner"></div></div>
            </div>
        `,this._bindRef(),this.on(this.ref("backBtn"),"click",()=>this._showList()),this._rebuildActions(e),await this._loadSlips(e.id)}_rebuildActions(e){const t=this.ref("actionBar");if(t){if(t.innerHTML="",e.status==="draft"||e.status==="generated"){const s=document.createElement("button");s.className="acc-btn acc-btn--primary",s.textContent=e.status==="draft"?"⚙️ تولید فیش‌ها":"🔄 بازتولید فیش‌ها",s.addEventListener("click",async()=>{if(confirm("فیش‌های حقوقی تولید / بازتولید شود؟")){s.disabled=!0,s.textContent="⏳ در حال محاسبه...";try{const a=await this.api.post(`/payroll/periods/${e.id}/generate`,{});this._toast(`✅ ${a.slip_count} فیش تولید شد`);const i=await this.api.get(`/payroll/periods/${e.id}`);e=(i==null?void 0:i.data)??e,this._selectedPeriod=e,this._updateKPIs(e),this._rebuildActions(e),await this._loadSlips(e.id)}catch(a){alert("خطا: "+((a==null?void 0:a.message)??"")),s.disabled=!1}}}),t.appendChild(s)}if(e.status==="generated"){const s=document.createElement("button");s.className="acc-btn acc-btn--primary",s.style.cssText="background:#059669;border-color:#059669;",s.textContent="✅ نهایی‌سازی و ثبت حسابداری",s.addEventListener("click",async()=>{if(confirm("دوره نهایی شود و رویداد شناخت حقوق در دفتر کل ثبت گردد؟")){s.disabled=!0,s.textContent="⏳ در حال ثبت...";try{const a=await this.api.post(`/payroll/periods/${e.id}/finalize`,{});if(a!=null&&a.success){this._toast(`✅ نهایی‌سازی انجام شد — رویداد حسابداری #${a.event_id}`);const i=await this.api.get(`/payroll/periods/${e.id}`);e=(i==null?void 0:i.data)??e,this._selectedPeriod=e,this._updateKPIs(e),this._rebuildActions(e),await this._loadSlips(e.id)}else alert("خطا: "+((a==null?void 0:a.message)??"")),s.disabled=!1}catch(a){alert("خطا: "+((a==null?void 0:a.message)??"")),s.disabled=!1}}}),t.appendChild(s)}if(e.status==="finalized"){const s=document.createElement("button");if(s.className="acc-btn acc-btn--primary",s.style.cssText="background:#7c3aed;border-color:#7c3aed;",s.textContent="💳 ثبت پرداخت حقوق",s.addEventListener("click",async()=>{if(confirm("پرداخت حقوق ثبت شود؟ رویداد حسابداری «پرداخت» صادر می‌گردد.")){s.disabled=!0,s.textContent="⏳ در حال ثبت...";try{const a=await this.api.post(`/payroll/periods/${e.id}/pay`,{});if(a!=null&&a.success){this._toast(`💳 پرداخت ثبت شد — رویداد #${a.event_id}`,"#7c3aed");const i=await this.api.get(`/payroll/periods/${e.id}`);e=(i==null?void 0:i.data)??e,this._selectedPeriod=e,this._updateKPIs(e),this._rebuildActions(e),await this._loadSlips(e.id)}else alert("خطا: "+((a==null?void 0:a.message)??"")),s.disabled=!1}catch(a){alert("خطا: "+((a==null?void 0:a.message)??"")),s.disabled=!1}}}),t.appendChild(s),e.recognition_event_id){const a=document.createElement("span");a.className="acc-link-badge",a.style.fontSize="12px",a.textContent=`🔗 رویداد شناخت #${e.recognition_event_id}`,t.appendChild(a)}}if(e.status==="paid"){const s=document.createElement("span");s.style.cssText="display:inline-flex;align-items:center;gap:6px;background:#f3e8ff;color:#6d28d9;border-radius:8px;padding:8px 14px;font-size:13px;font-weight:600;",s.textContent=`✅ حقوق پرداخت شده — رویداد #${e.payment_event_id}`,t.appendChild(s)}}}_updateKPIs(e){this._setRef("kpiSlips",e.slip_count??0),this._setRef("kpiGross",this._fmt(e.total_gross)),this._setRef("kpiDed",this._fmt(e.total_deductions)),this._setRef("kpiNet",this._fmt(e.total_net))}async _loadSlips(e){const t=this.ref("slipsWrap");if(t){t.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const s=await this.api.get(`/payroll/periods/${e}/slips`);this._slips=(s==null?void 0:s.data)??[],this._renderSlips(t)}catch{t.innerHTML='<div class="acc-error">خطا در بارگذاری فیش‌ها</div>'}}}_renderSlips(e){if(!this._slips.length){e.innerHTML='<div class="acc-empty">هنوز فیشی تولید نشده است. از دکمه «تولید فیش‌ها» استفاده کنید.</div>';return}const t=a=>`<th style="padding:9px 12px;text-align:right;font-size:12px;font-weight:700;color:#374151;border-bottom:2px solid #e2e8f0;">${a}</th>`;e.innerHTML=`
            <div style="overflow-x:auto;">
            <table style="width:100%;border-collapse:collapse;font-size:13px;min-width:560px;">
                <thead><tr style="background:#f8fafc;">
                    ${t("#")}
                    ${t("پرسنل")}
                    ${t("واحد / سمت")}
                    ${t("ناخالص ﷼")}
                    ${t("کسورات ﷼")}
                    ${t("خالص ﷼")}
                    ${t("عملیات")}
                </tr></thead>
                <tbody id="slips-tbody"></tbody>
            </table>
            </div>`;const s=e.querySelector("#slips-tbody");this._slips.forEach((a,i)=>{const n=document.createElement("tr");n.style.cursor="pointer",n.innerHTML=`
                <td style="padding:9px 12px;color:#94a3b8;font-size:11px;">${i+1}</td>
                <td style="padding:9px 12px;font-weight:700;color:#1e293b;">${this.escape(a.emp_name)}</td>
                <td style="padding:9px 12px;font-size:11px;color:#64748b;">${this.escape(a.position||"")}${a.department?` / ${this.escape(a.department)}`:""}</td>
                <td style="padding:9px 12px;text-align:left;font-family:monospace;color:#059669;">${this._fmt(a.gross_salary)}</td>
                <td style="padding:9px 12px;text-align:left;font-family:monospace;color:#dc2626;">${this._fmt(a.total_deductions)}</td>
                <td style="padding:9px 12px;text-align:left;font-family:monospace;font-weight:800;color:#1e293b;font-size:14px;">${this._fmt(a.net_salary)}</td>
                <td style="padding:9px 8px;text-align:center;">
                    <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="view">ریز فیش</button>
                </td>
            `,n.addEventListener("click",()=>this._openSlipDetail(a.id)),n.querySelector("[data-action='view']").addEventListener("click",r=>{r.stopPropagation(),this._openSlipDetail(a.id)}),s.appendChild(n)})}async _openSlipDetail(e){let t=null;try{const o=await this.api.get(`/payroll/slips/${e}`);t=o==null?void 0:o.data}catch{alert("خطا در بارگذاری فیش");return}const s=(t.items??[]).filter(o=>o.type==="earning"),a=(t.items??[]).filter(o=>o.type==="deduction"),i=(o,l)=>o.map(c=>`
            <tr>
                <td style="padding:7px 14px;color:#475569;">${this.escape(c.component_name)}</td>
                <td style="padding:7px 14px;text-align:left;font-family:monospace;font-weight:600;color:${l};">
                    ${this._fmt(c.amount)} ﷼
                </td>
            </tr>`).join(""),n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
            <div class="acc-modal" style="max-width:480px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title" style="border-bottom:2px solid #e2e8f0;padding-bottom:12px;margin-bottom:16px;">
                    فیش حقوقی — ${this.escape(t.emp_name)}
                    <div style="font-size:12px;color:#64748b;font-weight:400;margin-top:4px;">دوره: ${this.escape(t.period_name??"")}</div>
                </div>

                <table style="width:100%;border-collapse:collapse;font-size:13px;margin-bottom:8px;">
                    <tr style="background:#f0fdf4;">
                        <td colspan="2" style="padding:8px 14px;font-weight:700;color:#059669;font-size:12px;">✅ درآمدها</td>
                    </tr>
                    ${i(s,"#059669")}
                    <tr style="background:#f8fafc;">
                        <td style="padding:8px 14px;font-weight:600;color:#374151;">جمع درآمد ناخالص</td>
                        <td style="padding:8px 14px;text-align:left;font-family:monospace;font-weight:800;color:#059669;">${this._fmt(t.gross_salary)} ﷼</td>
                    </tr>
                </table>

                <table style="width:100%;border-collapse:collapse;font-size:13px;margin-bottom:8px;">
                    <tr style="background:#fef2f2;">
                        <td colspan="2" style="padding:8px 14px;font-weight:700;color:#dc2626;font-size:12px;">🔻 کسورات</td>
                    </tr>
                    ${i(a,"#dc2626")}
                    <tr style="background:#f8fafc;">
                        <td style="padding:8px 14px;font-weight:600;color:#374151;">جمع کسورات</td>
                        <td style="padding:8px 14px;text-align:left;font-family:monospace;font-weight:800;color:#dc2626;">${this._fmt(t.total_deductions)} ﷼</td>
                    </tr>
                </table>

                <table style="width:100%;border-collapse:collapse;font-size:14px;">
                    <tr style="background:#eff6ff;border-top:2px solid #2563eb;">
                        <td style="padding:14px;font-weight:800;color:#1e293b;font-size:15px;">💵 خالص پرداختی</td>
                        <td style="padding:14px;text-align:left;font-family:monospace;font-weight:900;color:#2563eb;font-size:18px;">${this._fmt(t.net_salary)} ﷼</td>
                    </tr>
                </table>

                <div style="text-align:center;margin-top:16px;">
                    <button class="acc-btn acc-btn--secondary" data-action="close">بستن</button>
                </div>
            </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector("[data-action='close']").addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()})}_setRef(e,t){const s=this.ref(e);s&&(s.textContent=t)}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}_toast(e,t="#059669"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;right:24px;background:${t};color:#fff;padding:13px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;box-shadow:0 4px 20px rgba(0,0,0,.15);max-width:400px;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),4500)}}class Un extends x{constructor(e={}){super(e),this._employees=[],this._allComps=[]}async template(){return`
            <div style="display:flex;gap:10px;margin-bottom:14px;flex-wrap:wrap;align-items:center;">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">+ پرسنل جدید</button>
                <input type="text" data-ref="searchIn" placeholder="جستجو نام / کد..." style="padding:7px 12px;border:1.5px solid #d1d5db;border-radius:8px;font-size:13px;min-width:200px;">
            </div>
            <div class="entity-grid" data-ref="grid"></div>
        `}async afterRender(){try{const e=await this.api.get("/payroll/components");this._allComps=(e==null?void 0:e.data)??[]}catch{}this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),this.on(this.ref("searchIn"),"input",()=>this._load(this.ref("searchIn").value)),await this._load()}async _load(e=""){const t=this.ref("grid");t.innerHTML='<div class="acc-loading" style="grid-column:1/-1"><div class="acc-spinner"></div></div>';try{const s=await this.api.get("/payroll/employees",e?{search:e}:{});this._employees=(s==null?void 0:s.data)??[],this._render(t)}catch{t.innerHTML='<div class="acc-error" style="grid-column:1/-1">خطا در بارگذاری پرسنل</div>'}}_render(e){if(!this._employees.length){e.innerHTML='<div class="acc-empty" style="grid-column:1/-1">پرسنلی یافت نشد.</div>';return}e.innerHTML="",this._employees.forEach(t=>{const s=document.createElement("div");s.className="entity-card",s.innerHTML=`
                <div class="entity-card__code">${this.escape(t.emp_code||"")}</div>
                <div class="entity-card__name">${this.escape(t.full_name)}</div>
                <div class="entity-card__meta">
                    ${t.position?`💼 ${this.escape(t.position)}<br>`:""}
                    ${t.department?`🏢 ${this.escape(t.department)}<br>`:""}
                    ${t.hire_date?`📅 استخدام: ${t.hire_date}<br>`:""}
                    ${t.national_id?`🪪 ${this.escape(t.national_id)}`:""}
                </div>
                <div class="entity-card__actions">
                    <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit">ویرایش</button>
                    <button class="acc-btn acc-btn--sm payroll-comp-btn" data-action="comps">💰 حقوق</button>
                    <button class="acc-btn acc-btn--danger    acc-btn--sm" data-action="del">حذف</button>
                </div>
            `,s.querySelector("[data-action='edit']").addEventListener("click",()=>this._openForm(t)),s.querySelector("[data-action='comps']").addEventListener("click",()=>this._openComponents(t)),s.querySelector("[data-action='del']").addEventListener("click",()=>this._delete(t)),e.appendChild(s)})}_openForm(e=null){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
            <div class="acc-modal" style="max-width:520px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${e?"ویرایش پرسنل":"پرسنل جدید"}</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>کد پرسنلی</label><input name="emp_code" value="${this.escape((e==null?void 0:e.emp_code)||"")}"></div>
                        <div class="acc-form-group"><label>نام و نام خانوادگی *</label><input name="full_name" value="${this.escape((e==null?void 0:e.full_name)||"")}" required></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>کد ملی</label><input name="national_id" value="${this.escape((e==null?void 0:e.national_id)||"")}"></div>
                        <div class="acc-form-group"><label>تاریخ استخدام</label><input type="date" name="hire_date" value="${this.escape((e==null?void 0:e.hire_date)||"")}"></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>سمت / عنوان شغلی</label><input name="position" value="${this.escape((e==null?void 0:e.position)||"")}"></div>
                        <div class="acc-form-group"><label>واحد / بخش</label><input name="department" value="${this.escape((e==null?void 0:e.department)||"")}"></div>
                    </div>
                    <div class="acc-form-group"><label>شماره شبا (IBAN)</label><input name="bank_iban" value="${this.escape((e==null?void 0:e.bank_iban)||"")}" placeholder="IR..."></div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${e?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector("[data-action='cancel']").addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries()),n=a.target.querySelector("[type='submit']");n.disabled=!0,n.textContent="در حال ذخیره...";try{e?await this.api.put(`/payroll/employees/${e.id}`,i):await this.api.post("/payroll/employees",i),s(),await this._load()}catch(r){alert("خطا: "+((r==null?void 0:r.message)??"")),n.disabled=!1,n.textContent=e?"ذخیره":"افزودن"}})}async _openComponents(e){let t=[];try{const l=await this.api.get(`/payroll/employees/${e.id}/components`);t=(l==null?void 0:l.data)??[]}catch{}const s={};if(t.forEach(l=>{s[l.component_id]=l.amount}),!this._allComps.length)try{const l=await this.api.get("/payroll/components");this._allComps=(l==null?void 0:l.data)??[]}catch{}const a=this._allComps.filter(l=>l.type==="earning"),i=this._allComps.filter(l=>l.type==="deduction"),n=l=>l.map(c=>{const d=s[c.id]!==void 0,h=s[c.id]??c.default_value??0,u=c.calc_type==="percent_of_base"?"٪":"ریال";return`
                <tr>
                    <td style="text-align:center;padding:7px 6px;">
                        <input type="checkbox" class="comp-chk" data-comp="${c.id}" ${d?"checked":""}>
                    </td>
                    <td style="padding:7px 10px;font-weight:600;">${this.escape(c.name)}</td>
                    <td style="padding:7px 10px;font-size:11px;color:#64748b;">${c.calc_type==="fixed"?"مبلغ ثابت":"% از پایه"}</td>
                    <td style="padding:7px 6px;">
                        <input type="number" class="comp-amt" data-comp="${c.id}"
                               value="${h}" min="0" step="any"
                               style="width:120px;padding:5px 8px;border:1.5px solid #e2e8f0;border-radius:6px;font-size:12px;text-align:left;">
                        <span style="font-size:11px;color:#94a3b8;">${u}</span>
                    </td>
                </tr>`}).join(""),r=document.createElement("div");r.className="acc-modal-overlay",r.innerHTML=`
            <div class="acc-modal" style="max-width:560px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">اجزای حقوق: <span style="color:#2563eb;">${this.escape(e.full_name)}</span></div>
                <form>
                    <p style="font-size:12px;color:#64748b;margin:0 0 12px;">موارد تیک‌دار در محاسبه فیش این پرسنل استفاده می‌شوند.</p>

                    <div style="font-size:12px;font-weight:700;color:#059669;margin-bottom:6px;">✅ درآمدها</div>
                    <table style="width:100%;border-collapse:collapse;margin-bottom:16px;">
                        <thead><tr style="background:#f0fdf4;font-size:12px;">
                            <th style="padding:7px 6px;text-align:right;width:32px;"></th>
                            <th style="padding:7px 10px;text-align:right;">عنوان</th>
                            <th style="padding:7px 10px;text-align:right;">روش</th>
                            <th style="padding:7px 6px;text-align:right;width:160px;">مبلغ / درصد</th>
                        </tr></thead>
                        <tbody>${n(a)}</tbody>
                    </table>

                    <div style="font-size:12px;font-weight:700;color:#dc2626;margin-bottom:6px;">🔻 کسورات</div>
                    <table style="width:100%;border-collapse:collapse;">
                        <thead><tr style="background:#fef2f2;font-size:12px;">
                            <th style="padding:7px 6px;text-align:right;width:32px;"></th>
                            <th style="padding:7px 10px;text-align:right;">عنوان</th>
                            <th style="padding:7px 10px;text-align:right;">روش</th>
                            <th style="padding:7px 6px;text-align:right;width:160px;">مبلغ / درصد</th>
                        </tr></thead>
                        <tbody>${n(i)}</tbody>
                    </table>

                    <div class="acc-modal__actions" style="margin-top:16px;">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">💾 ذخیره اجزای حقوق</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(r);const o=()=>r.remove();r.querySelector(".acc-modal__close").addEventListener("click",o),r.querySelector("[data-action='cancel']").addEventListener("click",o),r.addEventListener("click",l=>{l.target===r&&o()}),r.querySelector("form").addEventListener("submit",async l=>{l.preventDefault();const c=[];r.querySelectorAll(".comp-chk:checked").forEach(h=>{var m;const u=parseInt(h.dataset.comp),f=parseFloat(((m=r.querySelector(`.comp-amt[data-comp="${u}"]`))==null?void 0:m.value)??0)||0;c.push({component_id:u,amount:f})});const d=l.target.querySelector("[type='submit']");d.disabled=!0,d.textContent="در حال ذخیره...";try{await this.api.post(`/payroll/employees/${e.id}/components`,{components:c}),o(),this._toast(`✅ اجزای حقوق ${e.full_name} ذخیره شد`)}catch(h){alert("خطا: "+((h==null?void 0:h.message)??"")),d.disabled=!1,d.textContent="💾 ذخیره اجزای حقوق"}})}async _delete(e){if(confirm(`حذف پرسنل «${e.full_name}»؟`))try{await this.api.delete(`/payroll/employees/${e.id}`),await this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}_toast(e){const t=document.createElement("div");t.style.cssText="position:fixed;bottom:24px;right:24px;background:#059669;color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;box-shadow:0 4px 20px rgba(0,0,0,.15);",t.textContent=e,document.body.appendChild(t),setTimeout(()=>t.remove(),3500)}}const fs={earning:"درآمد",deduction:"کسورات"},ms={fixed:"مبلغ ثابت",percent_of_base:"% از پایه"};class Gn extends x{constructor(e={}){super(e),this._components=[]}async template(){return`
            <div style="display:flex;gap:10px;align-items:center;margin-bottom:16px;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">+ جزء حقوقی جدید</button>
                <span style="font-size:12px;color:#94a3b8;" data-ref="countLbl"></span>
            </div>
            <div data-ref="tableWrap"></div>
        `}async afterRender(){this.on(this.ref("addBtn"),"click",()=>this._openForm(null)),await this._load()}async _load(){const e=this.ref("tableWrap");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t=await this.api.get("/payroll/components");this._components=(t==null?void 0:t.data)??[];const s=this.ref("countLbl");s&&(s.textContent=`${this._components.length} جزء تعریف‌شده`),this._render(e)}catch{e.innerHTML='<div class="acc-error">خطا در بارگذاری</div>'}}_render(e){if(!this._components.length){e.innerHTML='<div class="acc-empty">هیچ جزء حقوقی تعریف نشده است.</div>';return}const t=(a,i="")=>`<th style="padding:10px 12px;text-align:right;font-size:12px;font-weight:700;color:#374151;border-bottom:2px solid #e2e8f0;${i?"width:"+i:""}">${a}</th>`;e.innerHTML=`
            <div style="overflow-x:auto;">
            <table style="width:100%;border-collapse:collapse;font-size:13px;min-width:600px;">
                <thead><tr style="background:#f8fafc;">
                    ${t("کد","60px")}
                    ${t("عنوان")}
                    ${t("نوع","90px")}
                    ${t("روش محاسبه","120px")}
                    ${t("مقدار پیش‌فرض","130px")}
                    ${t("بیمه‌پذیر","70px")}
                    ${t("مالیاتی","70px")}
                    ${t("عملیات","110px")}
                </tr></thead>
                <tbody data-ref="tbody"></tbody>
            </table>
            </div>`,this.refs.tbody=e.querySelector("[data-ref='tbody']");const s=this.refs.tbody;this._components.forEach((a,i)=>{const n=a.type==="earning",r=document.createElement("tr");r.style.background=i%2===0?"#fff":"#fafbff",r.innerHTML=`
                <td style="padding:9px 12px;font-family:monospace;font-size:11px;color:#94a3b8;">${this.escape(a.code||"")}</td>
                <td style="padding:9px 12px;font-weight:600;color:#1e293b;">${this.escape(a.name)}</td>
                <td style="padding:9px 12px;">
                    <span class="payroll-type-badge ${n?"payroll-type-badge--earn":"payroll-type-badge--ded"}">
                        ${n?"✅":"🔻"} ${fs[a.type]??a.type}
                    </span>
                </td>
                <td style="padding:9px 12px;font-size:12px;color:#475569;">${ms[a.calc_type]??a.calc_type}</td>
                <td style="padding:9px 12px;text-align:left;font-family:monospace;font-weight:600;">
                    ${this._fmt(a.default_value)}${a.calc_type==="percent_of_base"?"%":" ﷼"}
                </td>
                <td style="padding:9px 12px;text-align:center;">${+a.is_insurance_base?"✅":"—"}</td>
                <td style="padding:9px 12px;text-align:center;">${+a.is_taxable?"✅":"—"}</td>
                <td style="padding:9px 8px;text-align:center;">
                    <button class="acc-btn acc-btn--secondary acc-btn--sm" data-action="edit">ویرایش</button>
                    <button class="acc-btn acc-btn--danger    acc-btn--sm" data-action="del">حذف</button>
                </td>
            `,r.querySelector("[data-action='edit']").addEventListener("click",()=>this._openForm(a)),r.querySelector("[data-action='del']").addEventListener("click",()=>this._delete(a)),s.appendChild(r)})}_openForm(e=null){const t=["earning","deduction"].map(n=>`<option value="${n}" ${(e==null?void 0:e.type)===n?"selected":""}>${fs[n]}</option>`).join(""),s=Object.entries(ms).map(([n,r])=>`<option value="${n}" ${(e==null?void 0:e.calc_type)===n?"selected":""}>${r}</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
            <div class="acc-modal" style="max-width:480px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${e?"ویرایش جزء حقوقی":"جزء حقوقی جدید"}</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>کد</label><input name="code" value="${this.escape((e==null?void 0:e.code)||"")}"></div>
                        <div class="acc-form-group"><label>عنوان *</label><input name="name" value="${this.escape((e==null?void 0:e.name)||"")}" required></div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>نوع</label>
                            <select name="type">${t}</select>
                        </div>
                        <div class="acc-form-group">
                            <label>روش محاسبه</label>
                            <select name="calc_type">${s}</select>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>مقدار پیش‌فرض</label><input name="default_value" type="number" step="any" min="0" value="${(e==null?void 0:e.default_value)??0}"></div>
                        <div class="acc-form-group"><label>ترتیب نمایش</label><input name="sort_order" type="number" min="0" value="${(e==null?void 0:e.sort_order)??0}"></div>
                    </div>
                    <div class="doc-form-row" style="gap:20px;align-items:center;padding:8px 0;">
                        <label style="display:flex;align-items:center;gap:8px;font-size:13px;cursor:pointer;">
                            <input type="checkbox" name="is_insurance_base" value="1" ${+(e==null?void 0:e.is_insurance_base)?"checked":""}>
                            مبنای محاسبه بیمه
                        </label>
                        <label style="display:flex;align-items:center;gap:8px;font-size:13px;cursor:pointer;">
                            <input type="checkbox" name="is_taxable" value="1" ${+(e==null?void 0:e.is_taxable)?"checked":""}>
                            مشمول مالیات
                        </label>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${e?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action='cancel']").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=new FormData(n.target),o=Object.fromEntries(r.entries());o.is_insurance_base=r.has("is_insurance_base")?1:0,o.is_taxable=r.has("is_taxable")?1:0;const l=n.target.querySelector("[type='submit']");l.disabled=!0,l.textContent="در حال ذخیره...";try{e?await this.api.put(`/payroll/components/${e.id}`,o):await this.api.post("/payroll/components",o),i(),await this._load()}catch(c){alert("خطا: "+((c==null?void 0:c.message)??"")),l.disabled=!1,l.textContent=e?"ذخیره":"افزودن"}})}async _delete(e){if(confirm(`حذف «${e.name}»؟`))try{await this.api.delete(`/payroll/components/${e.id}`),await this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}}const dt=[{key:"run",icon:"🏃",title:"اجرای حقوق",desc:"دوره‌ها و فیش‌ها",Class:Wn},{key:"employees",icon:"👨‍💼",title:"پرسنل",desc:"مدیریت کارکنان",Class:Un},{key:"components",icon:"⚙️",title:"اجزای حقوق",desc:"تعریف مؤلفه‌ها",Class:Gn}];class vs extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="run",this._sections={}}async template(){const t=dt.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
            </div>
        `).join(""),s=dt.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=dt.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(vs,"title","حقوق و دستمزد"),E.register("payroll",vs);class bs{constructor(e){this.api=e}async load(e,t={}){if(!e)throw new Error("Entity is required");try{const s=await this.api.get(`runtime/${e}/schema`),a=(s==null?void 0:s.data)||s;if(!a||!Array.isArray(a.fields))throw console.error("Invalid schema response:",s),new Error("Invalid schema response");return t.forCard&&(a.fields=a.fields.filter(i=>typeof i.show_in_card>"u"?!0:Number(i.show_in_card)===1)),a}catch(s){throw console.error("Schema load failed:",s),new Error((s==null?void 0:s.message)||"Schema load failed")}}}class Kn{constructor(){this.events={}}on(e,t){this.events[e]||(this.events[e]=[]),this.events[e].push(t)}emit(e,t={}){this.events[e]&&this.events[e].forEach(s=>s(t)),this.events["*"]&&this.events["*"].forEach(s=>s(e,t))}}class pe{}g(pe,"bus",new Kn);class Q{static register(e,t){this.components[e]=t}static get(e){return this.components[e]}}g(Q,"components",{});function O(p){return String(p).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#039;")}class Jn{static render(e,t){return`
            <div class="project-header">

                <div>

                    <div class="project-title">
                        ${O(t.title)}
                    </div>

                    <div class="project-code">
                        ${O(t.code)}
                    </div>

                </div>

                <div class="
                    project-status
                    ${O(t.status)}
                ">
                    ${O(t.status)}
                </div>

            </div>
        `}}class Yn{static render(e,t){const s=Number(t.progress)||0;return`
            <div class="project-progress">

                <div class="progress-label">
                    ${s}%
                </div>

                <div class="progress-bar">

                    <div
                        class="progress-fill"
                        style="width:${s}%">
                    </div>

                </div>

            </div>
        `}}class Qn{static render(e,t){return`
            <div class="project-stats">
                ${e.fields.map(a=>`
                <div class="stat">

                    <span>
                        ${O(a)}
                    </span>

                    <strong>
                        ${O(t[a])}
                    </strong>

                </div>
            `).join("")}
            </div>
        `}}class Zn{static render(e,t){return e.actions?`
            <div class="project-actions">
                ${e.actions.map(a=>`
                <button
                    class="card-action"
                    data-action="${O(a)}"
                    data-id="${O(t.id)}">

                    ${O(a)}

                </button>
            `).join("")}
            </div>
        `:""}}const Xn={type:"field-list",resolveValue(p,e){if(!e||!p)return"";if(e[p+"_label"]!==void 0)return e[p+"_label"];const t=p+"_id";if(t in e&&e[p+"_id_label"]!==void 0)return e[p+"_id_label"];if(p in e)return e[p];if(t in e)return e[t];if(p.endsWith("_id")){const n=p.replace(/_id$/,"");if(n in e)return e[n]}const s=p.toLowerCase();for(const n of Object.keys(e))if(n.toLowerCase()===s)return e[n];const a=p.replace(/[A-Z]/g,n=>"_"+n.toLowerCase());if(a in e)return e[a];const i=p.replace(/_([a-z])/g,function(n,r){return r.toUpperCase()});return i in e?e[i]:""},resolveRelationDisplayValue(p,e){const t=e[p.name];if(e[p.name+"_label"]!==void 0)return e[p.name+"_label"];if(t&&typeof t=="object"){const i=p.config&&p.config.displayField||"title";if(t[i]!==void 0)return t[i];if(t.title!==void 0)return t.title;if(t.name!==void 0)return t.name;if(t.label!==void 0)return t.label}const s=p.name.replace(/_id$/,""),a=[p.name+"_display",p.name+"_title",p.name+"_name",p.name+"_label",s+"_display",s+"_title",s+"_name",s+"_label"];for(const i of a)if(e[i]!==void 0&&e[i]!==null&&e[i]!=="")return e[i];return t&&typeof t=="object"&&t.id!==void 0?t.title||t.name||t.label||t.id:null},render(p,e){return!p||!Array.isArray(p.fields)||p.fields.length===0?'<div class="runtime-card-warning">⚠️ No visible fields defined</div>':`
            <div class="runtime-field-list">
                ${p.fields.map(s=>{const a=s&&s.name?s.name:"",i=s&&s.label?s.label:a,n=s&&s.type?s.type:null;let r=this.resolveValue(a,e);if(n==="relation"){const l=this.resolveRelationDisplayValue(s,e);l!==null&&(r=l)}const o=r!=null&&r!==""?r:"—";return`
                <div class="runtime-field-row">
                    <div class="runtime-field-label">
                        ${i}
                    </div>
                    <div class="runtime-field-value">
                        ${o}
                    </div>
                </div>
            `}).join("")}
            </div>
        `}};Q.register("field-list",Xn),Q.register("header",Jn),Q.register("progress",Yn),Q.register("stats",Qn),Q.register("actions",Zn);class er{static async handle(e,t){console.log("[Process]",e,t)}}pe.bus.on("*",async(p,e)=>{await er.handle(p,e)});class gs{static render(e,t){if(!e)return console.warn("CardRenderer: schema missing"),"";let s=[];if(e.card&&Array.isArray(e.card.sections))s=e.card.sections;else if(Array.isArray(e.fields))s=this.buildSectionsFromFields(e.fields);else return console.warn("CardRenderer: invalid schema structure",e),"";return`
            <div class="runtime-card">
                ${s.map(i=>this.renderSection(i,t)).join("")}
            </div>
        `}static buildSectionsFromFields(e){if(!Array.isArray(e))return[];const t=a=>{const i=a.name??a.field??a.key??a.column_name??a.field_name??null,n=a.label??a.title??a.caption??a.text??a.field_label??i??"";return i?{name:i,label:n,type:a.field_type??a.type??null,config:a.config??a.field_config??null}:null};return[{type:"field-list",fields:e.map(t).filter(Boolean)}]}static renderSection(e,t){if(!e||!e.type)return console.warn("CardRenderer: invalid section",e),"";const s=Q.get(e.type);if(!s)return console.warn(`CardRenderer: component not found → ${e.type}`),"";if(typeof s.render!="function")return console.warn(`CardRenderer: component has no render() → ${e.type}`),"";try{return s.render(e,t)}catch(a){return console.error(`CardRenderer: component render failed → ${e.type}`,a),`<div class="runtime-card-error">⚠️ Render failed for ${e.type}</div>`}}}se.registerModule([Re,Ce,Me,Le,Te,Qe]);class tr{constructor({api:e,schema:t,store:s=null,eventBus:a=null}){this.api=e,this.schema=t,this.store=s,this.eventBus=a,this.table=null,this.currentSearchTerm="",this._selectedId=null}_prepareRecord(e){if(!e)return e;const t={...e};if(typeof t.status_id=="string"&&t.status_id.includes("–")){const s=t.status_id.split("–");t.status_id=parseInt(s[0].trim()),t.status_id_label=s[1].trim()}if(typeof t.phase_id=="string"&&t.phase_id.includes("–")){const s=t.phase_id.split("–");t.phase_id=parseInt(s[0].trim()),t.phase_id_label=s[1].trim()}if(typeof t.lifecycle_stage_id=="string"&&t.lifecycle_stage_id.includes("–")){const s=t.lifecycle_stage_id.split("–");t.lifecycle_stage_id=parseInt(s[0].trim()),t.lifecycle_stage_id_label=s[1].trim()}return t.status&&typeof t.status=="object"&&t.status.title&&(t.status_label=t.status.title),Object.keys(t).forEach(s=>{t[s]&&typeof t[s]=="object"&&t[s].title&&(t[s+"_label"]=t[s].title)}),t}mount(e){this._injectStyles();const t='<svg viewBox="0 0 24 24" width="18" height="18"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25z"/></svg>',s='<svg viewBox="0 0 24 24" width="18" height="18"><path d="M6 7h12v12a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V7zm3-4h6l1 2H8l1-2z"/></svg>';this.table=new se(e,{index:"id",height:"auto",layout:"fitColumns",headerVisible:!1,pagination:!0,paginationMode:"remote",paginationSize:10,ajaxURL:"/runtime/projects/records",ajaxRequestFunc:async(a,i,n)=>{var o;const r={page:n.page||1,size:n.size||10,search:this.currentSearchTerm.trim()};try{const l=await this.api.get("/runtime/projects/records",r);return{data:((l==null?void 0:l.data)??[]).map(h=>this._prepareRecord(h)),last_page:Math.max(1,Math.ceil((((o=l==null?void 0:l.pagination)==null?void 0:o.total)||0)/(n.size||10)))}}catch(l){return console.error("Fetch Error:",l),{data:[],last_page:1}}},columns:[{field:"id",widthGrow:1,formatter:a=>{const i=a.getRow().getData();let n="";try{n=gs.render(this.schema,i)}catch(r){console.error("Render Error ID "+i.id,r),n='<div style="color:red; padding:10px;">Error in CardRenderer</div>'}return`
              <div class="project-card-wrapper" style="width:100%; padding:2px;">
                <div class="project-card" style="background:#fff; border:1px solid #eee; border-radius:10px; box-shadow:0 2px 8px rgba(0,0,0,0.05); overflow:hidden;">
                    <div class="card-body" style="padding:15px;">${n}</div>
                    <div class="card-footer" style="background:#f9f9f9; padding:10px 15px; display:flex; justify-content:flex-end; gap:10px; border-top:1px solid #eee;">
                       <button class="edit-trigger" title="ویرایش" style="border:none; background:none; cursor:pointer; fill:#1a73e8; padding:5px;">${t}</button>
                       <button class="delete-trigger" title="حذف" style="border:none; background:none; cursor:pointer; fill:#d93025; padding:5px;">${s}</button>
                    </div>
                </div>
              </div>`}}]}),this.table.on("cellClick",(a,i)=>{const n=i.getRow().getData(),r=a.target.closest("button");if(r!=null&&r.classList.contains("edit-trigger")){pe.bus.emit("project-edit-requested",{id:n.id,record:n});return}if(r!=null&&r.classList.contains("delete-trigger")){pe.bus.emit("project-delete-requested",{id:n.id});return}this._selectProject(n)})}_selectProject(e){e!=null&&e.id&&(this._selectedId=e.id,this.store&&this.store.set("context.project",e),this._updateSelectionVisual(e.id))}_updateSelectionVisual(e){this.table&&this.table.getRows().forEach(t=>{const s=t.getData(),a=t.getElement();a&&a.classList.toggle("project-card--selected",s.id===e)})}search(e){this.currentSearchTerm=(e||"").trim(),this.table&&(this.table.setPage(1),this.table.setData("/runtime/projects/records"))}updateRow(e,t){if(!this.table)return;const s=this.table.getRow(e);s?s.update(this._prepareRecord(t)):this.reload()}deleteRow(e){if(!this.table)return;const t=this.table.getRow(e);t&&t.delete()}reload(){this.table&&this.table.setData("/runtime/projects/records")}_injectStyles(){if(document.getElementById("projects-table-styles"))return;const e=document.createElement("style");e.id="projects-table-styles",e.innerHTML=`
      .tabulator { border:none !important; background:transparent !important; font-family: inherit !important; }
      .tabulator-tableholder { overflow-x: hidden !important; }
      .tabulator-row { display: block !important; width: 100% !important; margin-bottom: 15px !important; background: transparent !important; border: none !important; }
      .tabulator-cell { width: 100% !important; display: block !important; padding: 0 !important; border: none !important; }
      .project-card { transition: all 0.3s ease; cursor: pointer; }
      .project-card:hover { transform: translateY(-3px); box-shadow: 0 4px 12px rgba(0,0,0,0.1) !important; }
      .tabulator-row.project-card--selected .project-card { border: 2px solid #1a73e8 !important; box-shadow: 0 0 0 3px rgba(26,115,232,0.15) !important; }
      .tabulator-row.project-card--selected .project-card::before { content: "✓ انتخاب شده"; display:block; background:#1a73e8; color:#fff; font-size:11px; padding:2px 10px; text-align:right; }
    `,document.head.appendChild(e)}destroy(){var e;(e=this.table)==null||e.destroy()}}class ys{constructor({table:e}){e?this.table=e:(console.error("ProjectsToolbar requires a 'table' instance."),this.table=null),this.searchTimeout=null}mount(e){e.innerHTML=`
            <div class="projects-toolbar-wrapper">
                <input 
                    class="projects-runtime-search"
                    type="text"
                    placeholder="جستجو در نام پروژه، کد یا کارفرما..."
                    style="
                        width:100%;
                        padding:10px 12px;
                        border:1px solid #ddd;
                        border-radius:8px;
                        outline:none;
                        font-size:14px;
                    "
                >
            </div>
        `,e.querySelector(".projects-runtime-search").addEventListener("input",s=>{clearTimeout(this.searchTimeout),this.searchTimeout=setTimeout(()=>{const a=s.target.value||"";this.table&&typeof this.table.search=="function"?this.table.search(a):console.warn("Table instance or search method not available in ProjectsToolbar.")},450)})}destroy(){this.searchTimeout&&(clearTimeout(this.searchTimeout),this.searchTimeout=null)}}class sr{constructor({api:e=null,schema:t=null}={}){this.formEl=null,this.api=e,this.schema=t}async mount(e,t={},s=null){const a=s||this.schema;if(e.innerHTML="",!a||!Array.isArray(a.fields)){console.error("[DynamicFormAdapter] No valid schema fields found.");return}const i=[];for(const n of a.fields){const r=n.field_name,o=document.createElement("div");o.className="form-group mb-3",o.dataset.fieldName=r;const l=document.createElement("label");l.textContent=n.field_label||r,o.appendChild(l);const c=t[r]??"",d=document.createElement("input");d.name=r,d.value=c,d.className="form-control",n.field_type==="date"?d.type="date":n.field_type==="relation"?d.type="hidden":d.type="text",o.appendChild(d),e.appendChild(o),n.field_type==="relation"&&c&&i.push({wrapper:o,field:n,value:c})}this.formEl=e.closest("form")||e,this._loadRelationHints(i)}async _loadRelationHints(e=[]){if(!e.length||!this.api)return;const t=e.map(async({wrapper:s,field:a,value:i})=>{var n;try{const r=await this.api.get(`/runtime/${a.source_entity}/record/${i}`),o=((n=r==null?void 0:r.data)==null?void 0:n.name)||(r==null?void 0:r.name)||"";if(!o)return;let l=s.querySelector(".relation-hint");l||(l=document.createElement("small"),l.className="relation-hint",l.style.display="block",l.style.marginTop="4px",l.style.color="#6b7280",s.appendChild(l)),l.textContent=`نمایش: ${o}`}catch(r){console.warn(`[DynamicFormAdapter] Failed to load relation label for ${a.field_name}:`,r)}});await Promise.all(t)}getValue(){if(!this.formEl)return{};const e={},t=this.formEl.querySelectorAll("input, select, textarea");for(const s of t)s.name&&(e[s.name]=s.value);return e}}class ar{constructor({api:e,source:t,valueField:s="id",labelField:a="name"}){this.api=e,this.source=t,this.valueField=s,this.labelField=a,this.container=null,this.input=null,this.dropdown=null,this.records=[],this.value=null}async mount(e,t=null){e&&(this.container=document.createElement("div"),this.container.className="search-select",this.container.innerHTML=`
            <input type="text" class="search-select-input" placeholder="جستجو..." />
            <div class="search-select-dropdown"></div>
        `,e.appendChild(this.container),this.input=this.container.querySelector(".search-select-input"),this.dropdown=this.container.querySelector(".search-select-dropdown"),!(!this.input||!this.dropdown)&&(await this.load(),t&&this.setValue(t),this.bindEvents()))}async load(){if(!this.api||typeof this.api.get!="function")return;const e=await this.api.get(this.source);this.records=(e==null?void 0:e.records)||(e==null?void 0:e.data)||e||[],this.renderList(this.records)}bindEvents(){!this.input||!this.dropdown||(this.input.addEventListener("focus",()=>{this.dropdown.style.display="block"}),this.input.addEventListener("input",()=>{const e=(this.input.value||"").toLowerCase(),t=this.records.filter(s=>String(s[this.labelField]??"").toLowerCase().includes(e));this.renderList(t)}),document.addEventListener("click",e=>{this.container.contains(e.target)||(this.dropdown.style.display="none")}))}renderList(e){if(!this.dropdown)return;this.dropdown.innerHTML=e.map(s=>`
            <div class="search-select-item" data-id="${s[this.valueField]}">
                ${s[this.labelField]}
            </div>
        `).join(""),this.dropdown.querySelectorAll(".search-select-item").forEach(s=>{s.onclick=()=>{const a=s.dataset.id,i=e.find(n=>String(n[this.valueField])===a);this.value=a,i&&(this.input.value=i[this.labelField]),this.dropdown.style.display="none"}})}setValue(e){const t=this.records.find(s=>String(s[this.valueField])===String(e));t&&(this.value=e,this.input.value=t[this.labelField])}getValue(){return this.value}}class _s{constructor({api:e,table:t=null,schema:s,onSaved:a=null}){this.api=e,this.table=t,this.schema=s,this.onSaved=a,this.modal=null,this.formAdapter=new sr({api:this.api,schema:this.schema}),this.context=null,this.relationInputs={},this._openSeq=0,this._mountEl=null,this._titleEl=null,this._formEl=null}mount(e){const t=document.createElement("div");t.className="projects-dynamic-modal-backdrop",t.innerHTML=`
            <div class="projects-dynamic-modal" role="dialog" aria-modal="true">
                <div class="projects-dynamic-modal-header">
                    <h2 class="projects-dynamic-modal-title">ویرایش پروژه</h2>
                    <button type="button" class="projects-dynamic-modal-close" aria-label="Close">×</button>
                </div>

                <form class="projects-dynamic-form">
                    <div class="projects-dynamic-modal-body">
                        <div class="dynamic-form-mount"></div>
                    </div>

                    <div class="projects-dynamic-modal-footer">
                        <button type="button" class="projects-dynamic-cancel">انصراف</button>
                        <button type="submit" class="projects-dynamic-save">ذخیره</button>
                    </div>
                </form>
            </div>
        `,e.appendChild(t),this.modal=t,this._injectStyles(),this._mountEl=this.modal.querySelector(".dynamic-form-mount"),this._titleEl=this.modal.querySelector(".projects-dynamic-modal-title"),this._formEl=this.modal.querySelector("form"),this._bindEvents()}_bindEvents(){this._formEl.addEventListener("submit",async e=>{var s,a,i;if(e.preventDefault(),!((s=this.context)!=null&&s.id))return;const t=this.formAdapter.getValue();for(const n in this.relationInputs)t[n]=((i=(a=this.relationInputs[n])==null?void 0:a.getValue)==null?void 0:i.call(a))??t[n];try{await this.api.put(`/runtime/projects/record/${this.context.id}`,t),typeof this.onSaved=="function"?await this.onSaved():this.table&&typeof this.table.reload=="function"&&await this.table.reload(),this.close()}catch(n){console.error("Update error:",n),alert("خطا در ذخیره‌سازی تغییرات پروژه")}}),this.modal.querySelector(".projects-dynamic-modal-close").onclick=()=>this.close(),this.modal.querySelector(".projects-dynamic-cancel").onclick=()=>this.close(),this.modal.addEventListener("click",e=>{e.target===this.modal&&this.close()}),document.addEventListener("keydown",e=>{var t;e.key==="Escape"&&((t=this.modal)!=null&&t.classList.contains("is-open"))&&this.close()})}async open({id:e,record:t,title:s}){this.context={id:e},this.relationInputs={};const a=++this._openSeq;this._titleEl.textContent=s||"ویرایش پروژه",this._mountEl.innerHTML="",this.modal.classList.add("is-open"),await new Promise(i=>requestAnimationFrame(i)),a===this._openSeq&&(await this.formAdapter.mount(this._mountEl,t,this.schema),a===this._openSeq&&this._enhanceRelationFields(t,a))}async _enhanceRelationFields(e,t){var a,i;if(!((i=(a=this.schema)==null?void 0:a.fields)!=null&&i.length))return;const s=[];for(const n of this.schema.fields){if(n.field_type!=="relation")continue;const r=this._mountEl.querySelector(`[name="${CSS.escape(n.field_name)}"]`);if(!r)continue;r.style.display="none";const o=r.parentNode;if(!o||o.querySelector(".search-select"))continue;const l=new ar({api:this.api,source:`/runtime/${n.source_entity}/records`,valueField:"id",labelField:"name"}),c=l.mount(o,e==null?void 0:e[n.field_name]).then(()=>{t===this._openSeq&&(this.relationInputs[n.field_name]=l)}).catch(d=>{t===this._openSeq&&console.error("Relation load error:",d)});s.push(c)}await Promise.all(s)}close(){this._openSeq++,this.modal.classList.remove("is-open"),this.context=null,this.relationInputs={}}_injectStyles(){if(document.getElementById("projects-dynamic-modal-style"))return;const e=document.createElement("style");e.id="projects-dynamic-modal-style",e.textContent=`
            .projects-dynamic-modal-backdrop{
                position: fixed; inset: 0;
                background: rgba(0,0,0,0.45);
                display: flex; align-items: center; justify-content: center;
                padding: 24px;
                z-index: 9999;
                opacity: 0; visibility: hidden;
                transition: opacity .2s ease;
                direction: rtl;
            }
            .projects-dynamic-modal-backdrop.is-open{ opacity: 1; visibility: visible; }

            .projects-dynamic-modal{
                width: min(960px,100%);
                max-height: 90vh;
                background: #fff;
                border-radius: 12px;
                box-shadow: 0 20px 50px rgba(0,0,0,0.18);
                display: flex;
                flex-direction: column;
                overflow: hidden;
            }

            .projects-dynamic-modal-header{
                display: flex; justify-content: space-between; align-items: center;
                padding: 20px 24px;
                border-bottom: 1px solid #e5e7eb;
                background: #f8fafc;
            }
            .projects-dynamic-modal-title{ margin: 0; font-size: 18px; font-weight: 700; }
            .projects-dynamic-modal-close{ border: none; background: transparent; font-size: 24px; cursor: pointer; }

            /* نکته مهم برای اسکرول داخل flex */
            .projects-dynamic-modal-body{
                padding: 24px;
                overflow-y: auto;
                flex: 1 1 auto;
                min-height: 0;
            }

            .dynamic-form-mount{ display: flex; flex-direction: column; gap: 20px; }
            .dynamic-form-mount input, .dynamic-form-mount .search-select{ width: 100%; box-sizing: border-box; }

            .projects-dynamic-modal-footer{
                display: flex; justify-content: flex-end; gap: 12px;
                padding: 16px 24px;
                border-top: 1px solid #e5e7eb;
                background: #f8fafc;
            }

            .projects-dynamic-save{
                background: #2563eb; color: #fff;
                border: none; padding: 10px 20px;
                border-radius: 10px; cursor: pointer;
            }
            .projects-dynamic-cancel{
                background: #e5e7eb;
                border: none; padding: 10px 20px;
                border-radius: 10px; cursor: pointer;
            }
        `,document.head.appendChild(e)}}class ir{constructor({modal:e}){this.modal=e,this.bind()}bind(){pe.bus.on("project-edit-requested",e=>{this.modal.open({title:"ویرایش پروژه",id:e.id,record:e.record})})}}let nr=(It=class extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this.schemaLoader=new bs(this.api),this.table=null,this.toolbar=null,this.modal=null,this.runtimeEvents=null}async render(t){await super.render(t);const s=this.ref("body");s.innerHTML=`
            <div class="projects-runtime-wrapper">
                <div class="projects-runtime-toolbar"></div>
                <div class="projects-runtime-table"></div>
            </div>
        `;const a=await this.schemaLoader.load("projects");return this.table=new tr({api:this.api,schema:a,store:this.store,eventBus:this.eventBus}),this.toolbar=new ys({table:this.table}),this.modal=new _s({api:this.api,table:this.table,schema:a,onSaved:async()=>{await this.table.reload()}}),this.runtimeEvents=new ir({modal:this.modal}),this.table.mount(s.querySelector(".projects-runtime-table")),this.toolbar.mount(s.querySelector(".projects-runtime-toolbar")),this.modal.mount(s),this}destroy(){var t,s,a,i,n,r;dbg("Destroying ProjectsRuntimeView..."),(s=(t=this.table)==null?void 0:t.destroy)==null||s.call(t),(i=(a=this.toolbar)==null?void 0:a.destroy)==null||i.call(a),(r=(n=this.modal)==null?void 0:n.destroy)==null||r.call(n),this.runtimeEvents&&typeof this.runtimeEvents.destroy=="function"&&this.runtimeEvents.destroy(),super.destroy()}},g(It,"title","لیست پروژه‌ها"),It);E.register("projectsAuo",nr);class rr{constructor(){const e=localStorage.getItem("runtime_state");this.state=e?JSON.parse(e):{},this.listeners={}}set(e,t){this.state[e]=t,localStorage.setItem("runtime_state",JSON.stringify(this.state)),this.notify(e,t)}get(e){return this.state[e]}subscribe(e,t){this.listeners[e]||(this.listeners[e]=[]),this.listeners[e].push(t)}notify(e,t){this.listeners[e]&&this.listeners[e].forEach(s=>s(t))}}const xs=new rr;class or{constructor({api:e,endpoint:t,pageSize:s=10}){this.api=e,this.endpoint=t,this.pageSize=s,this.currentPage=1,this.totalPages=1,this.totalRecords=0,this.records=[],this.searchTerm="",this.onDataLoaded=null,this.onError=null}async loadPage(e=1){var s;this.currentPage=e;const t={page:this.currentPage,size:this.pageSize,search:this.searchTerm.trim()};try{const a=await this.api.get(this.endpoint,t),i=(a==null?void 0:a.data)??[],n=((s=a==null?void 0:a.pagination)==null?void 0:s.total)??i.length;this.records=i,this.totalRecords=n,this.totalPages=Math.max(1,Math.ceil(this.totalRecords/this.pageSize)),this.onDataLoaded&&this.onDataLoaded({records:this.records,currentPage:this.currentPage,totalPages:this.totalPages,totalRecords:this.totalRecords})}catch(a){console.error("[ProjectsDataSource] Fetch Error:",a),this.records=[],this.totalPages=1,this.totalRecords=0,this.onError&&this.onError(a)}}setSearch(e){this.searchTerm=e||"",this.loadPage(1)}reload(){this.loadPage(this.currentPage)}updateRecord(e,t){const s=this.records.findIndex(a=>String(a.id)===String(e));s!==-1&&(this.records[s]={...this.records[s],...t})}deleteRecord(e){this.records=this.records.filter(t=>String(t.id)!==String(e))}destroy(){this.records=[]}}class lr{constructor({schema:e,onEdit:t,onDelete:s,onSelect:a}){this.schema=e,this.container=null,this.records=[],this.onEdit=t,this.onDelete=s,this.onSelect=a}mount(e){this.container=e}render(e=[]){if(!this.container)return;this.records=e;const t='<svg viewBox="0 0 24 24" width="18" height="18"><path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25z"/></svg>',s='<svg viewBox="0 0 24 24" width="18" height="18"><path d="M6 7h12v12a2 2 0 0 1-2 2H8a2 2 0 0 1-2-2V7zm3-4h6l1 2H8l1-2z"/></svg>',a='<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"/></svg>';if(!e.length){this.container.innerHTML='<div style="padding:30px;text-align:center;color:#777">هیچ داده‌ای یافت نشد</div>';return}const i=xs.get("active_project_id"),n=e.map(r=>{let o="";const l=String(r.id)===String(i);try{o=gs.render(this.schema,r)}catch(c){console.error("[ProjectsRenderer] render error:",c),o='<div style="color:red">render error</div>'}return`
            <div class="project-card-wrapper ${l?"active-project":""}" data-id="${r.id}" style="${l?"border: 2px solid #3b82f6;":"border: 1px solid #e5e7eb;"} padding: 10px; border-radius: 8px; margin-bottom: 10px;">
              ${o}
              <div class="project-card-actions" style="display: flex; gap: 10px; margin-top: 10px;">
                <button class="btn-select" data-id="${r.id}" style="color: ${l?"#fbbf24":"#9ca3af"}; border: none; background: none; cursor: pointer; padding: 0;">${a}</button>
                <button class="btn-edit" data-id="${r.id}" style="border: none; background: none; cursor: pointer; padding: 0;">${t}</button>
                <button class="btn-delete" data-id="${r.id}" style="border: none; background: none; cursor: pointer; padding: 0;">${s}</button>
              </div>
            </div>
          `}).join("");this.container.innerHTML=n,this.bindEvents()}bindEvents(){this.container.querySelectorAll(".btn-edit").forEach(e=>{e.addEventListener("click",t=>{const s=t.currentTarget.dataset.id;this.onEdit&&this.onEdit(s)})}),this.container.querySelectorAll(".btn-delete").forEach(e=>{e.addEventListener("click",t=>{const s=t.currentTarget.dataset.id;this.onDelete&&this.onDelete(s)})}),this.container.querySelectorAll(".btn-select").forEach(e=>{e.addEventListener("click",t=>{const s=t.currentTarget.dataset.id;this.onSelect&&this.onSelect(s)})})}}class cr{constructor({container:e,dataSource:t}){this.container=e,this.dataSource=t,this.prevBtn=null,this.nextBtn=null,this.infoEl=null}mount(){this.container&&(this.container.innerHTML=`
        <div class="projects-pagination"
             style="display:flex;gap:10px;align-items:center;justify-content:center;margin-top:10px;">
             
          <button class="page-prev">« قبلی</button>
  
          <span class="page-info"></span>
  
          <button class="page-next">بعدی »</button>
  
        </div>
      `,this.prevBtn=this.container.querySelector(".page-prev"),this.nextBtn=this.container.querySelector(".page-next"),this.infoEl=this.container.querySelector(".page-info"),this.prevBtn.addEventListener("click",()=>{this.dataSource.currentPage>1&&this.dataSource.loadPage(this.dataSource.currentPage-1)}),this.nextBtn.addEventListener("click",()=>{this.dataSource.currentPage<this.dataSource.totalPages&&this.dataSource.loadPage(this.dataSource.currentPage+1)}))}update(){if(!this.infoEl)return;const e=this.dataSource.currentPage,t=this.dataSource.totalPages;this.infoEl.textContent=`صفحه ${e} از ${t}`,this.prevBtn&&(this.prevBtn.disabled=e<=1),this.nextBtn&&(this.nextBtn.disabled=e>=t)}destroy(){this.container=null}}class ws extends C{constructor(e={}){super(e),this.api=e.api,this.schemaLoader=new bs(this.api),this.dataSource=null,this.renderer=null,this.paginator=null,this.toolbar=null,this.modal=null,this.availableSchemas=[{id:"projects",title:"پروژه‌ها",icon:"🏢"},{id:"lands",title:"زمین‌ها",icon:"🗺️"},{id:"units",title:"واحدها",icon:"🏠"}],this.currentSlug="projects"}async render(e){await super.render(e);const t=this.ref("body");t.innerHTML=`
        <style>
            .runtime-layout-container {
                display: flex;
                height: 100%;
                background: #f9fafb;
                position: relative;
            }

            .runtime-sidebar {
                width: 240px;
                background: #fff;
                border-left: 1px solid #e5e7eb;
                transition: width 0.3s ease;
                overflow: hidden;
                flex-shrink: 0;
            }

            .runtime-sidebar.collapsed {
                width: 0;
                border: none;
            }

            .sidebar-inner {
                padding: 15px;
                width: 240px;
            }

            .schema-item {
                padding: 12px;
                margin-bottom: 8px;
                border-radius: 8px;
                cursor: pointer;
                display: flex;
                align-items: center;
                gap: 10px;
                border: 1px solid transparent;
                transition: all 0.2s;
            }

            .schema-item:hover {
                background: #f3f4f6;
                border-color: #d1d5db;
                transform: translateX(4px);
            }

            .schema-item.active {
                background: #eff6ff;
                border-color: #3b82f6;
                color: #1d4ed8;
            }

            .sidebar-toggle {
                position: absolute;
                top: 20px;
                left: 240px;
                z-index: 20;
                background: #fff;
                border: 1px solid #e5e7eb;
                border-radius: 0 8px 8px 0;
                padding: 6px 10px;
                cursor: pointer;
                transition: left 0.3s ease;
            }

            .runtime-sidebar.collapsed + .sidebar-toggle {
                left: 0;
            }
        </style>

        <div class="runtime-layout-container">
            <div class="runtime-sidebar" id="runtimeSidebar">
                <div class="sidebar-inner">
                    <h4 style="margin-bottom:16px;font-size:13px;color:#6b7280;border-bottom:1px solid #eee;padding-bottom:8px">
                        انتخاب موجودیت
                    </h4>

                    <div class="schema-switcher-list">
                        ${this.availableSchemas.map(i=>`
                            <div class="schema-item ${i.id===this.currentSlug?"active":""}"
                                 data-slug="${i.id}">
                                <span>${i.icon}</span>
                                <span style="font-weight:500">${i.title}</span>
                            </div>
                        `).join("")}
                    </div>
                </div>
            </div>

            <button class="sidebar-toggle" id="sidebarToggle">☰</button>

            <div class="runtime-main-content" style="flex:1;padding:20px;overflow-y:auto">
                <div class="projects-runtime-wrapper">
                    <div class="projects-runtime-toolbar" style="margin-bottom:12px"></div>
                    <div class="projects-runtime-list"></div>
                    <div class="projects-runtime-pagination" style="margin-top:10px"></div>
                </div>
            </div>
        </div>
        `;const s=t.querySelector("#runtimeSidebar"),a=t.querySelector("#sidebarToggle");return a.onclick=()=>{s.classList.toggle("collapsed"),a.textContent=s.classList.contains("collapsed")?"→":"☰"},t.querySelectorAll(".schema-item").forEach(i=>{i.onclick=()=>this.switchTo(i.dataset.slug)}),await this.switchTo(this.currentSlug),this}async switchTo(e){this.currentSlug=e,this.ref("body").querySelectorAll(".schema-item").forEach(s=>{s.classList.toggle("active",s.dataset.slug===e)});const t=this.ref("body").querySelector(".projects-runtime-list");t.innerHTML=`<div style="padding:40px;text-align:center;color:#9ca3af">
                در حال بارگذاری ${e}...
             </div>`;try{const s=await this.schemaLoader.load(e);this.dataSource=new or({api:this.api,endpoint:`/runtime/${e}/records`,pageSize:10}),this.renderer=new lr({schema:s,onEdit:i=>this.handleEdit(i),onDelete:i=>this.handleDelete(i),onSelect:i=>{xs.set("active_project_id",i),this.renderer.render(this.dataSource.records)}}),t.innerHTML="",this.renderer.mount(t);const a=this.ref("body").querySelector(".projects-runtime-pagination");this.paginator=new cr({container:a,dataSource:this.dataSource}),this.paginator.mount(),this.dataSource.onDataLoaded=({records:i})=>{this.renderer.render(i),this.paginator.update()},this.setupComponents(s),await this.dataSource.loadPage(1)}catch(s){console.error(s),t.innerHTML=`<div style="color:red;padding:20px">
                    خطا در بارگذاری ${e}
                 </div>`}}setupComponents(e){const t=this.ref("body").querySelector(".projects-runtime-toolbar"),s={setSearch:a=>this.dataSource.setSearch(a),reload:()=>this.dataSource.reload(),create:()=>this.handleCreate()};this.toolbar=new ys({table:s}),t.innerHTML="",this.toolbar.mount(t),this.modal=new _s({api:this.api,schema:e,onSaved:()=>this.dataSource.reload()}),this.modal.mount(document.body)}handleCreate(){var e;(e=this.modal)==null||e.open({mode:"create"})}handleEdit(e){const t=this.dataSource.records.find(s=>String(s.id)===String(e));t&&this.modal.open({mode:"edit",id:t.id,record:t})}async handleDelete(e){confirm("آیا از حذف مطمئن هستید؟")&&(await this.api.delete(`/runtime/${this.currentSlug}/records/${e}`),this.dataSource.deleteRecord(e),this.renderer.render(this.dataSource.records))}destroy(){var e,t,s,a,i,n,r,o,l,c;(t=(e=this.dataSource)==null?void 0:e.destroy)==null||t.call(e),(a=(s=this.renderer)==null?void 0:s.destroy)==null||a.call(s),(n=(i=this.paginator)==null?void 0:i.destroy)==null||n.call(i),(o=(r=this.toolbar)==null?void 0:r.destroy)==null||o.call(r),(c=(l=this.modal)==null?void 0:l.destroy)==null||c.call(l),super.destroy()}}g(ws,"title","Dynamic Runtime Explorer"),E.register("lands",ws);class $s extends C{constructor(e={}){super(e),this.api=e.api}async render(e){await super.render(e);const t=this.ref("body");try{const a=(await this.api.get("/wordpress/wp-menus")).items||[];t.innerHTML=`
                <div class="wp-menus-wrapper" style="padding: 15px;">
                    ${a.map(i=>`
                        <div class="menu-container" style="margin-bottom: 10px; border: 1px solid #ddd; border-radius: 5px; overflow: hidden;">
                            <div class="menu-header" style="background: #f0f0f0; padding: 12px; cursor: pointer; display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid #ddd;" 
                                 onclick="this.nextElementSibling.style.display = (this.nextElementSibling.style.display === 'none' ? 'block' : 'none')">
                                <h3 style="margin: 0; font-size: 16px;">منو: ${i.name} <small style="color: #666;">(ID: ${i.id})</small></h3>
                                <span>▼</span>
                            </div>
                            <ul class="menu-items-list" style="list-style: none; padding: 0; margin: 0; display: none; background: #fff;">
                                ${i.items.map(n=>`
                                    <li class="menu-item-row" style="padding: 10px; border-bottom: 1px solid #eee; margin-left: ${n.parent>0?"40px":"0"}">
                                        <div style="display: flex; justify-content: space-between; align-items: center;">
                                            <div>
                                                <strong>${n.title}</strong>
                                                <span style="background: #e7f3ff; color: #0073aa; padding: 2px 6px; border-radius: 4px; font-size: 0.75em; margin-left: 5px;">
                                                    ${n.type_label}
                                                </span>
                                            </div>
                                            <button class="edit-btn" data-id="${n.id}" data-title="${n.title}" data-url="${n.url}" 
                                                style="cursor: pointer; padding: 5px 10px;">ویرایش</button>
                                        </div>
                                        <div style="font-size: 0.85em; color: #555; margin-top: 5px; font-family: monospace;">
                                            URL: <a href="${n.url}" target="_blank">${n.url}</a>
                                        </div>
                                    </li>
                                `).join("")}
                            </ul>
                        </div>
                    `).join("")}
                </div>
            `,t.querySelectorAll(".edit-btn").forEach(i=>{i.addEventListener("click",n=>this.openEditModal(n.target.dataset))})}catch(s){t.innerHTML=`<div style="color: red; padding: 20px;">خطا در دریافت لیست منوها: ${s.message}</div>`}return this}openEditModal(e){const t="menu-edit-modal";document.body.insertAdjacentHTML("beforeend",`
            <div id="${t}" style="position:fixed; top:0; left:0; width:100%; height:100%; background:rgba(0,0,0,0.5); z-index:9999; display:flex; justify-content:center; align-items:center;">
                <div style="background:white; padding: 20px; border-radius: 8px; width: 400px; box-shadow: 0 2px 10px rgba(0,0,0,0.3);">
                    <h3>ویرایش: ${e.title}</h3>
                    <div style="margin-bottom: 10px;">
                        <label>عنوان:</label><br>
                        <input type="text" id="edit-title" value="${e.title}" style="width: 100%; padding: 8px;">
                    </div>
                    <div style="margin-bottom: 15px;">
                        <label>URL:</label><br>
                        <input type="text" id="edit-url" value="${e.url}" style="width: 100%; padding: 8px;">
                    </div>
                    <button id="save-btn" style="padding: 8px 15px; cursor: pointer;">ذخیره</button>
                    <button id="close-btn" style="padding: 8px 15px; cursor: pointer; margin-right: 5px;">انصراف</button>
                </div>
            </div>
        `),document.getElementById("save-btn").onclick=()=>{const s=document.getElementById("edit-title").value,a=document.getElementById("edit-url").value;this.saveMenuItem(e.id,s,a)},document.getElementById("close-btn").onclick=()=>document.getElementById(t).remove()}async saveMenuItem(e,t,s){try{(await this.api.post("/wordpress/wp-menus/update",{menu_item_id:e,title:t,url:s})).success&&(alert("بروزرسانی با موفقیت انجام شد."),document.getElementById("menu-edit-modal").remove(),this.render(this.container))}catch(a){alert("خطا در ذخیره: "+a.message)}}}g($s,"title","مدیریت منوها"),E.register("manager",$s);const Ae=["#3b82f6","#10b981","#f59e0b","#ef4444","#8b5cf6","#ec4899","#06b6d4","#84cc16","#f97316","#6366f1"];function dr(p){if(!p)return null;const e=p.split("-");return e.length>=3?e.slice(0,3).join("-"):null}const Fe={prospect:"#f59e0b",under_review:"#f97316",purchased:"#3b82f6",permitted:"#8b5cf6",under_construction:"#ef4444",completed:"#10b981",sold:"#6b7280",archived:"#d1d5db"},he={prospect:"در کشف",under_review:"در بررسی",purchased:"خریداری‌شده",permitted:"مجوزگرفته",under_construction:"در ساخت",completed:"تکمیل‌شده",sold:"فروخته‌شده"},ks={mortgage:"در رهن بانک",court_seizure:"توقیف دادگاه",tax_seizure:"توقیف مالیاتی",legal_dispute:"دعوای حقوقی",inheritance_dispute:"اختلاف وراثتی",road_plan:"در طرح معبر",national_land:"اراضی ملی",endowment:"وقف",utility_debt:"بدهی آب/برق/گاز",municipality_debt:"بدهی شهرداری",easement:"حق ارتفاق",other:"سایر"},Es={use_change:"تغییر کاربری",extra_build:"اضافه بنا",no_permit:"بدون مجوز",setback_violation:"تجاوز به حریم",floor_excess:"اضافه طبقه",other:"سایر"},Ls="gis_selected_blocks";class pr extends x{constructor(e={}){super(e),this.gisView=e.gisView??null,this._map=null,this._layers={districts:null,neighborhoods:null,parcels:null},this._mapData={districts:[],neighborhoods:[],parcels:[]},this._selected=null,this._panelOpen=!1,this._addMode=!1,this._activeFilter="all",this._layerVis={districts:!0,neighborhoods:!0,parcels:!0},this._blockMode=!1,this._selectedBlocks=new Map,this._blockColorIdx=0,this._activeLayerId=null}async template(){return`
        <div class="gis-wrap" data-ref="wrap">

            <!-- Toolbar — ردیف اول: همه در یک خط (بدون class قدیمی) -->
            <div data-ref="primaryToolbar"
                 style="display:flex;flex-direction:row;flex-wrap:nowrap;gap:6px;align-items:center;padding:6px 8px;background:#f8fafc;border-radius:8px;overflow-x:auto;white-space:nowrap;">

                <!-- 4 دکمه ناوبری بخش‌های GIS -->
                <div style="display:inline-flex;gap:2px;background:#fff;border:1.5px solid #cbd5e1;border-radius:6px;padding:2px;flex-shrink:0;">
                    <button data-section-nav="map" type="button"
                            style="padding:5px 10px;border:none;background:#3b82f6;color:#fff;border-radius:4px;font-size:12px;font-weight:700;cursor:pointer;">
                        🗺️ نقشه
                    </button>
                    <button data-section-nav="parcels" type="button"
                            style="padding:5px 10px;border:none;background:transparent;color:#475569;border-radius:4px;font-size:12px;font-weight:600;cursor:pointer;">
                        📁 پرونده‌ها
                    </button>
                    <button data-section-nav="layers" type="button"
                            style="padding:5px 10px;border:none;background:transparent;color:#475569;border-radius:4px;font-size:12px;font-weight:600;cursor:pointer;">
                        🏙️ لایه‌ها
                    </button>
                    <button data-section-nav="universal" type="button"
                            style="padding:5px 10px;border:none;background:transparent;color:#475569;border-radius:4px;font-size:12px;font-weight:600;cursor:pointer;">
                        🌐 نقشه عمومی
                    </button>
                </div>

                <!-- جستجوی کد نوسازی -->
                <div style="position:relative;display:inline-flex;align-items:center;flex-shrink:0;">
                    <input type="text" data-ref="codeSearch"
                           placeholder="🔍 کد نوسازی..."
                           dir="ltr"
                           style="padding:6px 30px 6px 8px;border:1.5px solid #cbd5e1;border-radius:6px;font-size:12px;width:170px;text-align:center;background:#fff;">
                    <button data-ref="codeSearchBtn" type="button"
                            style="position:absolute;left:2px;padding:2px 6px;border:none;background:transparent;cursor:pointer;font-size:13px;"
                            title="جستجو">🔍</button>
                    <div data-ref="codeSearchResults" style="display:none;position:absolute;top:36px;right:0;left:0;background:#fff;border:1px solid #cbd5e1;border-radius:8px;max-height:240px;overflow-y:auto;box-shadow:0 4px 12px rgba(0,0,0,.1);z-index:9999;white-space:normal;"></div>
                </div>

                <!-- انتخاب بلوک -->
                <button data-ref="blockModeBtn" type="button"
                        title="کلیک روی پارسل → نمایش همه پارسل‌های آن بلوک"
                        style="padding:6px 12px;font-weight:700;font-size:12px;border:1.5px solid #cbd5e1;border-radius:6px;background:#fff;cursor:pointer;flex-shrink:0;">
                    📦 انتخاب بلوک
                </button>

                <!-- انتخاب لایه -->
                <select data-ref="layerFilter"
                        style="padding:6px 8px;font-size:12px;background:#fff;border:1.5px solid #cbd5e1;border-radius:6px;flex-shrink:0;max-width:160px;"
                        title="فیلتر لایه">
                    <option value="">📚 همه لایه‌ها</option>
                </select>

                <!-- دکمه نمایش/مخفی drawer -->
                <button data-ref="toolsBtn" type="button"
                        style="margin-right:auto;padding:6px 12px;background:#eff6ff;border:1.5px solid #93c5fd;color:#1e40af;font-weight:700;font-size:12px;border-radius:6px;cursor:pointer;flex-shrink:0;"
                        title="نمایش بقیه ابزارها">
                    ⚙️ ابزارها
                </button>
            </div>

            <!-- Toolbar — بقیه ابزارها (آکاردیون قابل باز/بسته) -->
            <div data-ref="toolsPanel" style="display:none;background:#fff;border:1px solid #e2e8f0;border-radius:8px;margin-top:6px;overflow:hidden;">

                <!-- آکاردیون: افزودن و عملیات -->
                <details style="border-bottom:1px solid #f1f5f9;" open>
                    <summary style="padding:10px 14px;cursor:pointer;font-weight:700;font-size:13px;background:#f8fafc;">
                        ➕ افزودن / عملیات پارسل
                    </summary>
                    <div style="padding:10px;display:flex;flex-wrap:wrap;gap:6px;">
                        <button class="gis-btn gis-btn--add" data-ref="addBtn" data-perm="gis.parcels.create">
                            ➕ افزودن پارسل
                        </button>
                        <button class="gis-btn gis-btn--add-mode" data-ref="cancelAddBtn" style="display:none;">
                            ✕ لغو افزودن
                        </button>
                        <span class="gis-add-hint" data-ref="addHint" style="display:none;color:#3b82f6;font-size:12px;padding:6px;">
                            📍 روی نقشه کلیک کنید تا پارسل ثبت شود
                        </span>
                        <button class="gis-btn gis-btn--refresh" data-ref="refreshBtn">🔄 رفرش</button>
                        <button class="gis-btn" data-ref="rebuildBtn"
                                title="بازسازی index بلوک‌ها (بعد از import)" data-perm="gis.parcels.create"
                                style="background:#fef3c7;color:#92400e;">
                            🔧 بازسازی index
                        </button>
                    </div>
                </details>

                <!-- آکاردیون: فیلتر وضعیت -->
                <details style="border-bottom:1px solid #f1f5f9;">
                    <summary style="padding:10px 14px;cursor:pointer;font-weight:700;font-size:13px;background:#f8fafc;">
                        🎨 فیلتر وضعیت پارسل
                    </summary>
                    <div style="padding:10px;display:flex;flex-wrap:wrap;gap:6px;">
                        <button class="gis-filter-btn gis-filter-btn--active" data-filter="all">همه</button>
                        ${Object.entries(he).map(([e,t])=>`<button class="gis-filter-btn" data-filter="${e}"
                                style="--fc:${Fe[e]}">${t}</button>`).join("")}
                    </div>
                </details>

                <!-- آکاردیون: لایه‌های نقشه -->
                <details style="border-bottom:1px solid #f1f5f9;">
                    <summary style="padding:10px 14px;cursor:pointer;font-weight:700;font-size:13px;background:#f8fafc;">
                        🏙️ لایه‌های نمایش
                    </summary>
                    <div style="padding:10px;display:flex;flex-wrap:wrap;gap:14px;">
                        <label class="gis-layer-toggle"><input type="checkbox" data-layer="districts" checked> مناطق</label>
                        <label class="gis-layer-toggle"><input type="checkbox" data-layer="neighborhoods" checked> محلات</label>
                        <label class="gis-layer-toggle"><input type="checkbox" data-layer="parcels" checked> پارسل‌ها</label>
                    </div>
                </details>

                <!-- آکاردیون: نوع نقشه پایه -->
                <details style="border-bottom:1px solid #f1f5f9;">
                    <summary style="padding:10px 14px;cursor:pointer;font-weight:700;font-size:13px;background:#f8fafc;">
                        🗺️ نوع نقشه پایه
                    </summary>
                    <div style="padding:10px;display:flex;flex-wrap:wrap;gap:6px;">
                        <button class="gis-tile-btn gis-tile-btn--active" data-ref="tileEsri">🗺 Esri</button>
                        <button class="gis-tile-btn" data-ref="tileVoyager">🎨 Voyager</button>
                        <button class="gis-tile-btn" data-ref="tileCarto">⬜ Carto</button>
                    </div>
                </details>

                <!-- آکاردیون: آفلاین -->
                <details>
                    <summary style="padding:10px 14px;cursor:pointer;font-weight:700;font-size:13px;background:#f8fafc;">
                        📥 نقشه آفلاین
                    </summary>
                    <div style="padding:10px;">
                        <button class="gis-btn" data-ref="offlineBtn"
                                style="background:#f0fdf4;border:1.5px solid #86efac;color:#166534;">
                            📥 دانلود کاشی‌های آفلاین
                        </button>
                    </div>
                </details>
            </div>

            <!-- نوار بلوک‌های انتخابی -->
            <div class="gis-block-bar" data-ref="blockBar" style="display:none;">
                <span style="font-size:11px;color:#64748b;white-space:nowrap;">📦 بلوک‌ها:</span>
                <div class="gis-block-chips" data-ref="blockChips"></div>
                <button class="gis-btn" data-ref="clearBlocksBtn"
                    style="font-size:11px;padding:3px 10px;margin-right:auto;color:#ef4444;border-color:#fca5a5;">
                    🗑 پاک کردن همه
                </button>
            </div>

            <!-- Body: نقشه + پانل جزئیات -->
            <div class="gis-body" data-ref="body">
                <div class="gis-map-container" data-ref="mapContainer">
                    <div id="gis-leaflet-map" data-ref="mapEl"></div>
                    <div class="gis-map-loading" data-ref="mapLoading">
                        <div class="acc-spinner"></div> در حال بارگذاری نقشه...
                    </div>
                </div>
                <div class="gis-detail-panel" data-ref="detailPanel">
                    <div class="gis-detail-panel__inner" data-ref="panelInner"></div>
                </div>
            </div>

            <!-- نوار وضعیت پایین -->
            <div class="gis-statusbar">
                <span data-ref="coordsLbl">📍 مختصات: —</span>
                <span data-ref="countLbl"></span>
            </div>
        </div>`}async afterRender(){this._bindToolbar(),await this._loadLeaflet(),this._initMap(),await this._loadMapData(),await this._restoreSelectedBlocks(),await this._focusPendingBlock()}async _focusPendingBlock(){var a;let e;try{const i=sessionStorage.getItem("acc_gis_focus_block");if(!i)return;sessionStorage.removeItem("acc_gis_focus_block"),e=JSON.parse(i)}catch{return}if(!(e!=null&&e.block))return;const t=e.filters||{},s={block:e.block};t.layer_id&&(s.layer_id=t.layer_id),t.land_use&&(s.land_use=t.land_use),t.area_min!=null&&(s.area_min=t.area_min),t.area_max!=null&&(s.area_max=t.area_max),(a=t.statuses)!=null&&a.length&&(s.statuses=t.statuses.join(",")),t.def_building>=0&&(s.def_building=t.def_building),t.def_units>=0&&(s.def_units=t.def_units),t.def_shops>=0&&(s.def_shops=t.def_shops),this._activeLayerId=t.layer_id||this._activeLayerId;try{const i=await this.api.get("/gis/block-parcels",s);this._renderFilteredBlock(e.block,(i==null?void 0:i.data)??[],!!(i!=null&&i.filtered))}catch{this._toast("❌ خطا در بارگذاری بلوک","#ef4444")}}_renderFilteredBlock(e,t,s){const a=window.L;if(!a||!this._map)return;this._selectedBlocks.has(e)&&this._removeBlock(e);const i="#ef4444",n="#94a3b8",r="#3b82f6",o=a.layerGroup().addTo(this._map);this._selectedBlocks.set(e,{color:s?i:r,layerGroup:o,parcels:t});let l=0;t.forEach(h=>{if(!h.lat||!h.lng)return;const u=parseInt(h.is_match)===1;u&&l++;const f=s&&u,m=s?u?i:n:r,b=s?u?.95:.3:.85;if(h.geometry)try{const y=typeof h.geometry=="string"?JSON.parse(h.geometry):h.geometry;a.geoJSON(y,{style:{color:m,weight:f?2.5:1,fillColor:m,fillOpacity:b*.3}}).addTo(o)}catch{}const v=a.circleMarker([parseFloat(h.lat),parseFloat(h.lng)],{radius:f?9:6,fillColor:m,color:"#fff",weight:f?2.5:1.5,fillOpacity:b});v.bindTooltip(`<b>${h.code||"—"}</b><br>بلوک: ${e}`+(s?u?"<br>✅ مطابق فیلتر":"<br>— خارج از فیلتر":""),{direction:"top",offset:[0,-8]}),v.on("click",()=>this._openParcelPanel(h)),v.addTo(o)}),this._updateBlockBar(),this._saveSelectedBlocks();const c=t.map(h=>parseFloat(h.lat)).filter(h=>!isNaN(h)),d=t.map(h=>parseFloat(h.lng)).filter(h=>!isNaN(h));c.length&&this._map.fitBounds(a.latLngBounds([Math.min(...c),Math.min(...d)],[Math.max(...c),Math.max(...d)]),{padding:[40,40],maxZoom:18}),this._toast(s?`✅ بلوک ${e}: ${l} مطابق از ${t.length}`:`📦 بلوک ${e}: ${t.length} پارسل`,s?i:r)}async _restoreSelectedBlocks(){try{const e=await this.api.get(`/user/prefs/${Ls}`),t=Array.isArray(e==null?void 0:e.data)?e.data:[];if(!t.length)return;this._toast(`🔄 بازیابی ${t.length} بلوک قبلی...`,"#6366f1");for(const s of t)try{const a={block:s,per_page:500};this._activeLayerId&&(a.layer_id=this._activeLayerId);const i=await this.api.get("/gis/parcels",a),n=(i==null?void 0:i.data)??[];n.length&&this._renderBlockData(s,n,!0)}catch{}}catch{}}async _saveSelectedBlocks(){try{const e=[...this._selectedBlocks.keys()];await this.api.put(`/user/prefs/${Ls}`,{value:e})}catch(e){console.warn("saveSelectedBlocks failed",e)}}async _loadLeaflet(){var i;if(window.L)return;const e=n=>{if(document.querySelector('link[href*="leaflet"]'))return;const r=document.createElement("link");r.rel="stylesheet",r.href=n,document.head.appendChild(r)},t=n=>new Promise((r,o)=>{const l=document.createElement("script");l.src=n,l.onload=r,l.onerror=o,document.head.appendChild(l)}),s=(((i=window.ACC_CONFIG)==null?void 0:i.pluginUrl)??"").replace(/\/+$/,""),a=s?`${s}/assets/vendor/leaflet`:"/wp-content/plugins/acc-engine/assets/vendor/leaflet";e(`${a}/leaflet.css`),await t(`${a}/leaflet.js`)}_initMap(){var n;const e=window.L,t=this.ref("mapEl");if(!t||!e)return;this.ref("mapLoading").style.display="none",this._map=e.map(t,{zoomControl:!0,attributionControl:!0,maxZoom:19}).setView([29.5926,52.5836],13);const a=(((n=window.ACC_CONFIG)==null?void 0:n.pluginUrl)??"").replace(/\/+$/,"")||"/wp-content/plugins/acc-engine",i=`${a}/assets/vendor/leaflet/tiles/blank.png`;this._tileLayers={esri:e.tileLayer(`${a}/assets/vendor/leaflet/tiles_esri/{z}/{x}/{y}.png`,{attribution:"© Esri",minZoom:10,maxZoom:19,maxNativeZoom:16,errorTileUrl:i}),voyager:e.tileLayer(`${a}/assets/vendor/leaflet/tiles_osm/{z}/{x}/{y}.png`,{attribution:"© CartoDB Voyager",minZoom:10,maxZoom:19,maxNativeZoom:16,errorTileUrl:i}),carto:e.tileLayer(`${a}/assets/vendor/leaflet/tiles/{z}/{x}/{y}.png`,{attribution:"© CartoDB",minZoom:10,maxZoom:19,maxNativeZoom:16,errorTileUrl:i})},this._activeTileKey="esri",this._tileLayers.esri.addTo(this._map),this._layers.districts=e.layerGroup().addTo(this._map),this._layers.neighborhoods=e.layerGroup().addTo(this._map),this._layers.parcels=e.layerGroup().addTo(this._map),this._map.on("mousemove",r=>{const o=this.ref("coordsLbl");o&&(o.textContent=`📍 ${r.latlng.lat.toFixed(5)} , ${r.latlng.lng.toFixed(5)}`)}),this._map.on("click",r=>{this._addMode?this._openAddParcelModal(r.latlng.lat,r.latlng.lng):this._blockMode&&this._loadBlockByClick(r.latlng.lat,r.latlng.lng)})}async _loadMapData(){try{const e=await this.api.get("/gis/map-data");this._mapData=e??{districts:[],neighborhoods:[],parcels:[]},this._renderAll(),this._updateCountLabel()}catch{this._toast("خطا در بارگذاری نقشه","#ef4444")}}_renderAll(){this._renderDistricts(),this._renderNeighborhoods(),this._renderParcels()}_renderDistricts(){const e=window.L;!e||!this._layers.districts||(this._layers.districts.clearLayers(),this._mapData.districts.forEach(t=>{if(t.geometry)try{const s=typeof t.geometry=="string"?JSON.parse(t.geometry):t.geometry;e.geoJSON(s,{style:{color:t.color||"#3b82f6",weight:2.5,fillOpacity:.06,fillColor:t.color||"#3b82f6"}}).bindTooltip(`<b>${t.name}</b>${t.assigned_user_name?"<br>"+t.assigned_user_name:""}`,{sticky:!0}).addTo(this._layers.districts)}catch{}}))}_renderNeighborhoods(){const e=window.L;!e||!this._layers.neighborhoods||(this._layers.neighborhoods.clearLayers(),this._mapData.neighborhoods.forEach(t=>{if(t.geometry)try{const s=typeof t.geometry=="string"?JSON.parse(t.geometry):t.geometry,a=t.development_trend==="growing"?"#10b981":t.development_trend==="declining"?"#ef4444":"#6b7280";e.geoJSON(s,{style:{color:a,weight:1.5,fillOpacity:.04,dashArray:"4 4"}}).bindTooltip(`<b>${t.name}</b>${t.assigned_user_name?"<br>"+t.assigned_user_name:""}`,{sticky:!0}).addTo(this._layers.neighborhoods)}catch{}}))}_renderParcels(){const e=window.L;if(!e||!this._layers.parcels)return;this._layers.parcels.clearLayers(),(this._activeFilter==="all"?this._mapData.parcels:this._mapData.parcels.filter(s=>s.status===this._activeFilter)).forEach(s=>{if(!s.lat||!s.lng)return;const a=Fe[s.status]||"#94a3b8",i=parseInt(s.critical_issues)>0,n=e.circleMarker([parseFloat(s.lat),parseFloat(s.lng)],{radius:i?10:8,fillColor:a,color:i?"#dc2626":"#fff",weight:i?3:1.5,opacity:1,fillOpacity:.85});n.bindTooltip(this._parcelTooltip(s),{direction:"top",offset:[0,-8]}),n.on("click",()=>{this._blockMode?this._selectBlock(dr(s.code),s):this._openParcelPanel(s)}),s.locked_by_name&&n.setStyle({dashArray:"4 4",color:"#f59e0b",weight:2.5}),n.addTo(this._layers.parcels)}),this._updateCountLabel()}_parcelTooltip(e){parseInt(e.total_issues);const t=parseInt(e.critical_issues)||0;return`
            <div style="min-width:160px;font-family:inherit;direction:rtl;">
                <div style="font-weight:700;font-size:13px;color:#1e293b;margin-bottom:4px;">
                    ${e.code?`پلاک ${e.code}`:"پارسل #"+e.id}
                </div>
                ${e.district_name?`<div style="font-size:11px;color:#64748b;">${e.district_name} — ${e.neighborhood_name||""}</div>`:""}
                <div style="margin-top:4px;">
                    <span style="background:${Fe[e.status]};color:#fff;border-radius:5px;padding:1px 7px;font-size:11px;font-weight:600;">
                        ${he[e.status]||e.status}
                    </span>
                </div>
                ${t>0?`<div style="color:#dc2626;font-size:11px;margin-top:3px;">⚠️ ${t} مشکل بحرانی</div>`:""}
                ${e.locked_by_name?`<div style="color:#d97706;font-size:11px;margin-top:2px;">🔒 در دست ${e.locked_by_name}</div>`:""}
            </div>`}async _openParcelPanel(e){this._selected={type:"parcel",data:e},this._showPanelLoading();try{const t=await this.api.get(`/gis/parcels/${e.id}`),s=t==null?void 0:t.data;if(!s)return;this._selected.data=s,this._renderParcelPanel(s)}catch{this._toast("خطا در بارگذاری پرونده","#ef4444")}}_showPanelLoading(){const e=this.ref("detailPanel"),t=this.ref("panelInner");this._panelOpen||(e.classList.add("gis-detail-panel--open"),this._panelOpen=!0,setTimeout(()=>{var s;return(s=this._map)==null?void 0:s.invalidateSize()},320)),t.innerHTML='<div class="gis-panel-loading"><div class="acc-spinner"></div></div>'}_closePanel(){this.ref("detailPanel").classList.remove("gis-detail-panel--open"),this._panelOpen=!1,this._selected=null,setTimeout(()=>{var e;return(e=this._map)==null?void 0:e.invalidateSize()},320)}_renderParcelPanel(e){const t=e.score||{score:0,level:"risky"},s={good:"#10b981",moderate:"#f59e0b",risky:"#ef4444"}[t.level]||"#6b7280",a=e.land||{};e.building,e.use;const i=e.issues||[];e.commissions,e.owners,e.history;const n=i.filter(l=>l.status==="active"),r=n.filter(l=>l.severity==="critical").length,o=n.filter(l=>l.severity==="warning").length;this.ref("panelInner").innerHTML=`
            <!-- هدر پانل -->
            <div class="gis-panel-header">
                <div class="gis-panel-header__info">
                    <div class="gis-panel-title">
                        ${e.code?`پلاک ${this.escape(e.code)}/${this.escape(e.sub_code||"")}`:`پارسل #${e.id}`}
                    </div>
                    <div class="gis-panel-sub">
                        ${e.district_name||""} ${e.neighborhood_name?"← "+e.neighborhood_name:""}
                    </div>
                </div>
                <div style="display:flex;gap:6px;align-items:center;">
                    <div class="gis-score-badge" style="background:${s}">
                        ${t.score}<span style="font-size:10px;">/۱۰۰</span>
                    </div>
                    <button class="gis-panel-close" data-ref="panelCloseBtn">✕</button>
                </div>
            </div>

            <!-- وضعیت -->
            <div class="gis-panel-status-row">
                <span class="gis-status-dot" style="background:${Fe[e.status]||"#94a3b8"}"></span>
                <span style="font-weight:700;font-size:13px;">${he[e.status]||e.status}</span>
                ${e.locked_by_name?`<span class="gis-lock-badge">🔒 ${this.escape(e.locked_by_name)}</span>`:""}
                ${r>0?`<span class="gis-issue-badge gis-issue-badge--critical">⚠️ ${r} بحرانی</span>`:""}
                ${o>0?`<span class="gis-issue-badge gis-issue-badge--warning">⚡ ${o} هشدار</span>`:""}
            </div>

            <!-- تب‌ها -->
            <div class="gis-panel-tabs" data-ref="panelTabs">
                <button class="gis-panel-tab gis-panel-tab--active" data-tab="land">📍 زمین</button>
                <button class="gis-panel-tab" data-tab="building">🏛️ ساختمان</button>
                <button class="gis-panel-tab" data-tab="ownership">👤 مالکیت</button>
                <button class="gis-panel-tab" data-tab="use">🏷️ کاربری</button>
                <button class="gis-panel-tab" data-tab="issues">⚠️ مشکلات${r+o>0?` (${r+o})`:""}</button>
                <button class="gis-panel-tab" data-tab="score">📊 کارنامه</button>
            </div>

            <!-- محتوای تب‌ها -->
            <div class="gis-panel-body" data-ref="panelBody">
                ${this._renderTabLand(a,e)}
            </div>

            <!-- اکشن‌ها -->
            <div class="gis-panel-actions">
                <button class="gis-btn gis-btn--primary" data-ref="editParcelBtn">✏️ ویرایش</button>
                <button class="gis-btn gis-btn--secondary" data-ref="lockBtn">
                    ${e.locked_by_name?"🔓 آزاد کردن":"🔒 رزرو"}
                </button>
                <button class="gis-btn" data-ref="commissionBtn" style="background:#fef3c7;color:#92400e;border:1.5px solid #fcd34d;">
                    🔨 کمیسیون ۱۰۰
                </button>
                <button class="gis-btn gis-btn--success" data-ref="createProjectBtn">🏗️ ایجاد پروژه</button>
                ${this.can("melk.cases.create")?'<button class="gis-btn" data-ref="melkCaseBtn" style="background:#312e81;color:#fff;border:none;">🏛️ پرونده ملک</button>':""}
            </div>
        `,this.ref("panelInner").querySelectorAll("[data-ref]").forEach(l=>{this.refs[l.dataset.ref]=l}),this.on(this.ref("panelCloseBtn"),"click",()=>this._closePanel()),this.ref("panelTabs").querySelectorAll(".gis-panel-tab").forEach(l=>{l.addEventListener("click",()=>{this.ref("panelTabs").querySelectorAll(".gis-panel-tab").forEach(c=>c.classList.remove("gis-panel-tab--active")),l.classList.add("gis-panel-tab--active"),this.ref("panelBody").innerHTML=this._renderTabContent(l.dataset.tab,e),this._bindTabActions(l.dataset.tab,e)})}),this.on(this.ref("editParcelBtn"),"click",()=>this._openEditParcelModal(e)),this.on(this.ref("lockBtn"),"click",()=>this._toggleLock(e)),this.on(this.ref("createProjectBtn"),"click",()=>this._openCreateProjectModal(e)),this.ref("melkCaseBtn")&&this.on(this.ref("melkCaseBtn"),"click",()=>{const l="/acc-engine/";sessionStorage.setItem("acc_melk_create_parcel",JSON.stringify({parcel_id:e.id,code:e.code,district_id:e.district_id,neighborhood_id:e.neighborhood_id,block_code:e.block_code})),window.location.href=l+"melk.php"}),this.on(this.ref("commissionBtn"),"click",()=>{var c;const l=e.code;if(!l){this._toast("این پارسل کد نوسازی ندارد","#f59e0b");return}sessionStorage.setItem("acc_commission_pending_code",l),(c=this.eventBus)==null||c.emit("tab:open",{key:"commission",params:{code:l}})}),this._bindTabActions("land",e)}_renderTabContent(e,t){switch(e){case"land":return this._renderTabLand(t.land||{},t);case"building":return this._renderTabBuilding(t.building||{});case"ownership":return this._renderTabOwnership(t.owners||[],t.history||[]);case"use":return this._renderTabUse(t.use||{},t);case"issues":return this._renderTabIssues(t.issues||[],t.commissions||[]);case"score":return this._renderTabScore(t.score||{});default:return""}}_bindTabActions(e,t){var s,a,i,n,r,o,l,c;e==="land"&&((s=this.ref("panelBody").querySelector('[data-action="edit-land"]'))==null||s.addEventListener("click",()=>this._openLandModal(t.id,t.land||{}))),e==="building"&&((a=this.ref("panelBody").querySelector('[data-action="edit-building"]'))==null||a.addEventListener("click",()=>this._openBuildingModal(t.id,t.building||{}))),e==="use"&&((i=this.ref("panelBody").querySelector('[data-action="edit-use"]'))==null||i.addEventListener("click",()=>this._openUseModal(t.id,t.use||{}))),e==="ownership"&&((n=this.ref("panelBody").querySelector('[data-action="add-owner"]'))==null||n.addEventListener("click",()=>this._openOwnerModal(t.id)),(r=this.ref("panelBody").querySelector('[data-action="add-history"]'))==null||r.addEventListener("click",()=>this._openHistoryModal(t.id)),this.ref("panelBody").querySelectorAll("[data-edit-owner]").forEach(d=>{const h=(t.owners||[]).find(u=>String(u.id)===d.dataset.editOwner);h&&d.addEventListener("click",()=>this._openOwnerModal(t.id,h))}),this.ref("panelBody").querySelectorAll("[data-del-owner]").forEach(d=>{d.addEventListener("click",async()=>{if(confirm("آیا از حذف این مالک مطمئن هستید؟"))try{await this.api.delete(`/gis/parcels/${t.id}/owners/${d.dataset.delOwner}`),this._toast("🗑️ مالک حذف شد"),this._openParcelPanel({id:t.id})}catch(h){alert("خطا: "+((h==null?void 0:h.message)||""))}})}),this.ref("panelBody").querySelectorAll("[data-del-history]").forEach(d=>{d.addEventListener("click",async()=>{if(confirm("حذف این آیتم تاریخچه؟"))try{await this.api.delete(`/gis/parcels/${t.id}/history/${d.dataset.delHistory}`),this._toast("🗑️ تاریخچه حذف شد"),this._openParcelPanel({id:t.id})}catch(h){alert("خطا: "+((h==null?void 0:h.message)||""))}})})),e==="issues"&&((o=this.ref("panelBody").querySelector('[data-action="add-issue"]'))==null||o.addEventListener("click",()=>this._openIssueModal(t.id,t)),this.ref("panelBody").querySelectorAll("[data-del-issue]").forEach(d=>{d.addEventListener("click",async()=>{if(confirm("حذف این مشکل؟"))try{await this.api.delete(`/gis/parcels/${t.id}/issues/${d.dataset.delIssue}`),this._toast("🗑️ مشکل حذف شد"),this._openParcelPanel({id:t.id})}catch(h){alert("خطا: "+((h==null?void 0:h.message)||""))}})}),this.ref("panelBody").querySelectorAll("[data-resolve-issue]").forEach(d=>{d.addEventListener("click",async()=>{try{await this.api.put(`/gis/parcels/${t.id}/issues/${d.dataset.resolveIssue}`,{status:"resolved",resolved_at:new Date().toISOString().split("T")[0]}),this._toast("✅ مشکل به‌عنوان حل‌شده ثبت شد","#10b981"),this._openParcelPanel({id:t.id})}catch(h){alert("خطا: "+((h==null?void 0:h.message)||""))}})}),(l=this.ref("panelBody").querySelector('[data-action="toggle-resolved"]'))==null||l.addEventListener("click",d=>{const h=d.currentTarget.dataset.showing==="1";this.ref("panelBody").querySelectorAll(".gis-issue-resolved").forEach(u=>{u.style.display=h?"none":""}),d.currentTarget.dataset.showing=h?"0":"1",d.currentTarget.textContent=h?`👁️ رفع‌شده‌ها (${this.ref("panelBody").querySelectorAll(".gis-issue-resolved").length})`:"🙈 پنهان کردن رفع‌شده‌ها"}),(c=this.ref("panelBody").querySelector('[data-action="add-commission"]'))==null||c.addEventListener("click",()=>this._openCommissionModal(t.id)),this.ref("panelBody").querySelectorAll("[data-edit-commission]").forEach(d=>{const h=(t.commissions||[]).find(u=>String(u.id)===d.dataset.editCommission);h&&d.addEventListener("click",()=>this._openCommissionModal(t.id,h))}),this.ref("panelBody").querySelectorAll("[data-del-commission]").forEach(d=>{d.addEventListener("click",async()=>{if(confirm("حذف این کمیسیون ماده ۱۰۰؟"))try{await this.api.delete(`/gis/parcels/${t.id}/commissions/${d.dataset.delCommission}`),this._toast("🗑️ کمیسیون حذف شد"),this._openParcelPanel({id:t.id})}catch(h){alert("خطا: "+((h==null?void 0:h.message)||""))}})}))}_renderTabLand(e,t){const s=(o,l)=>l!=null&&l!==""?`<div class="gis-info-row"><span class="gis-info-label">${o}</span><span class="gis-info-value">${l}</span></div>`:"",a={rectangular:"مستطیل",square:"مربع",corner:"گوشه‌ای",irregular:"نامنظم",triangular:"مثلثی"},i={middle:"میانی",corner:"گوشه",end:"انتهایی"},n={private:"ملکی",endowment:"وقفی",government:"دولتی",national:"اراضی ملی"},r=e.main_street_width?e.main_street_width<6?"۲ طبقه":e.main_street_width<12?"۵ طبقه":e.main_street_width<24?"۷ طبقه":"۱۰+ طبقه":"—";return`
        <div class="gis-tab-content">
            ${s("مساحت",e.area_sqm?`${this._fmt(e.area_sqm)} م²`:null)}
            ${s("شکل زمین",a[e.shape])}
            ${s("موقعیت",i[e.position])}
            ${s("نوع مالکیت زمین",n[e.ownership_type])}
            ${e.is_national_land?'<div class="gis-alert-row gis-alert-row--critical">🔴 اراضی ملی</div>':""}
            <div class="gis-info-divider">معابر مجاور</div>
            ${s("معبر اصلی",e.main_street_width?`${e.main_street_width} متر — ${e.main_street_dir||""}`:null)}
            ${s("معبر فرعی",e.second_street_width?`${e.second_street_width} متر — ${e.second_street_dir||""}`:null)}
            ${s("طبقات مجاز (تخمین)",r)}
            <div class="gis-info-divider">ابعاد</div>
            ${s("بر شمالی",e.north_dim?e.north_dim+" م":null)}
            ${s("بر جنوبی",e.south_dim?e.south_dim+" م":null)}
            ${s("عمق شرقی",e.east_dim?e.east_dim+" م":null)}
            ${s("عمق غربی",e.west_dim?e.west_dim+" م":null)}
            ${t.address?`<div class="gis-info-divider">آدرس</div><div style="font-size:12px;color:#475569;padding:8px 0;">${this.escape(t.address)}</div>`:""}
            <div style="margin-top:12px;">
                <button class="gis-btn gis-btn--secondary gis-btn--sm" data-action="edit-land">✏️ ویرایش اطلاعات زمین</button>
            </div>
        </div>`}_renderTabBuilding(e){if(!e||!e.has_building)return`<div class="gis-empty-tab">🏗️ اطلاعات ساختمان ثبت نشده است.
                <br><button class="gis-btn gis-btn--secondary gis-btn--sm" style="margin-top:12px;" data-action="edit-building">+ ثبت اطلاعات ساختمان</button></div>`;const t=(n,r)=>r!=null&&r!==""?`<div class="gis-info-row"><span class="gis-info-label">${n}</span><span class="gis-info-value">${r}</span></div>`:"",s=e.built_year?new Date().getFullYear()-e.built_year+" سال":null,a={concrete:"بتن‌آرمه",steel:"فلزی",masonry:"آجری",other:"سایر"},i=n=>n?"✅":"❌";return`
        <div class="gis-tab-content">
            ${t("تعداد طبقات",e.floors)}
            ${t("تعداد واحدها",e.units)}
            ${t("مساحت کل بنا",e.total_area_sqm?this._fmt(e.total_area_sqm)+" م²":null)}
            ${t("سال ساخت",e.built_year)} ${t("عمر بنا",s)}
            ${t("نوع اسکلت",a[e.structure_type])}
            ${t("نما",e.facade)}
            <div class="gis-info-divider">مدارک</div>
            ${t("پروانه ساخت",e.has_permit==="yes"?"✅ دارد":e.has_permit==="no"?"❌ ندارد":"⚠️ نامعلوم")}
            ${e.permit_number?t("شماره پروانه",e.permit_number):""}
            ${t("پایان کار",e.has_completion==="yes"?"✅ دارد":e.has_completion==="no"?"❌ ندارد":"⚠️ ناقص")}
            <div class="gis-info-divider">امکانات</div>
            <div class="gis-amenities-grid">
                <span>${i(e.has_water)} آب</span><span>${i(e.has_electricity)} برق</span>
                <span>${i(e.has_gas)} گاز</span><span>${i(e.has_elevator)} آسانسور</span>
                <span>${i(e.has_parking)} پارکینگ</span><span>${i(e.has_storage)} انباری</span>
                ${e.has_basement?"<span>✅ زیرزمین</span>":""}
            </div>
        </div>`}_renderTabOwnership(e,t){const s={single_page:"تک‌برگ",old:"منگوله‌دار",qolnameh:"قولنامه‌ای",other:"سایر"},a={sale:"خرید و فروش",inheritance:"ارث",gift:"هبه",auction:"مزایده",government:"تملک دولتی",endowment:"وقف",other:"سایر"},i=e.length?e.map(r=>`
            <div class="gis-owner-card ${r.is_primary=="1"?"gis-owner-card--primary":""}">
                <div class="gis-owner-name">${this.escape(r.name)} ${r.is_primary=="1"?'<span class="gis-badge">اصلی</span>':""}</div>
                <div class="gis-owner-meta">
                    ${s[r.deed_type]||r.deed_type}
                    ${r.deed_number?" — سند "+r.deed_number:""}
                    ${r.ownership_share?" — "+r.ownership_share:""}
                </div>
                ${r.phone?`<div class="gis-owner-meta">📞 ${this.escape(r.phone)}</div>`:""}
                <div style="display:flex;gap:6px;margin-top:8px;">
                    <button class="gis-btn gis-btn--xs" data-edit-owner="${r.id}">✏️ ویرایش</button>
                    <button class="gis-btn gis-btn--xs gis-btn--danger" data-del-owner="${r.id}">🗑️ حذف</button>
                </div>
            </div>`).join(""):'<div class="gis-empty-tab">مالکی ثبت نشده است.</div>',n=t.length?'<div class="gis-timeline">'+t.map(r=>`
            <div class="gis-timeline-item">
                <div class="gis-timeline-dot"></div>
                <div class="gis-timeline-body">
                    <div class="gis-timeline-title">${this.escape(r.owner_name)}</div>
                    <div class="gis-timeline-meta">
                        ${a[r.transfer_type]||r.transfer_type}
                        ${r.transfer_date?" — "+this._jalali(r.transfer_date):""}
                        ${r.transfer_price?' — کد نوسازی: <bdi dir="ltr">'+this.escape(r.transfer_price)+"</bdi>":""}
                    </div>
                    ${r.notes?`<div class="gis-timeline-note">${this.escape(r.notes)}</div>`:""}
                    <button class="gis-btn gis-btn--xs gis-btn--danger" data-del-history="${r.id}" style="margin-top:4px;">🗑️ حذف</button>
                </div>
            </div>`).join("")+"</div>":'<div class="gis-empty-tab" style="margin-top:8px;">تاریخچه‌ای ثبت نشده.</div>';return`
        <div class="gis-tab-content">
            <div class="gis-section-title">مالکین فعلی
                <button class="gis-btn gis-btn--xs" data-action="add-owner">+ افزودن</button>
            </div>
            ${i}
            <div class="gis-section-title" style="margin-top:16px;">تاریخچه مالکیت
                <button class="gis-btn gis-btn--xs" data-action="add-history">+ افزودن</button>
            </div>
            ${n}
        </div>`}_renderTabUse(e,t){var d;const s=(h,u,f="")=>u!=null&&u!==""?`<div class="gis-info-row">
                   <span class="gis-info-label">${h}</span>
                   <span class="gis-info-value">${u}${f?`<span style="font-size:10px;color:#94a3b8;margin-right:4px;">${f}</span>`:""}</span>
               </div>`:"",a=!e||!e.current_use&&!e.approved_use&&!e.density_pct,i=e.current_use&&e.approved_use&&e.current_use.trim()!==e.approved_use.trim(),n=parseFloat(((d=t.land)==null?void 0:d.area_sqm)||0),r=parseFloat(e.density_pct||0),o=parseFloat(e.coverage_pct||0),l=e.max_build_area?parseFloat(e.max_build_area):n>0&&r>0?n*r/100:null,c=n>0&&o>0?n*o/100:null;return a?`
            <div class="gis-tab-content">
                <div class="gis-empty-tab">
                    🏷️ اطلاعات کاربری ثبت نشده است.
                    <br>
                    <button class="gis-btn gis-btn--secondary gis-btn--sm" style="margin-top:12px;"
                        data-action="edit-use">+ ثبت اطلاعات کاربری</button>
                </div>
            </div>`:`
        <div class="gis-tab-content">

            ${i?`
            <div class="gis-alert-row gis-alert-row--critical" style="margin-bottom:12px;">
                ⚠️ تعارض کاربری: کاربری فعلی با مصوب طرح تفصیلی مغایرت دارد
            </div>`:""}

            <div class="gis-info-divider">کاربری</div>
            ${s("کاربری فعلی",e.current_use?this.escape(e.current_use):null)}
            ${s("کاربری مصوب (طرح تفصیلی)",e.approved_use?this.escape(e.approved_use):null,i?"⚠️ مغایرت":e.approved_use?"✅ مطابقت":"")}

            <div class="gis-info-divider">ضوابط ساختمانی</div>
            ${s("تراکم ساختمانی مجاز",r>0?`${r}%`:null)}
            ${s("سطح اشغال مجاز",o>0?`${o}%`:null)}
            ${s("حداکثر طبقات مجاز",e.max_floors||null)}

            ${l||c?`
            <div class="gis-info-divider">محاسبات اتوماتیک</div>
            ${l?`
            <div class="gis-info-row" style="background:#f0fdf4;border-radius:8px;padding:8px 12px;">
                <span class="gis-info-label">حداکثر زیربنای مجاز</span>
                <span class="gis-info-value" style="color:#166534;font-weight:800;font-size:15px;">
                    ${this._fmt(l)} م²
                </span>
            </div>`:""}
            ${c?`
            <div class="gis-info-row" style="background:#eff6ff;border-radius:8px;padding:8px 12px;">
                <span class="gis-info-label">سطح اشغال زمین</span>
                <span class="gis-info-value" style="color:#1e40af;font-weight:700;">
                    ${this._fmt(c)} م²
                </span>
            </div>`:""}
            `:""}

            <div style="margin-top:14px;">
                <button class="gis-btn gis-btn--secondary gis-btn--sm" data-action="edit-use">
                    ✏️ ویرایش اطلاعات کاربری
                </button>
            </div>
        </div>`}_openUseModal(e,t={}){var c,d,h;const a=["مسکونی","تجاری","اداری","صنعتی","آموزشی","درمانی","فرهنگی","ورزشی","باغی","مختلط مسکونی-تجاری"].map(u=>`<option value="${u}">`).join(""),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
            <div class="acc-modal" style="max-width:460px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">🏷️ اطلاعات کاربری</div>

                <datalist id="use-suggestions">${a}</datalist>

                <form>
                    <div class="acc-form-group">
                        <label>کاربری فعلی واقعی</label>
                        <input name="current_use" list="use-suggestions"
                            value="${this.escape(t.current_use||"")}"
                            placeholder="مثلاً: مسکونی، تجاری...">
                    </div>
                    <div class="acc-form-group">
                        <label>کاربری مصوب (طرح تفصیلی)</label>
                        <input name="approved_use" list="use-suggestions"
                            value="${this.escape(t.approved_use||"")}"
                            placeholder="کاربری که شهرداری تعیین کرده">
                    </div>

                    <div class="gis-info-divider">ضوابط ساختمانی</div>

                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>تراکم مجاز (%)</label>
                            <input name="density_pct" type="number" min="0" max="1000" step="5"
                                value="${t.density_pct||""}" placeholder="مثلاً: 240">
                        </div>
                        <div class="acc-form-group">
                            <label>سطح اشغال (%)</label>
                            <input name="coverage_pct" type="number" min="0" max="100" step="5"
                                value="${t.coverage_pct||""}" placeholder="مثلاً: 60">
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>حداکثر طبقات مجاز</label>
                        <input name="max_floors" type="number" min="0" max="50"
                            value="${t.max_floors||""}">
                    </div>

                    <div style="background:#f0fdf4;border-radius:8px;padding:10px 12px;font-size:12px;color:#166534;margin:10px 0;" id="use-calc-preview">
                        💡 حداکثر زیربنا پس از ذخیره محاسبه می‌شود
                    </div>

                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(i);const n=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",n),i.querySelector('[data-action="cancel"]').addEventListener("click",n),i.addEventListener("click",u=>{u.target===i&&n()});const r=parseFloat(((h=(d=(c=this._selected)==null?void 0:c.data)==null?void 0:d.land)==null?void 0:h.area_sqm)||0),o=i.querySelector("#use-calc-preview"),l=()=>{const u=parseFloat(i.querySelector('[name="density_pct"]').value)||0,f=parseFloat(i.querySelector('[name="coverage_pct"]').value)||0;if(r>0&&(u>0||f>0)){const m=[];u>0&&m.push(`حداکثر زیربنا: <b>${this._fmt(r*u/100)} م²</b>`),f>0&&m.push(`سطح اشغال: <b>${this._fmt(r*f/100)} م²</b>`),o.innerHTML="💡 "+m.join(" | ")}else o.textContent=r>0?"💡 تراکم یا سطح اشغال را وارد کنید":"💡 ابتدا مساحت زمین را در دفتر زمین ثبت کنید"};i.querySelector('[name="density_pct"]').addEventListener("input",l),i.querySelector('[name="coverage_pct"]').addEventListener("input",l),l(),i.querySelector("form").addEventListener("submit",async u=>{u.preventDefault();const f=Object.fromEntries(new FormData(u.target).entries());["density_pct","coverage_pct","max_floors"].forEach(b=>{f[b]||delete f[b]});const m=u.target.querySelector('[type="submit"]');m.disabled=!0,m.textContent="در حال ذخیره...";try{await this.api.put(`/gis/parcels/${e}/use`,f),n(),this._toast("✅ اطلاعات کاربری ذخیره شد"),this._openParcelPanel({id:e})}catch(b){alert("خطا: "+((b==null?void 0:b.message)||"")),m.disabled=!1,m.textContent="ذخیره"}})}_renderTabIssues(e,t){const s={critical:"#fee2e2",warning:"#fef3c7",info:"#eff6ff"},a={critical:"#ef4444",warning:"#f59e0b",info:"#3b82f6"},i={active:"فعال",resolved:"رفع‌شده",partial:"جزئی"},n={demolish:"🔴 تخریب",fine:"🟡 جریمه",conditional:"🟠 مشروط"},r={pending:"در انتظار",executed:"اجرا شده",not_executed:"اجرا نشده",appealed:"اعتراض"},o=e.filter(u=>u.status==="active"),l=e.filter(u=>u.status!=="active"),c=o.length?o.map(u=>`
            <div class="gis-issue-card" style="background:${s[u.severity]||"#f8fafc"};border-right:3px solid ${a[u.severity]||"#cbd5e1"}">
                <div class="gis-issue-title">${this.escape(u.title)}</div>
                <div class="gis-issue-meta">${ks[u.type]||u.type} ${u.amount?" — "+this._fmt(u.amount)+" ﷼":""}</div>
                ${u.description?`<div class="gis-issue-desc">${this.escape(u.description)}</div>`:""}
                <div style="display:flex;gap:6px;margin-top:6px;">
                    <button class="gis-btn gis-btn--xs" style="background:#dcfce7;color:#166534;border:1px solid #86efac;"
                        data-resolve-issue="${u.id}">✅ حل شد</button>
                    <button class="gis-btn gis-btn--xs gis-btn--danger" data-del-issue="${u.id}">🗑️ حذف</button>
                </div>
            </div>`).join(""):'<div class="gis-empty-tab" style="padding:12px 0;">مشکل فعالی ثبت نشده ✅</div>',d=l.length?l.map(u=>`
            <div class="gis-issue-card gis-issue-resolved" style="background:#f8fafc;border-right:3px solid #cbd5e1;opacity:0.7;display:none;">
                <div class="gis-issue-title" style="text-decoration:line-through;color:#94a3b8;">${this.escape(u.title)}</div>
                <div class="gis-issue-meta" style="color:#94a3b8;">
                    ✅ ${i[u.status]||u.status}
                    ${u.resolved_at?" — "+this._jalali(u.resolved_at):""}
                </div>
            </div>`).join(""):"",h=t.length?t.map(u=>`
            <div class="gis-issue-card" style="background:#fef9c3;border-right:3px solid #eab308;">
                <div class="gis-issue-title">ماده ۱۰۰ — سال ${u.year}</div>
                <div class="gis-issue-meta">
                    ${Es[u.violation_type]||u.violation_type} |
                    ${n[u.verdict]||u.verdict} |
                    ${r[u.verdict_status]||u.verdict_status}
                    ${u.fine_amount?" — "+this._fmt(u.fine_amount)+" ﷼":""}
                </div>
                ${u.case_number?`<div class="gis-issue-meta">پرونده: ${u.case_number}</div>`:""}
                <div style="display:flex;gap:6px;margin-top:6px;">
                    <button class="gis-btn gis-btn--xs" data-edit-commission="${u.id}">✏️ ویرایش</button>
                    <button class="gis-btn gis-btn--xs gis-btn--danger" data-del-commission="${u.id}">🗑️ حذف</button>
                </div>
            </div>`).join(""):"";return`
        <div class="gis-tab-content">
            <div class="gis-section-title">مشکلات و موانع
                <button class="gis-btn gis-btn--xs" data-action="add-issue">+ افزودن</button>
                ${l.length?`<button class="gis-btn gis-btn--xs" data-action="toggle-resolved"
                    style="background:#f1f5f9;color:#64748b;" data-showing="0">
                    👁️ رفع‌شده‌ها (${l.length})</button>`:""}
            </div>
            ${c}
            ${d}
            <div class="gis-section-title" style="margin-top:16px;">کمیسیون ماده ۱۰۰
                <button class="gis-btn gis-btn--xs" data-action="add-commission">+ افزودن</button>
            </div>
            ${h||'<div class="gis-empty-tab" style="padding:8px 0;">سابقه‌ای ثبت نشده ✅</div>'}
        </div>`}_renderTabScore(e){const t={good:"#10b981",moderate:"#f59e0b",risky:"#ef4444"}[e.level]||"#6b7280",s={good:"خوب",moderate:"متوسط",risky:"پرریسک"}[e.level]||"—",a=(e.score||0)+"%";return`
        <div class="gis-tab-content">
            <div class="gis-score-display" style="border-color:${t}">
                <div class="gis-score-value" style="color:${t}">${e.score||0}</div>
                <div class="gis-score-label">${s}</div>
            </div>
            <div class="gis-score-bar-wrap">
                <div class="gis-score-bar-track">
                    <div class="gis-score-bar-fill" style="width:${a};background:${t}"></div>
                </div>
            </div>
            ${(e.warnings||[]).length?`
            <div class="gis-section-title" style="margin-top:14px;">موارد کاهش امتیاز</div>
            ${e.warnings.map(i=>`
                <div class="gis-issue-card" style="background:${i.level==="critical"?"#fee2e2":"#fef3c7"};border-right:3px solid ${i.level==="critical"?"#ef4444":"#f59e0b"}">
                    <span style="font-size:13px;">${i.level==="critical"?"🔴":"🟡"} ${this.escape(i.text)}</span>
                </div>`).join("")}`:`
            <div class="gis-empty-tab" style="margin-top:16px;color:#10b981;">✅ هیچ مشکل کاهش‌دهنده‌ای یافت نشد</div>`}
        </div>`}_openAddParcelModal(e,t){this._exitAddMode();const s='<option value="">— انتخاب —</option>'+(this._mapData.districts||[]).map(l=>`<option value="${l.id}">${this.escape(l.name)}</option>`).join(""),a=Object.entries(he).map(([l,c])=>`<option value="${l}">${c}</option>`).join(""),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
            <div class="acc-modal" style="max-width:480px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">📍 افزودن پارسل جدید</div>
                <div style="background:#f0fdf4;border-radius:8px;padding:8px 12px;font-size:12px;color:#166534;margin-bottom:14px;">
                    مختصات: ${e.toFixed(6)} , ${t.toFixed(6)}
                </div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>پلاک اصلی</label>
                            <input name="code" type="text" placeholder="مثال: ۲۳">
                        </div>
                        <div class="acc-form-group">
                            <label>پلاک فرعی</label>
                            <input name="sub_code" type="text" placeholder="مثال: ۱۴۵">
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>منطقه</label>
                            <select name="district_id" id="new-district-sel">${s}</select>
                        </div>
                        <div class="acc-form-group">
                            <label>محله</label>
                            <select name="neighborhood_id" id="new-neighborhood-sel">
                                <option value="">— ابتدا منطقه انتخاب کنید —</option>
                            </select>
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>آدرس</label>
                        <input name="address" type="text" placeholder="آدرس دقیق...">
                    </div>
                    <div class="acc-form-group">
                        <label>وضعیت</label>
                        <select name="status">${a}</select>
                    </div>
                    <div class="acc-form-group">
                        <label>کارشناس مسئول</label>
                        <input name="assigned_user_name" type="text" placeholder="نام کارشناس (اختیاری)">
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">ثبت پارسل</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(i);const n=i.querySelector("#new-district-sel"),r=i.querySelector("#new-neighborhood-sel");n.addEventListener("change",()=>{const l=parseInt(n.value),c='<option value="">— انتخاب —</option>'+(this._mapData.neighborhoods||[]).filter(d=>d.district_id==l).map(d=>`<option value="${d.id}">${this.escape(d.name)}</option>`).join("");r.innerHTML=c});const o=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",o),i.querySelector('[data-action="cancel"]').addEventListener("click",o),i.addEventListener("click",l=>{l.target===i&&o()}),i.querySelector("form").addEventListener("submit",async l=>{l.preventDefault();const c=new FormData(l.target),d=Object.fromEntries(c.entries());d.lat=e,d.lng=t,d.district_id||delete d.district_id,d.neighborhood_id||delete d.neighborhood_id,d.assigned_user_name||delete d.assigned_user_name;const h=l.target.querySelector('[type="submit"]');h.disabled=!0,h.textContent="در حال ثبت...";try{const u=await this.api.post("/gis/parcels",d);o(),this._toast("✅ پارسل با موفقیت ثبت شد"),await this._loadMapData(),u!=null&&u.id&&this._openParcelPanel({id:u.id})}catch(u){alert("خطا: "+((u==null?void 0:u.message)||"")),h.disabled=!1,h.textContent="ثبت پارسل"}})}_openEditParcelModal(e){const t='<option value="">— انتخاب —</option>'+(this._mapData.districts||[]).map(i=>`<option value="${i.id}" ${i.id==e.district_id?"selected":""}>${this.escape(i.name)}</option>`).join(""),s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
            <div class="acc-modal" style="max-width:520px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">✏️ ویرایش پارسل</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>پلاک اصلی</label>
                            <input name="code" value="${this.escape(e.code||"")}">
                        </div>
                        <div class="acc-form-group">
                            <label>پلاک فرعی</label>
                            <input name="sub_code" value="${this.escape(e.sub_code||"")}">
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>بخش ثبتی</label>
                        <input name="registry_section" value="${this.escape(e.registry_section||"")}">
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>منطقه</label>
                            <select name="district_id">${t}</select>
                        </div>
                        <div class="acc-form-group">
                            <label>وضعیت</label>
                            <select name="status">
                                ${Object.entries(he).map(([i,n])=>`<option value="${i}" ${e.status===i?"selected":""}>${n}</option>`).join("")}
                            </select>
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>آدرس</label>
                        <textarea name="address" rows="2">${this.escape(e.address||"")}</textarea>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group">
                            <label>کارشناس مسئول</label>
                            <input name="assigned_user_name" value="${this.escape(e.assigned_user_name||"")}">
                        </div>
                    </div>
                    <div class="acc-form-group">
                        <label>یادداشت</label>
                        <textarea name="notes" rows="2">${this.escape(e.notes||"")}</textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">ذخیره تغییرات</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector('[data-action="cancel"]').addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries()),r=i.target.querySelector('[type="submit"]');r.disabled=!0,r.textContent="در حال ذخیره...";try{await this.api.put(`/gis/parcels/${e.id}`,n),a(),this._toast("✅ تغییرات ذخیره شد"),await this._loadMapData(),this._openParcelPanel({id:e.id})}catch(o){alert("خطا: "+((o==null?void 0:o.message)||"")),r.disabled=!1,r.textContent="ذخیره تغییرات"}})}_openOwnerModal(e,t=null){const s=!!t,a=[["single_page","تک‌برگ"],["old","منگوله‌دار"],["qolnameh","قولنامه‌ای"],["other","سایر"]],i=o=>(t==null?void 0:t.deed_type)===o?"selected":"",n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
            <div class="acc-modal" style="max-width:420px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">👤 ${s?"ویرایش":"افزودن"} مالک</div>
                <form>
                    <div class="acc-form-group"><label>نام مالک *</label>
                        <input name="name" required value="${this.escape((t==null?void 0:t.name)||"")}">
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>کد ملی</label>
                            <input name="national_id" value="${this.escape((t==null?void 0:t.national_id)||"")}">
                        </div>
                        <div class="acc-form-group"><label>سهم (مثلاً 6/6)</label>
                            <input name="ownership_share" value="${this.escape((t==null?void 0:t.ownership_share)||"6/6")}">
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>نوع سند</label>
                            <select name="deed_type">
                                ${a.map(([o,l])=>`<option value="${o}" ${i(o)}>${l}</option>`).join("")}
                            </select>
                        </div>
                        <div class="acc-form-group"><label>شماره سند</label>
                            <input name="deed_number" value="${this.escape((t==null?void 0:t.deed_number)||"")}">
                        </div>
                    </div>
                    <div class="acc-form-group"><label>دفترخانه</label>
                        <input name="registry_office" value="${this.escape((t==null?void 0:t.registry_office)||"")}">
                    </div>
                    <div class="acc-form-group"><label>تلفن</label>
                        <input name="phone" type="tel" value="${this.escape((t==null?void 0:t.phone)||"")}">
                    </div>
                    <label style="display:flex;gap:8px;align-items:center;font-size:13px;margin:10px 0;">
                        <input type="checkbox" name="is_primary" value="1" ${(t==null?void 0:t.is_primary)=="1"?"checked":""}> مالک اصلی
                    </label>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${s?"ذخیره":"ثبت مالک"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector('[data-action="cancel"]').addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()}),n.querySelector("form").addEventListener("submit",async o=>{o.preventDefault();const l=Object.fromEntries(new FormData(o.target).entries());l.is_primary=l.is_primary?1:0,s&&(l.owner_id=t.id);const c=o.target.querySelector('[type="submit"]');c.disabled=!0;try{s?(await this.api.put(`/gis/parcels/${e}/owners/${t.id}`,l),this._toast("✅ اطلاعات مالک به‌روز شد")):(await this.api.post(`/gis/parcels/${e}/owners`,l),this._toast("✅ مالک ثبت شد")),r(),this._openParcelPanel({id:e})}catch(d){alert("خطا: "+((d==null?void 0:d.message)||"")),c.disabled=!1}})}_openIssueModal(e,t){const s=Object.entries(ks),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
            <div class="acc-modal" style="max-width:420px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">⚠️ افزودن مشکل</div>
                <form>
                    <div class="acc-form-group"><label>نوع مشکل</label>
                        <select name="type">${s.map(([n,r])=>`<option value="${n}">${r}</option>`).join("")}</select>
                    </div>
                    <div class="acc-form-group"><label>عنوان *</label><input name="title" required></div>
                    <div class="acc-form-group"><label>شدت</label>
                        <select name="severity">
                            <option value="critical">🔴 بحرانی</option>
                            <option value="warning" selected>🟡 هشدار</option>
                            <option value="info">🔵 اطلاع</option>
                        </select>
                    </div>
                    <div class="acc-form-group"><label>مبلغ (اختیاری)</label>
                        <input name="amount" type="number" min="0" placeholder="ریال">
                    </div>
                    <div class="acc-form-group"><label>توضیحات</label>
                        <textarea name="description" rows="2"></textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">ثبت مشکل</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector('[data-action="cancel"]').addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries()),o=n.target.querySelector('[type="submit"]');o.disabled=!0;try{await this.api.post(`/gis/parcels/${e}/issues`,r),i(),this._toast("⚠️ مشکل ثبت شد"),this._openParcelPanel({id:e})}catch(l){alert("خطا: "+((l==null?void 0:l.message)||"")),o.disabled=!1}})}_openCommissionModal(e,t=null){const s=!!t,a=t||{},i=Object.entries(Es),n=d=>a.violation_type===d?"selected":"",r=d=>a.verdict===d?"selected":"",o=d=>a.verdict_status===d?"selected":"",l=document.createElement("div");l.className="acc-modal-overlay",l.innerHTML=`
            <div class="acc-modal" style="max-width:420px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">🔨 ${s?"ویرایش":"ثبت"} کمیسیون ماده ۱۰۰</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>سال</label>
                            <input name="year" type="number" value="${a.year||new Date().getFullYear()}" min="1350">
                        </div>
                        <div class="acc-form-group"><label>شماره پرونده</label>
                            <input name="case_number" value="${this.escape(a.case_number||"")}" placeholder="اختیاری">
                        </div>
                    </div>
                    <div class="acc-form-group"><label>نوع تخلف</label>
                        <select name="violation_type">
                            ${i.map(([d,h])=>`<option value="${d}" ${n(d)}>${h}</option>`).join("")}
                        </select>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>رأی</label>
                            <select name="verdict">
                                <option value="fine"        ${r("fine")}>🟡 جریمه</option>
                                <option value="demolish"    ${r("demolish")}>🔴 تخریب</option>
                                <option value="conditional" ${r("conditional")}>🟠 مشروط</option>
                            </select>
                        </div>
                        <div class="acc-form-group"><label>وضعیت اجرا</label>
                            <select name="verdict_status">
                                <option value="pending"      ${o("pending")}>در انتظار</option>
                                <option value="executed"     ${o("executed")}>اجرا شده</option>
                                <option value="not_executed" ${o("not_executed")}>اجرا نشده</option>
                                <option value="appealed"     ${o("appealed")}>اعتراض</option>
                            </select>
                        </div>
                    </div>
                    <div class="acc-form-group"><label>مبلغ جریمه (ریال)</label>
                        <input name="fine_amount" type="number" min="0" value="${a.fine_amount||""}">
                    </div>
                    <div class="acc-form-group"><label>توضیحات</label>
                        <textarea name="description" rows="2">${this.escape(a.description||"")}</textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${s?"ذخیره":"ثبت"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(l);const c=()=>l.remove();l.querySelector(".acc-modal__close").addEventListener("click",c),l.querySelector('[data-action="cancel"]').addEventListener("click",c),l.addEventListener("click",d=>{d.target===l&&c()}),l.querySelector("form").addEventListener("submit",async d=>{d.preventDefault();const h=Object.fromEntries(new FormData(d.target).entries()),u=d.target.querySelector('[type="submit"]');u.disabled=!0;try{s?(await this.api.put(`/gis/parcels/${e}/commissions/${a.id}`,h),this._toast("✅ کمیسیون به‌روز شد","#eab308")):(await this.api.post(`/gis/parcels/${e}/commissions`,h),this._toast("🔨 کمیسیون ثبت شد","#eab308")),c(),this._openParcelPanel({id:e})}catch(f){alert("خطا: "+((f==null?void 0:f.message)||"")),u.disabled=!1}})}_openHistoryModal(e){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
            <div class="acc-modal" style="max-width:400px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">📜 ثبت تاریخچه مالکیت</div>
                <form>
                    <div class="acc-form-group"><label>نام مالک قبلی *</label><input name="owner_name" required></div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>نوع انتقال</label>
                            <select name="transfer_type">
                                <option value="sale">خرید و فروش</option>
                                <option value="inheritance">ارث</option>
                                <option value="gift">هبه</option>
                                <option value="auction">مزایده</option>
                                <option value="government">تملک دولتی</option>
                                <option value="other">سایر</option>
                            </select>
                        </div>
                        <div class="acc-form-group"><label>تاریخ انتقال</label>
                            <input name="transfer_date" type="date">
                        </div>
                    </div>
                    <div class="acc-form-group"><label>کد نوسازی</label>
                        <input name="transfer_price" type="text" placeholder="مثلاً: 10-2-162-7-0-0-0">
                    </div>
                    <div class="acc-form-group"><label>یادداشت</label>
                        <textarea name="notes" rows="2"></textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">ثبت</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector('[data-action="cancel"]').addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries()),n=a.target.querySelector('[type="submit"]');n.disabled=!0;try{await this.api.post(`/gis/parcels/${e}/history`,i),s(),this._toast("✅ تاریخچه ثبت شد"),this._openParcelPanel({id:e})}catch(r){alert("خطا: "+((r==null?void 0:r.message)||"")),n.disabled=!1}})}_openLandModal(e,t={}){const s=n=>["north","south","east","west"].map(r=>`<option value="${r}" ${t[n]===r?"selected":""}>${{north:"شمالی",south:"جنوبی",east:"شرقی",west:"غربی"}[r]}</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
            <div class="acc-modal" style="max-width:520px;max-height:90vh;overflow-y:auto;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">📍 اطلاعات زمین</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>مساحت (م²) *</label>
                            <input name="area_sqm" type="number" min="0" step="0.01" value="${t.area_sqm||""}" required>
                        </div>
                        <div class="acc-form-group"><label>شکل زمین</label>
                            <select name="shape">
                                <option value="rectangular" ${t.shape==="rectangular"?"selected":""}>مستطیل</option>
                                <option value="square"      ${t.shape==="square"?"selected":""}>مربع</option>
                                <option value="corner"      ${t.shape==="corner"?"selected":""}>گوشه‌ای</option>
                                <option value="irregular"   ${t.shape==="irregular"?"selected":""}>نامنظم</option>
                                <option value="triangular"  ${t.shape==="triangular"?"selected":""}>مثلثی</option>
                            </select>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>موقعیت پلاک</label>
                            <select name="position">
                                <option value="middle" ${t.position==="middle"?"selected":""}>میانی</option>
                                <option value="corner" ${t.position==="corner"?"selected":""}>گوشه</option>
                                <option value="end"    ${t.position==="end"?"selected":""}>انتهایی</option>
                            </select>
                        </div>
                        <div class="acc-form-group"><label>نوع مالکیت زمین</label>
                            <select name="ownership_type">
                                <option value="private"    ${t.ownership_type==="private"?"selected":""}>ملکی</option>
                                <option value="endowment"  ${t.ownership_type==="endowment"?"selected":""}>وقفی</option>
                                <option value="government" ${t.ownership_type==="government"?"selected":""}>دولتی</option>
                                <option value="national"   ${t.ownership_type==="national"?"selected":""}>اراضی ملی</option>
                            </select>
                        </div>
                    </div>
                    <div style="margin:8px 0;">
                        <label style="display:flex;gap:8px;align-items:center;font-size:13px;color:#dc2626;">
                            <input type="checkbox" name="is_national_land" value="1" ${t.is_national_land=="1"?"checked":""}>
                            🔴 اراضی ملی (کاهش ۵۰ امتیاز)
                        </label>
                    </div>
                    <div class="gis-info-divider">معابر مجاور</div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>عرض معبر اصلی (متر)</label>
                            <input name="main_street_width" type="number" min="0" step="0.5" value="${t.main_street_width||""}">
                        </div>
                        <div class="acc-form-group"><label>جهت معبر اصلی</label>
                            <select name="main_street_dir"><option value="">—</option>${s("main_street_dir")}</select>
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>عرض معبر فرعی (متر)</label>
                            <input name="second_street_width" type="number" min="0" step="0.5" value="${t.second_street_width||""}">
                        </div>
                        <div class="acc-form-group"><label>جهت معبر فرعی</label>
                            <select name="second_street_dir"><option value="">—</option>${s("second_street_dir")}</select>
                        </div>
                    </div>
                    <div class="gis-info-divider">ابعاد (متر)</div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>بر شمالی</label>
                            <input name="north_dim" type="number" step="0.01" value="${t.north_dim||""}">
                        </div>
                        <div class="acc-form-group"><label>بر جنوبی</label>
                            <input name="south_dim" type="number" step="0.01" value="${t.south_dim||""}">
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>عمق شرقی</label>
                            <input name="east_dim" type="number" step="0.01" value="${t.east_dim||""}">
                        </div>
                        <div class="acc-form-group"><label>عمق غربی</label>
                            <input name="west_dim" type="number" step="0.01" value="${t.west_dim||""}">
                        </div>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector('[data-action="cancel"]').addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());r.is_national_land=r.is_national_land?1:0;const o=n.target.querySelector('[type="submit"]');o.disabled=!0,o.textContent="در حال ذخیره...";try{await this.api.put(`/gis/parcels/${e}/land`,r),i(),this._toast("✅ اطلاعات زمین ذخیره شد"),this._openParcelPanel({id:e})}catch(l){alert("خطا: "+((l==null?void 0:l.message)||"")),o.disabled=!1,o.textContent="ذخیره"}})}_openBuildingModal(e,t={}){const s=(o,l)=>["yes","no","unknown"].map(c=>`<option value="${c}" ${l===c?"selected":""}>${{yes:"✅ دارد",no:"❌ ندارد",unknown:"⚠️ نامعلوم"}[c]}</option>`).join(""),a=(o,l)=>["yes","no","partial"].map(c=>`<option value="${c}" ${l===c?"selected":""}>${{yes:"✅ دارد",no:"❌ ندارد",partial:"🟡 ناقص"}[c]}</option>`).join(""),i=(o,l,c)=>`<label style="display:flex;gap:6px;align-items:center;font-size:13px;">
                <input type="checkbox" name="${o}" value="1" ${l?"checked":""}> ${c}
             </label>`,n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
            <div class="acc-modal" style="max-width:520px;max-height:90vh;overflow-y:auto;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">🏛️ اطلاعات ساختمان</div>
                <form>
                    <div style="margin-bottom:12px;">
                        ${i("has_building",t.has_building,"🏗️ این پلاک دارای ساختمان است")}
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>تعداد طبقات</label>
                            <input name="floors" type="number" min="0" value="${t.floors||""}">
                        </div>
                        <div class="acc-form-group"><label>تعداد واحدها</label>
                            <input name="units" type="number" min="0" value="${t.units||""}">
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>مساحت کل بنا (م²)</label>
                            <input name="total_area_sqm" type="number" min="0" step="0.1" value="${t.total_area_sqm||""}">
                        </div>
                        <div class="acc-form-group"><label>سال ساخت</label>
                            <input name="built_year" type="number" min="1300" max="${new Date().getFullYear()}" value="${t.built_year||""}">
                        </div>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>نوع اسکلت</label>
                            <select name="structure_type">
                                <option value="concrete" ${t.structure_type==="concrete"?"selected":""}>بتن‌آرمه</option>
                                <option value="steel"    ${t.structure_type==="steel"?"selected":""}>فلزی</option>
                                <option value="masonry"  ${t.structure_type==="masonry"?"selected":""}>آجری</option>
                                <option value="other"    ${t.structure_type==="other"?"selected":""}>سایر</option>
                            </select>
                        </div>
                        <div class="acc-form-group"><label>نما</label>
                            <input name="facade" type="text" value="${this.escape(t.facade||"")}" placeholder="مثلاً سنگ، آجر، کامپوزیت">
                        </div>
                    </div>
                    <div class="gis-info-divider">مدارک</div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>پروانه ساخت</label>
                            <select name="has_permit">${s("has_permit",t.has_permit)}</select>
                        </div>
                        <div class="acc-form-group"><label>شماره پروانه</label>
                            <input name="permit_number" value="${this.escape(t.permit_number||"")}">
                        </div>
                    </div>
                    <div class="acc-form-group"><label>پایان کار</label>
                        <select name="has_completion">${a("has_completion",t.has_completion)}</select>
                    </div>
                    <div class="gis-info-divider">امکانات</div>
                    <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;margin:8px 0;">
                        ${i("has_water",t.has_water,"💧 آب")}
                        ${i("has_electricity",t.has_electricity,"⚡ برق")}
                        ${i("has_gas",t.has_gas,"🔥 گاز")}
                        ${i("has_elevator",t.has_elevator,"🛗 آسانسور")}
                        ${i("has_parking",t.has_parking,"🚗 پارکینگ")}
                        ${i("has_storage",t.has_storage,"📦 انباری")}
                        ${i("has_basement",t.has_basement,"🏚️ زیرزمین")}
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector('[data-action="cancel"]').addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()}),n.querySelector("form").addEventListener("submit",async o=>{o.preventDefault();const l=new FormData(o.target),c=Object.fromEntries(l.entries());["has_building","has_basement","has_water","has_electricity","has_gas","has_elevator","has_parking","has_storage"].forEach(h=>{c[h]=c[h]?1:0});const d=o.target.querySelector('[type="submit"]');d.disabled=!0,d.textContent="در حال ذخیره...";try{await this.api.put(`/gis/parcels/${e}/building`,c),r(),this._toast("✅ اطلاعات ساختمان ذخیره شد"),this._openParcelPanel({id:e})}catch(h){alert("خطا: "+((h==null?void 0:h.message)||"")),d.disabled=!1,d.textContent="ذخیره"}})}_openCreateProjectModal(e){const t=`پروژه پلاک ${e.code||e.id}${e.sub_code?"/"+e.sub_code:""}`,s=new Date().toISOString().split("T")[0],a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
            <div class="acc-modal" style="max-width:460px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">🏗️ ایجاد پروژه ساخت</div>
                <div style="background:#eff6ff;border-radius:8px;padding:10px 14px;font-size:12px;color:#1e40af;margin-bottom:14px;">
                    📁 پلاک: ${this.escape(e.code||"—")}/${this.escape(e.sub_code||"—")}
                    ${e.district_name?` | 🏙️ ${this.escape(e.district_name)}`:""}
                </div>
                <form>
                    <div class="acc-form-group"><label>نام پروژه *</label>
                        <input name="name" required value="${this.escape(t)}">
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>کد پروژه</label>
                            <input name="code" placeholder="مثلاً PRJ-001">
                        </div>
                        <div class="acc-form-group"><label>تاریخ شروع</label>
                            <input name="start_date" type="date" value="${s}">
                        </div>
                    </div>
                    <div class="acc-form-group"><label>مدیر پروژه</label>
                        <input name="manager_name" value="${this.escape(e.assigned_user_name||"")}">
                    </div>
                    <div class="acc-form-group"><label>بودجه اولیه (ریال)</label>
                        <input name="budget" type="number" min="0" placeholder="اختیاری">
                    </div>
                    <div class="acc-form-group"><label>توضیحات</label>
                        <textarea name="description" rows="2" placeholder="خلاصه پروژه...">${this.escape(e.address?"آدرس: "+e.address:"")}</textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--success">🏗️ ایجاد پروژه</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector('[data-action="cancel"]').addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{var l;n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());r.type="construction",r.status="planned",r.parcel_id=e.id,r.budget||delete r.budget;const o=n.target.querySelector('[type="submit"]');o.disabled=!0,o.textContent="در حال ایجاد...";try{const c=await this.api.post("/pc/projects",r),d=(c==null?void 0:c.id)||((l=c==null?void 0:c.data)==null?void 0:l.id);d&&await this.api.put(`/gis/parcels/${e.id}`,{cpm_project_id:d}),i(),this._toast(`✅ پروژه با موفقیت ایجاد شد${d?" (ID: "+d+")":""}`,"#10b981"),await this._loadMapData(),this._openParcelPanel({id:e.id})}catch(c){alert("خطا در ایجاد پروژه: "+((c==null?void 0:c.message)||"")),o.disabled=!1,o.textContent="🏗️ ایجاد پروژه"}})}async _toggleLock(e){const t=this._getCurrentUser();try{if(e.locked_by_user_id&&e.locked_by_user_id!=t.id){alert(`این پارسل توسط ${e.locked_by_name} در دست بررسی است.`);return}e.locked_by_user_id?(await this.api.post(`/gis/parcels/${e.id}/unlock`,{}),this._toast("🔓 پارسل آزاد شد")):(await this.api.post(`/gis/parcels/${e.id}/lock`,{user_id:t.id,user_name:t.name}),this._toast("🔒 پارسل رزرو شد برای شما")),await this._loadMapData(),this._openParcelPanel({id:e.id})}catch(s){alert("خطا: "+((s==null?void 0:s.message)||""))}}_getCurrentUser(){try{const t=(sessionStorage.getItem("acc_token")||"").split(".")[1],s=JSON.parse(atob(t));return{id:s.user_id||s.sub||0,name:s.name||s.display_name||"کاربر"}}catch{return{id:0,name:"کاربر"}}}_enterAddMode(){this._addMode=!0,this.ref("addBtn").style.display="none",this.ref("cancelAddBtn").style.display="",this.ref("addHint").style.display="",this.ref("mapEl")&&(this.ref("mapEl").style.cursor="crosshair")}_exitAddMode(){this._addMode=!1,this.ref("addBtn").style.display="",this.ref("cancelAddBtn").style.display="none",this.ref("addHint").style.display="none",this.ref("mapEl")&&(this.ref("mapEl").style.cursor="")}_switchTile(e){var t,s,a;!this._map||!this._tileLayers||e===this._activeTileKey||(this._map.removeLayer(this._tileLayers[this._activeTileKey]),this._tileLayers[e].addTo(this._map),this._activeTileKey=e,(t=this.ref("tileEsri"))==null||t.classList.toggle("gis-tile-btn--active",e==="esri"),(s=this.ref("tileVoyager"))==null||s.classList.toggle("gis-tile-btn--active",e==="voyager"),(a=this.ref("tileCarto"))==null||a.classList.toggle("gis-tile-btn--active",e==="carto"))}_showOfflinePanel(){var a;const e=(((a=window.ACC_CONFIG)==null?void 0:a.api)??"/wp-json/acc/v1").replace(/\/+$/,""),t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:460px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">📥 دانلود نقشه آفلاین — شیراز</div>

            <div style="background:#f0fdf4;border:1px solid #86efac;border-radius:8px;padding:12px;font-size:12px;color:#166534;margin-bottom:14px;">
                کاشی‌های نقشه برای محدوده شیراز دانلود و در سرور ذخیره می‌شوند.
                پس از دانلود، نقشه بدون نیاز به اینترنت کار می‌کند.
            </div>

            <div class="doc-form-row">
                <div class="acc-form-group">
                    <label>حداقل zoom</label>
                    <select id="_zm_min" style="padding:7px;">
                        ${[10,11,12].map(i=>`<option value="${i}" ${i===10?"selected":""}>${i}</option>`).join("")}
                    </select>
                </div>
                <div class="acc-form-group">
                    <label>حداکثر zoom</label>
                    <select id="_zm_max" style="padding:7px;">
                        ${[12,13,14,15,16,17].map(i=>`<option value="${i}" ${i===14?"selected":""}>${i}</option>`).join("")}
                    </select>
                </div>
            </div>

            <div class="acc-form-group" style="font-size:11px;color:#64748b;">
                محدوده پیش‌فرض: شیراز کامل (lat 29.35–29.85 | lng 52.25–52.95)
            </div>

            <div id="_tile_status_bar" style="padding:10px;background:#f8fafc;border-radius:8px;font-size:12px;display:none;"></div>

            <div class="acc-modal__actions">
                <button class="acc-btn acc-btn--secondary" id="_tile_status_btn">📊 وضعیت کش</button>
                <button class="acc-btn acc-btn--primary"   id="_tile_dl_btn">📥 شروع دانلود</button>
            </div>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.addEventListener("click",i=>{i.target===t&&s()}),t.querySelector("#_tile_status_btn").addEventListener("click",async()=>{const i=t.querySelector("#_tile_status_bar");i.style.display="block",i.textContent="⏳ در حال بررسی...";try{const n=await fetch(`${e}/tiles/status`,{headers:{Authorization:`Bearer ${sessionStorage.getItem("acc_token")}`}}).then(r=>r.json());i.innerHTML=n.is_offline?`✅ <b>${n.tile_count.toLocaleString("fa-IR")}</b> کاشی در کش | حجم: <b>${n.size_kb.toLocaleString("fa-IR")} KB</b>`:"⚠️ هیچ کاشی‌ای در کش نیست. دانلود را شروع کنید."}catch{i.textContent="❌ خطا در بررسی وضعیت"}}),t.querySelector("#_tile_dl_btn").addEventListener("click",async()=>{const i=t.querySelector("#_tile_dl_btn"),n=t.querySelector("#_tile_status_bar"),r=parseInt(t.querySelector("#_zm_min").value),o=parseInt(t.querySelector("#_zm_max").value);n.style.display="block",n.textContent="⏳ در حال دانلود کاشی‌ها... (ممکن است چند دقیقه طول بکشد)",i.disabled=!0;try{const l=sessionStorage.getItem("acc_token"),c=await fetch(`${e}/tiles/download`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${l}`},body:JSON.stringify({lat_min:29.35,lat_max:29.85,lng_min:52.25,lng_max:52.95,zoom_min:r,zoom_max:o})}).then(d=>d.json());c.success?n.innerHTML=`✅ دانلود کامل شد!<br>
                        📥 دانلود جدید: <b>${c.downloaded}</b> |
                        ⏭ موجود: <b>${c.skipped}</b> |
                        ❌ خطا: <b>${c.failed}</b>`:n.innerHTML=`❌ ${c.message}`}catch(l){n.innerHTML=`❌ خطا: ${l.message}`}i.disabled=!1})}_toggleBlockMode(){this._blockMode=!this._blockMode;const e=this.ref("blockModeBtn");this._blockMode?(e.style.background="#dbeafe",e.style.borderColor="#3b82f6",e.style.color="#1d4ed8",e.textContent="📦 حالت انتخاب بلوک (فعال)",this._map&&(this._map.getContainer().style.cursor="crosshair")):(e.style.background="",e.style.borderColor="",e.style.color="",e.textContent="📦 انتخاب بلوک",this._map&&(this._map.getContainer().style.cursor=""))}async _loadLayersList(){try{const e=await this.api.get("/gis/layers-list"),t=(e==null?void 0:e.data)??[],s=this.ref("layerFilter");if(!s||!t.length)return;t.forEach(a=>{const i=document.createElement("option");i.value=a.layer_id,i.textContent=`📚 لایه ${a.layer_id} (${a.parcel_count})`,s.appendChild(i)})}catch{}}async _searchByCode(){var a;const e=this.ref("codeSearch"),t=this.ref("codeSearchResults"),s=((e==null?void 0:e.value)??"").trim();if(!s){this._toast("کد نوسازی را وارد کنید","#f59e0b");return}t.style.display="block",t.innerHTML='<div style="padding:10px;color:#64748b;font-size:12px;">⏳ در حال جستجو...</div>';try{const i=await this.api.get("/gis/search-by-code",{code:s});if((i==null?void 0:i.match_type)==="exact"&&i.parcel){t.style.display="none",this._jumpToParcel(i.parcel,i.block,i.parcels),this._toast(`✅ پارسل ${this.escape(i.parcel.code)} پیدا شد`,"#10b981");return}if((i==null?void 0:i.match_type)==="partial"&&((a=i.matches)!=null&&a.length)){t.innerHTML=`
                    <div style="padding:8px;color:#64748b;font-size:11px;background:#f8fafc;border-bottom:1px solid #e2e8f0;">
                        💡 ${i.matches.length} نتیجه — یکی را انتخاب کنید:
                    </div>
                    ${i.matches.map(n=>`
                        <div class="gis-search-result-item" data-code="${this.escape(n.code)}"
                             style="padding:8px 12px;border-bottom:1px solid #f1f5f9;cursor:pointer;font-size:12px;direction:ltr;text-align:left;">
                            <bdi>${this.escape(n.code)}</bdi>
                            ${n.address?`<div style="font-size:10px;color:#94a3b8;margin-top:2px;direction:rtl;text-align:right;">${this.escape(n.address)}</div>`:""}
                        </div>
                    `).join("")}
                `,t.querySelectorAll(".gis-search-result-item").forEach(n=>{n.addEventListener("mouseenter",()=>n.style.background="#eff6ff"),n.addEventListener("mouseleave",()=>n.style.background=""),n.addEventListener("click",()=>{e.value=n.dataset.code,this._searchByCode()})});return}t.innerHTML='<div style="padding:12px;color:#ef4444;font-size:12px;text-align:center;">❌ پارسلی با این کد یافت نشد</div>',setTimeout(()=>{t.style.display="none"},2500)}catch{t.innerHTML='<div style="padding:12px;color:#ef4444;font-size:12px;">❌ خطا در جستجو</div>'}}_jumpToParcel(e,t,s){const a=window.L;if(!a||!this._map)return;const i=parseFloat(e.lat),n=parseFloat(e.lng);if(t&&!this._selectedBlocks.has(t)&&(s!=null&&s.length)&&this._renderBlockData(t,s),!isNaN(i)&&!isNaN(n)){this._map.setView([i,n],18,{animate:!0});const r=a.circleMarker([i,n],{radius:18,color:"#ef4444",weight:4,fillColor:"#fbbf24",fillOpacity:.6}).addTo(this._map);let o=18,l=1;const c=setInterval(()=>{o+=l,(o>24||o<14)&&(l=-l),r.setRadius(o)},60);setTimeout(()=>{clearInterval(c),this._map.removeLayer(r)},3e3)}this._openParcelPanel(e)}async _rebuildBlocks(){if(!confirm("بازسازی index بلوک‌ها (چند ثانیه طول می‌کشد)؟"))return;const e=this.ref("rebuildBtn");e&&(e.disabled=!0,e.textContent="⏳ بازسازی...");try{const t=await this.api.post("/gis/rebuild-blocks",{});this._toast(`✅ ${(t==null?void 0:t.blocks_count)??0} بلوک بازسازی شد`,"#10b981")}catch{this._toast("❌ خطا در بازسازی","#ef4444")}finally{e&&(e.disabled=!1,e.textContent="🔧 بازسازی index")}}async _loadBlockByClick(e,t){this._toast("🔍 جستجوی نزدیک‌ترین بلوک...","#6366f1");try{const s={lat:e,lng:t};this._activeLayerId&&(s.layer_id=this._activeLayerId);const a=await this.api.get("/gis/parcels-by-click",s);if(!(a!=null&&a.block)){this._toast("⚠️ بلوکی در این ناحیه یافت نشد","#f59e0b");return}if(this._selectedBlocks.has(a.block)){this._removeBlock(a.block);return}this._renderBlockData(a.block,a.parcels??[])}catch{this._toast("❌ خطا در جستجوی بلوک","#ef4444")}}_renderBlockData(e,t,s=!1){const a=window.L,i=Ae[this._blockColorIdx%Ae.length];this._blockColorIdx++;const n=a.layerGroup().addTo(this._map);if(this._selectedBlocks.set(e,{color:i,layerGroup:n,parcels:t}),t.forEach(r=>{if(!r.lat||!r.lng)return;if(r.geometry)try{const l=typeof r.geometry=="string"?JSON.parse(r.geometry):r.geometry;a.geoJSON(l,{style:{color:i,weight:2,fillColor:i,fillOpacity:.25}}).addTo(n)}catch{}const o=a.circleMarker([parseFloat(r.lat),parseFloat(r.lng)],{radius:7,fillColor:i,color:"#fff",weight:2,fillOpacity:.9});o.bindTooltip(`<b>${r.code||"—"}</b><br>بلوک: ${e}`,{direction:"top",offset:[0,-8]}),o.on("click",()=>this._openParcelPanel(r)),o.addTo(n)}),this._updateBlockBar(),!s&&(this._saveSelectedBlocks(),this._toast(`✅ بلوک ${e}: ${t.length} پارسل`,i),t.length&&this._map)){const r=t.map(l=>parseFloat(l.lat)).filter(Boolean),o=t.map(l=>parseFloat(l.lng)).filter(Boolean);r.length&&this._map.fitBounds(a.latLngBounds([Math.min(...r),Math.min(...o)],[Math.max(...r),Math.max(...o)]),{padding:[40,40],maxZoom:17})}}async _selectBlock(e,t){if(!e)return;if(this._selectedBlocks.has(e)){this._removeBlock(e);return}const s=Ae[this._blockColorIdx%Ae.length];this._blockColorIdx++;const a=window.L,i=a.layerGroup().addTo(this._map);this._selectedBlocks.set(e,{color:s,layerGroup:i,parcels:[]}),this._updateBlockBar(),this._toast(`📦 بارگذاری بلوک ${e}...`,s);try{const n={block:e,per_page:500};this._activeLayerId&&(n.layer_id=this._activeLayerId);const r=await this.api.get("/gis/parcels",n),o=(r==null?void 0:r.data)??[];this._selectedBlocks.get(e).parcels=o,o.forEach(l=>{if(!l.lat||!l.lng)return;if(l.geometry)try{const d=typeof l.geometry=="string"?JSON.parse(l.geometry):l.geometry;a.geoJSON(d,{style:{color:s,weight:2,fillColor:s,fillOpacity:.25}}).addTo(i)}catch{}const c=a.circleMarker([parseFloat(l.lat),parseFloat(l.lng)],{radius:7,fillColor:s,color:"#fff",weight:2,fillOpacity:.9});c.bindTooltip(`<b>${l.code||"—"}</b><br>بلوک: ${e}`,{direction:"top",offset:[0,-8]}),c.on("click",()=>this._openParcelPanel(l)),c.addTo(i)}),this._updateBlockBar(),this._toast(`✅ بلوک ${e}: ${o.length} پارسل`,s)}catch{this._toast(`❌ خطا در بارگذاری بلوک ${e}`,"#ef4444")}}_removeBlock(e){const t=this._selectedBlocks.get(e);t&&(this._map&&t.layerGroup&&this._map.removeLayer(t.layerGroup),this._selectedBlocks.delete(e),this._updateBlockBar(),this._saveSelectedBlocks())}_clearAllBlocks(){for(const[e,t]of this._selectedBlocks)this._map&&t.layerGroup&&this._map.removeLayer(t.layerGroup);this._selectedBlocks.clear(),this._updateBlockBar(),this._saveSelectedBlocks()}_updateBlockBar(){const e=this.ref("blockBar"),t=this.ref("blockChips");if(!(!e||!t)){if(this._selectedBlocks.size===0){e.style.display="none";return}e.style.display="flex",t.innerHTML="";for(const[s,a]of this._selectedBlocks){const i=a.parcels.length,n=document.createElement("div");n.className="gis-block-chip",n.style.cssText=`
                display:inline-flex;align-items:center;gap:4px;
                background:${a.color}22;border:1.5px solid ${a.color};
                color:${a.color};border-radius:20px;
                padding:2px 10px;font-size:11px;font-weight:700;
                cursor:pointer;white-space:nowrap;
            `,n.innerHTML=`
                <span style="width:8px;height:8px;border-radius:50%;
                    background:${a.color};display:inline-block;"></span>
                ${this.escape(s)}
                ${i?`<span style="opacity:.7;">(${i})</span>`:""}
                <span class="gis-block-chip-remove" style="margin-right:2px;font-size:13px;
                    line-height:1;opacity:.7;">✕</span>
            `,n.querySelector(".gis-block-chip-remove").addEventListener("click",r=>{r.stopPropagation(),this._removeBlock(s)}),t.appendChild(n)}}}_bindToolbar(){this.on(this.ref("addBtn"),"click",()=>this._enterAddMode()),this.on(this.ref("cancelAddBtn"),"click",()=>this._exitAddMode()),this.on(this.ref("refreshBtn"),"click",async()=>{await this._loadMapData(),this._toast("🔄 نقشه به‌روزرسانی شد","#3b82f6")}),this.on(this.ref("offlineBtn"),"click",()=>this._showOfflinePanel()),this.on(this.ref("tileEsri"),"click",()=>this._switchTile("esri")),this.on(this.ref("tileVoyager"),"click",()=>this._switchTile("voyager")),this.on(this.ref("tileCarto"),"click",()=>this._switchTile("carto")),this.on(this.ref("blockModeBtn"),"click",()=>this._toggleBlockMode()),this.on(this.ref("clearBlocksBtn"),"click",()=>this._clearAllBlocks()),this.on(this.ref("rebuildBtn"),"click",()=>this._rebuildBlocks()),this.on(this.ref("codeSearchBtn"),"click",()=>this._searchByCode()),this.container.querySelectorAll("[data-section-nav]").forEach(e=>e.addEventListener("click",()=>{const t=e.dataset.sectionNav;this.gisView&&typeof this.gisView._switch=="function"&&this.gisView._switch(t)})),this.on(this.ref("toolsBtn"),"click",()=>{const e=this.ref("toolsPanel"),t=e.style.display!=="none";e.style.display=t?"none":"block",this.ref("toolsBtn").textContent=t?"⚙️ ابزارها":"✕ بستن ابزارها"}),this.on(this.ref("layerFilter"),"change",()=>{this._activeLayerId=this.ref("layerFilter").value||null,this._toast(this._activeLayerId?`📚 لایه فعال: ${this._activeLayerId}`:"📚 همه لایه‌ها","#3b82f6")}),this._loadLayersList(),this.on(this.ref("codeSearch"),"keydown",e=>{e.key==="Enter"&&(e.preventDefault(),this._searchByCode())}),document.addEventListener("click",e=>{const t=this.ref("codeSearchResults");t&&!t.contains(e.target)&&e.target!==this.ref("codeSearch")&&(t.style.display="none")}),this.container.querySelectorAll(".gis-filter-btn").forEach(e=>{e.addEventListener("click",()=>{this.container.querySelectorAll(".gis-filter-btn").forEach(t=>t.classList.remove("gis-filter-btn--active")),e.classList.add("gis-filter-btn--active"),this._activeFilter=e.dataset.filter||"all",this._renderParcels()})}),this.container.querySelectorAll(".gis-layer-toggle input").forEach(e=>{e.addEventListener("change",()=>{const t=e.dataset.layer,s=this._layers[t];!s||!this._map||(e.checked?s.addTo(this._map):this._map.removeLayer(s))})})}_updateCountLabel(){const e=this.ref("countLbl");if(!e)return;const t=this._activeFilter==="all"?this._mapData.parcels:this._mapData.parcels.filter(s=>s.status===this._activeFilter);e.textContent=`📁 ${t.length} پارسل`}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}_jalali(e){if(!e)return"";try{const t=new Date(e);return isNaN(t.getTime())?e:new Intl.DateTimeFormat("fa-IR-u-ca-persian",{year:"numeric",month:"2-digit",day:"2-digit"}).format(t)}catch{return e}}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;box-shadow:0 4px 20px rgba(0,0,0,.15);max-width:340px;direction:rtl;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3500)}destroy(){this._map&&(this._map.remove(),this._map=null),super.destroy()}}const pt={prospect:"#f59e0b",under_review:"#f97316",purchased:"#3b82f6",permitted:"#8b5cf6",under_construction:"#ef4444",completed:"#10b981",sold:"#6b7280"},Ss={prospect:"در کشف",under_review:"در بررسی",purchased:"خریداری‌شده",permitted:"مجوزگرفته",under_construction:"در ساخت",completed:"تکمیل‌شده",sold:"فروخته‌شده"},hr=["discovery","review","purchase","permit","construction","sale"],ur={discovery:"کشف",review:"بررسی",purchase:"خرید",permit:"مجوز",construction:"ساخت",sale:"فروش"};class fr extends x{constructor(e={}){super(e),this._parcels=[],this._districts=[],this._filter={status:"",district_id:"",search:""},this._view="list"}async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._loadDistricts(),await this._showList()}async _loadDistricts(){try{const e=await this.api.get("/gis/districts");this._districts=(e==null?void 0:e.data)??[]}catch{}}async _showList(){const e=this.ref("root"),t='<option value="">همه مناطق</option>'+this._districts.map(s=>`<option value="${s.id}">${this.escape(s.name)}</option>`).join("");e.innerHTML=`
            <div style="display:flex;gap:10px;align-items:center;margin-bottom:16px;flex-wrap:wrap;">
                <input type="text" class="acc-input" data-ref="searchInp" placeholder="🔍 جستجوی پلاک یا آدرس..."
                    style="min-width:200px;flex:1;" value="${this.escape(this._filter.search)}">
                <select class="event-type-filter" data-ref="distSel">
                    ${t}
                </select>
                <select class="event-type-filter" data-ref="statusSel">
                    <option value="">همه وضعیت‌ها</option>
                    ${Object.entries(Ss).map(([s,a])=>`<option value="${s}">${a}</option>`).join("")}
                </select>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="kanbanBtn">📋 Kanban</button>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
                <span style="font-size:12px;color:#94a3b8;" data-ref="countLbl"></span>
            </div>
            <div data-ref="body"></div>
        `,this._bindRef(),this.on(this.ref("searchInp"),"input",()=>{this._filter.search=this.ref("searchInp").value,this._loadList()}),this.on(this.ref("distSel"),"change",()=>{this._filter.district_id=this.ref("distSel").value,this._loadList()}),this.on(this.ref("statusSel"),"change",()=>{this._filter.status=this.ref("statusSel").value,this._loadList()}),this.on(this.ref("refreshBtn"),"click",()=>this._loadList()),this.on(this.ref("kanbanBtn"),"click",()=>this._view==="list"?this._renderKanban():this._renderListView()),await this._loadList()}_bindRef(){var e;(e=this.ref("root"))==null||e.querySelectorAll("[data-ref]").forEach(t=>{this.refs[t.dataset.ref]=t})}async _loadList(){const e=this.ref("body");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t={};this._filter.status&&(t.status=this._filter.status),this._filter.district_id&&(t.district_id=this._filter.district_id),this._filter.search&&(t.search=this._filter.search);const s=await this.api.get("/gis/parcels",t);this._parcels=(s==null?void 0:s.data)??[],this.ref("countLbl").textContent=`${this._parcels.length} پرونده`,this._view==="kanban"?this._renderKanban():this._renderListView()}catch{e.innerHTML='<div class="acc-error">خطا در بارگذاری</div>'}}_renderListView(){this._view="list";const e=this.ref("body");if(!this._parcels.length){e.innerHTML='<div class="acc-empty">پرونده‌ای یافت نشد.</div>';return}e.innerHTML="",this._parcels.forEach(t=>{const s=document.createElement("div");s.className="parcel-list-card",s.style.borderRight=`4px solid ${pt[t.status]||"#94a3b8"}`,s.innerHTML=`
                <div style="flex:1;min-width:0;">
                    <div style="font-weight:800;font-size:15px;color:#1e293b;margin-bottom:4px;">
                        پلاک ${this.escape(t.code||"—")}/${this.escape(t.sub_code||"—")}
                    </div>
                    <div style="font-size:12px;color:#64748b;margin-bottom:6px;">
                        ${this.escape(t.district_name||"")} ${t.neighborhood_name?"← "+this.escape(t.neighborhood_name):""}
                    </div>
                    <div style="font-size:12px;color:#475569;">${this.escape(t.address||"")}</div>
                </div>
                <div style="display:flex;flex-direction:column;align-items:flex-end;gap:6px;min-width:100px;">
                    <span style="background:${pt[t.status]||"#94a3b8"};color:#fff;border-radius:8px;padding:3px 10px;font-size:11px;font-weight:700;">
                        ${Ss[t.status]||t.status}
                    </span>
                    ${t.assigned_user_name?`<span style="font-size:11px;color:#64748b;">👤 ${this.escape(t.assigned_user_name)}</span>`:""}
                    ${t.locked_by_name?`<span style="font-size:11px;color:#d97706;">🔒 ${this.escape(t.locked_by_name)}</span>`:""}
                </div>
            `,e.appendChild(s)})}_renderKanban(){this._view="kanban";const e=this.ref("body");e.innerHTML=`
            <div class="gis-kanban">
                ${hr.map(t=>{const s=this._parcels.filter(a=>a.pipeline_stage===t);return`
                    <div class="gis-kanban-col">
                        <div class="gis-kanban-col__header">
                            ${ur[t]}
                            <span class="gis-kanban-count">${s.length}</span>
                        </div>
                        <div class="gis-kanban-col__body">
                            ${s.map(a=>`
                                <div class="gis-kanban-card" style="border-top:3px solid ${pt[a.status]||"#94a3b8"}">
                                    <div class="gis-kanban-card__title">پلاک ${this.escape(a.code||"—")}</div>
                                    <div class="gis-kanban-card__meta">${this.escape(a.district_name||"")} ${a.neighborhood_name?"← "+this.escape(a.neighborhood_name):""}</div>
                                    ${a.assigned_user_name?`<div class="gis-kanban-card__user">👤 ${this.escape(a.assigned_user_name)}</div>`:""}
                                </div>`).join("")}
                        </div>
                    </div>`}).join("")}
            </div>`}}class mr extends x{constructor(e={}){super(e),this._districts=[],this._neighborhoods=[],this._activeTab="districts"}async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._render()}async _render(){var t;const e=this.ref("root");e.innerHTML=`
            <div style="display:flex;gap:10px;margin-bottom:20px;flex-wrap:wrap;align-items:center;">
                <button class="acc-btn ${this._activeTab==="districts"?"acc-btn--primary":"acc-btn--secondary"}"
                    data-tab="districts">🏙️ مناطق شهرداری</button>
                <button class="acc-btn ${this._activeTab==="neighborhoods"?"acc-btn--primary":"acc-btn--secondary"}"
                    data-tab="neighborhoods">🏘️ محلات</button>
                <div style="margin-right:auto;">
                    <button class="acc-btn acc-btn--secondary" data-ref="importBtn"
                        style="background:#f0fdf4;border-color:#86efac;color:#166534;">
                        📥 ایمپورت JSON پارسل‌ها
                    </button>
                </div>
            </div>
            <div data-ref="body"></div>
        `,e.querySelectorAll("[data-tab]").forEach(s=>{s.addEventListener("click",()=>{this._activeTab=s.dataset.tab,this._render()})}),this._bindRef(),(t=this.ref("importBtn"))==null||t.addEventListener("click",()=>this._openImportModal()),this._activeTab==="districts"?await this._renderDistricts():await this._renderNeighborhoods()}_bindRef(){var e;(e=this.ref("root"))==null||e.querySelectorAll("[data-ref]").forEach(t=>{this.refs[t.dataset.ref]=t})}async _renderDistricts(){var s;const e=this.ref("body");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const a=await this.api.get("/gis/districts");this._districts=(a==null?void 0:a.data)??[]}catch{e.innerHTML='<div class="acc-error">خطا در بارگذاری</div>';return}e.innerHTML=`
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
                <span style="font-weight:700;color:#1e293b;">${this._districts.length} منطقه ثبت‌شده</span>
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-action="add-district">➕ منطقه جدید</button>
            </div>
            <div data-ref="distList"></div>
        `,e.querySelector("[data-ref]")&&(this.refs.distList=e.querySelector('[data-ref="distList"]')),(s=e.querySelector('[data-action="add-district"]'))==null||s.addEventListener("click",()=>this._openDistrictModal());const t=e.querySelector('[data-ref="distList"]');if(!this._districts.length){t.innerHTML='<div class="acc-empty">منطقه‌ای ثبت نشده.</div>';return}this._districts.forEach(a=>{var n,r;const i=document.createElement("div");i.className="gis-layer-row",i.style.borderRight=`4px solid ${a.color||"#3b82f6"}`,i.innerHTML=`
                <div class="gis-layer-dot" style="background:${a.color||"#3b82f6"}"></div>
                <div style="flex:1;">
                    <div style="font-weight:700;font-size:14px;color:#1e293b;">${this.escape(a.name)}</div>
                    <div style="font-size:12px;color:#64748b;">
                        ${a.neighborhood_count||0} محله | ${a.parcel_count||0} پارسل
                        ${a.assigned_user_name?" | 👤 "+this.escape(a.assigned_user_name):""}
                    </div>
                </div>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-edit="${a.id}">ویرایش</button>
                <button class="acc-btn acc-btn--danger acc-btn--sm" data-del="${a.id}">حذف</button>
            `,(n=i.querySelector("[data-edit]"))==null||n.addEventListener("click",()=>this._openDistrictModal(a)),(r=i.querySelector("[data-del]"))==null||r.addEventListener("click",async()=>{confirm(`حذف منطقه "${a.name}"؟`)&&(await this.api.delete(`/gis/districts/${a.id}`),this._renderDistricts())}),t.appendChild(i)})}_openDistrictModal(e=null){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
            <div class="acc-modal" style="max-width:400px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${e?"ویرایش":"افزودن"} منطقه</div>
                <form>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>نام منطقه *</label>
                            <input name="name" required value="${this.escape((e==null?void 0:e.name)||"")}">
                        </div>
                        <div class="acc-form-group"><label>کد</label>
                            <input name="code" value="${this.escape((e==null?void 0:e.code)||"")}">
                        </div>
                    </div>
                    <div class="acc-form-group"><label>شهر</label>
                        <input name="city" value="${this.escape((e==null?void 0:e.city)||"تهران")}">
                    </div>
                    <div class="acc-form-group"><label>کارشناس مسئول</label>
                        <input name="assigned_user_name" value="${this.escape((e==null?void 0:e.assigned_user_name)||"")}">
                    </div>
                    <div class="acc-form-group"><label>رنگ روی نقشه</label>
                        <input type="color" name="color" value="${(e==null?void 0:e.color)||"#3b82f6"}" style="width:60px;height:36px;cursor:pointer;">
                    </div>
                    <div class="acc-form-group"><label>یادداشت</label>
                        <textarea name="notes" rows="2">${this.escape((e==null?void 0:e.notes)||"")}</textarea>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${e?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector('[data-action="cancel"]').addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries()),n=a.target.querySelector('[type="submit"]');n.disabled=!0;try{e?await this.api.put(`/gis/districts/${e.id}`,i):await this.api.post("/gis/districts",i),s(),await this._renderDistricts()}catch(r){alert("خطا: "+((r==null?void 0:r.message)||"")),n.disabled=!1}})}async _renderNeighborhoods(){var i;const e=this.ref("body");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const[n,r]=await Promise.all([this.api.get("/gis/districts"),this.api.get("/gis/neighborhoods")]);this._districts=(n==null?void 0:n.data)??[],this._neighborhoods=(r==null?void 0:r.data)??[]}catch{e.innerHTML='<div class="acc-error">خطا</div>';return}const t={growing:"🔥",stable:"➡️",declining:"📉"},s={growing:"رو به رشد",stable:"پایدار",declining:"رو به افول"};e.innerHTML=`
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:12px;">
                <span style="font-weight:700;color:#1e293b;">${this._neighborhoods.length} محله ثبت‌شده</span>
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-action="add-n">➕ محله جدید</button>
            </div>
            <div id="n-list"></div>
        `,(i=e.querySelector('[data-action="add-n"]'))==null||i.addEventListener("click",()=>this._openNeighborhoodModal());const a=e.querySelector("#n-list");if(!this._neighborhoods.length){a.innerHTML='<div class="acc-empty">محله‌ای ثبت نشده.</div>';return}this._neighborhoods.forEach(n=>{var o,l;const r=document.createElement("div");r.className="gis-layer-row",r.innerHTML=`
                <div style="flex:1;">
                    <div style="font-weight:700;font-size:14px;color:#1e293b;">${this.escape(n.name)}</div>
                    <div style="font-size:12px;color:#64748b;margin-top:2px;">
                        🏙️ ${this.escape(n.district_name||"")} |
                        ${t[n.development_trend]||""} ${s[n.development_trend]||""}
                        ${n.has_metro=="1"?" | 🚇 مترو":""}
                        ${n.parcel_count?" | 📁 "+n.parcel_count+" پارسل":""}
                        ${n.assigned_user_name?" | 👤 "+this.escape(n.assigned_user_name):""}
                    </div>
                </div>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-edit="${n.id}">ویرایش</button>
                <button class="acc-btn acc-btn--danger acc-btn--sm" data-del="${n.id}">حذف</button>
            `,(o=r.querySelector("[data-edit]"))==null||o.addEventListener("click",()=>this._openNeighborhoodModal(n)),(l=r.querySelector("[data-del]"))==null||l.addEventListener("click",async()=>{confirm(`حذف محله "${n.name}"؟`)&&(await this.api.delete(`/gis/neighborhoods/${n.id}`),this._renderNeighborhoods())}),a.appendChild(r)})}_openNeighborhoodModal(e=null){const t='<option value="">— انتخاب منطقه —</option>'+this._districts.map(i=>`<option value="${i.id}" ${i.id==(e==null?void 0:e.district_id)?"selected":""}>${this.escape(i.name)}</option>`).join(""),s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
            <div class="acc-modal" style="max-width:440px;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${e?"ویرایش":"افزودن"} محله</div>
                <form>
                    <div class="acc-form-group"><label>نام محله *</label>
                        <input name="name" required value="${this.escape((e==null?void 0:e.name)||"")}">
                    </div>
                    <div class="acc-form-group"><label>منطقه *</label>
                        <select name="district_id" required>${t}</select>
                    </div>
                    <div class="doc-form-row">
                        <div class="acc-form-group"><label>کارشناس مسئول</label>
                            <input name="assigned_user_name" value="${this.escape((e==null?void 0:e.assigned_user_name)||"")}">
                        </div>
                        <div class="acc-form-group"><label>روند توسعه</label>
                            <select name="development_trend">
                                <option value="growing" ${(e==null?void 0:e.development_trend)==="growing"?"selected":""}>🔥 رو به رشد</option>
                                <option value="stable"  ${(e==null?void 0:e.development_trend)==="stable"?"selected":""}>➡️ پایدار</option>
                                <option value="declining" ${(e==null?void 0:e.development_trend)==="declining"?"selected":""}>📉 رو به افول</option>
                            </select>
                        </div>
                    </div>
                    <div class="acc-form-group"><label>کاربری غالب</label>
                        <input name="dominant_use" value="${this.escape((e==null?void 0:e.dominant_use)||"")}">
                    </div>
                    <div style="display:flex;gap:16px;margin:10px 0;font-size:13px;">
                        <label><input type="checkbox" name="has_metro" value="1" ${(e==null?void 0:e.has_metro)=="1"?"checked":""}> 🚇 مترو</label>
                        <label><input type="checkbox" name="has_brt"   value="1" ${(e==null?void 0:e.has_brt)=="1"?"checked":""}> 🚌 BRT</label>
                    </div>
                    <div class="acc-form-group"><label>وضعیت زیرساخت</label>
                        <select name="infrastructure">
                            <option value="complete" ${(e==null?void 0:e.infrastructure)==="complete"?"selected":""}>✅ کامل</option>
                            <option value="partial"  ${(e==null?void 0:e.infrastructure)==="partial"?"selected":""}>🟡 ناقص</option>
                            <option value="poor"     ${(e==null?void 0:e.infrastructure)==="poor"?"selected":""}>🔴 ضعیف</option>
                        </select>
                    </div>
                    <div class="acc-modal__actions">
                        <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                        <button type="submit" class="acc-btn acc-btn--primary">${e?"ذخیره":"افزودن"}</button>
                    </div>
                </form>
            </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector('[data-action="cancel"]').addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries());n.has_metro=n.has_metro?1:0,n.has_brt=n.has_brt?1:0;const r=i.target.querySelector('[type="submit"]');r.disabled=!0;try{e?await this.api.put(`/gis/neighborhoods/${e.id}`,n):await this.api.post("/gis/neighborhoods",n),a(),await this._renderNeighborhoods()}catch(o){alert("خطا: "+((o==null?void 0:o.message)||"")),r.disabled=!1}})}_openImportModal(){const e=document.createElement("div");e.className="acc-modal-overlay",e.innerHTML=`
        <div class="acc-modal" style="max-width:500px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">📥 ایمپورت JSON پارسل‌ها</div>

            <div style="background:#eff6ff;border:1px solid #bfdbfe;border-radius:8px;
                        padding:12px;font-size:12px;color:#1e40af;margin-bottom:16px;line-height:1.8;">
                <b>فرمت قابل قبول:</b><br>
                • فیلد <code>Geom</code>: WKT POLYGON<br>
                • فیلد <code>Code</code>/<code>Name</code>: کد پلاک<br>
                • فیلد <code>parsel</code>: کدهای نوسازی (comma-separated)
            </div>

            <div class="acc-form-group">
                <label>مسیر فایل JSON روی سرور</label>
                <input id="_imp_path" placeholder="مثال: C:/data/shiraz_parcels.json"
                    style="direction:ltr;font-size:12px;font-family:monospace;">
            </div>
            <div class="acc-form-group">
                <label>منطقه شهرداری (اختیاری)</label>
                <select id="_imp_district">
                    <option value="">— بدون تخصیص —</option>
                </select>
            </div>
            <div class="acc-form-group">
                <label style="display:flex;gap:8px;align-items:center;cursor:pointer;">
                    <input type="checkbox" id="_imp_skip" checked>
                    رد کردن پارسل‌های تکراری (بر اساس کد)
                </label>
            </div>

            <div id="_imp_result" style="display:none;padding:12px;border-radius:8px;
                font-size:13px;margin-top:10px;"></div>

            <div class="acc-modal__actions">
                <button class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                <button class="acc-btn acc-btn--primary" id="_imp_btn">📥 شروع ایمپورت</button>
            </div>
        </div>`,document.body.appendChild(e);const t=()=>e.remove();e.querySelector(".acc-modal__close").addEventListener("click",t),e.querySelector('[data-action="cancel"]').addEventListener("click",t),e.addEventListener("click",s=>{s.target===e&&t()}),this.api.get("/gis/districts").then(s=>{const a=e.querySelector("#_imp_district");((s==null?void 0:s.data)||[]).forEach(i=>{a.innerHTML+=`<option value="${i.id}">${this.escape(i.name)}</option>`})}),e.querySelector("#_imp_btn").addEventListener("click",async()=>{var o,l;const s=e.querySelector("#_imp_btn"),a=e.querySelector("#_imp_path").value.trim(),i=e.querySelector("#_imp_district").value,n=e.querySelector("#_imp_skip").checked,r=e.querySelector("#_imp_result");if(!a){alert("مسیر فایل را وارد کنید");return}s.disabled=!0,s.textContent="⏳ در حال ایمپورت...",r.style.display="none";try{const c=await this.api.post("/gis/import",{file_path:a,district_id:i||null,skip_duplicates:n}),d=c==null?void 0:c.success;r.style.display="block",r.style.background=d?"#f0fdf4":"#fef2f2",r.style.border=`1px solid ${d?"#86efac":"#fca5a5"}`,r.style.color=d?"#166534":"#991b1b",d?r.innerHTML=`
                        ✅ ایمپورت کامل شد<br>
                        📌 درج شده: <b>${c.inserted}</b><br>
                        ⏭ رد شده (تکراری): <b>${c.skipped}</b><br>
                        ❌ خطا: <b>${((o=c.errors)==null?void 0:o.length)||0}</b>
                        ${(l=c.errors)!=null&&l.length?"<br><small>"+c.errors.slice(0,3).map(h=>this.escape(h)).join("<br>")+"</small>":""}
                    `:r.textContent="❌ "+((c==null?void 0:c.message)||"خطا")}catch(c){r.style.display="block",r.style.background="#fef2f2",r.style.border="1px solid #fca5a5",r.style.color="#991b1b",r.textContent="❌ "+((c==null?void 0:c.message)||"خطای ارتباطی")}s.disabled=!1,s.textContent="📥 شروع ایمپورت"})}}const ue={customer:{label:"مشتریان",icon:"🛒",color:"#10b981",api:"/sales/customers",nameField:"name"},supplier:{label:"تأمین‌کنندگان",icon:"🏭",color:"#f59e0b",api:"/purchase/suppliers",nameField:"name"},employee:{label:"کارمندان",icon:"👤",color:"#3b82f6",api:"/hr/employees",nameField:"full_name"},project:{label:"پروژه‌ها",icon:"🏗️",color:"#ef4444",api:"/pc/projects",nameField:"name"},warehouse:{label:"انبارها",icon:"🏭",color:"#8b5cf6",api:"/inv/warehouses",nameField:"name"},lead:{label:"سرنخ‌ها",icon:"🌱",color:"#06b6d4",api:"/crm/leads",nameField:"name"}};class vr extends x{constructor(e){super(e),this._enabledTypes=new Set(["customer","supplier","employee","warehouse"]),this._entityCache={},this._allLocations=[],this._markers=[]}async template(){return`
        <div class="acc-section-wrap" style="display:flex;flex-direction:column;height:calc(100vh - 200px);">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🗺️ نقشه عمومی</h2>
                <div style="display:flex;gap:8px;align-items:center;">
                    <input type="text" data-ref="search" placeholder="🔍 جستجو..." class="acc-input" style="width:200px;">
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>

            <!-- فیلتر چیپ‌ها -->
            <div data-ref="filterBar" style="display:flex;flex-wrap:wrap;gap:8px;margin:12px 0;padding:10px;background:#f8fafc;border-radius:8px;">
                ${Object.entries(ue).map(([t,s])=>`
            <label class="umap-filter-chip" data-type="${t}" style="display:inline-flex;align-items:center;gap:6px;padding:6px 12px;border:2px solid ${s.color};border-radius:20px;cursor:pointer;font-size:12px;font-weight:600;color:${s.color};background:#fff;user-select:none;">
                <input type="checkbox" value="${t}" ${this._enabledTypes.has(t)?"checked":""} style="margin:0;">
                ${s.icon} ${s.label}
                <span class="umap-count" style="background:${s.color}1a;color:${s.color};border-radius:10px;padding:0 6px;font-size:10px;">0</span>
            </label>
        `).join("")}
            </div>

            <!-- نقشه -->
            <div style="flex:1;border:1px solid #cbd5e1;border-radius:8px;overflow:hidden;position:relative;">
                <div data-ref="mapEl" style="width:100%;height:100%;min-height:500px;"></div>
                <div data-ref="loading" style="position:absolute;inset:0;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.8);font-size:14px;color:#64748b;">
                    ⏳ بارگذاری...
                </div>
            </div>

            <!-- نوار آمار پایین -->
            <div data-ref="statusBar" style="display:flex;gap:16px;padding:8px 12px;background:#f8fafc;border-radius:8px;margin-top:8px;font-size:12px;color:#64748b;">
                <span data-ref="totalLbl">📍 مجموع: 0</span>
                <span data-ref="coordsLbl">🌐 —</span>
            </div>
        </div>`}async afterRender(){await this._loadLeaflet(),this._initMap(),await this._loadAll(),this.on(this.ref("refreshBtn"),"click",()=>this._loadAll()),this.on(this.ref("search"),"input",()=>{clearTimeout(this._t),this._t=setTimeout(()=>this._render(),300)}),this.ref("filterBar").querySelectorAll("input[type=checkbox]").forEach(e=>{e.addEventListener("change",()=>{e.checked?this._enabledTypes.add(e.value):this._enabledTypes.delete(e.value),this._render()})})}async _loadLeaflet(){var s;if(window.L)return;const e=(((s=window.ACC_CONFIG)==null?void 0:s.pluginUrl)??"").replace(/\/+$/,""),t=e?`${e}/assets/vendor/leaflet`:"/wp-content/plugins/acc-engine/assets/vendor/leaflet";if(!document.querySelector('link[href*="leaflet"]')){const a=document.createElement("link");a.rel="stylesheet",a.href=`${t}/leaflet.css`,document.head.appendChild(a)}await new Promise((a,i)=>{const n=document.createElement("script");n.src=`${t}/leaflet.js`,n.onload=a,n.onerror=i,document.head.appendChild(n)})}_initMap(){var a;const e=window.L,t=this.ref("mapEl");this._map=e.map(t,{zoomControl:!0}).setView([29.5926,52.5836],11);const s=(((a=window.ACC_CONFIG)==null?void 0:a.pluginUrl)??"").replace(/\/+$/,"");e.tileLayer(`${s||"/wp-content/plugins/acc-engine"}/assets/vendor/leaflet/tiles_esri/{z}/{x}/{y}.png`,{attribution:"© Esri",minZoom:10,maxZoom:19,maxNativeZoom:16}).addTo(this._map),this._layer=e.layerGroup().addTo(this._map),this._map.on("mousemove",i=>{const n=this.ref("coordsLbl");n&&(n.textContent=`🌐 ${i.latlng.lat.toFixed(5)}, ${i.latlng.lng.toFixed(5)}`)}),this.ref("loading").style.display="none"}async _loadAll(){this.ref("loading").style.display="flex";try{const e=await this.api.get("/gis/locations/map");this._allLocations=(e==null?void 0:e.data)??[];const t=Object.entries(ue).map(async([s,a])=>{try{const i=await this.api.get(a.api),n=(i==null?void 0:i.data)??[],r={};n.forEach(o=>{r[o.id]=o}),this._entityCache[s]=r}catch{this._entityCache[s]={}}});await Promise.all(t),this._render()}catch{this._toast("❌ خطا در بارگذاری","#ef4444")}finally{this.ref("loading").style.display="none"}}_render(){var n;const e=window.L;if(!this._map)return;this._layer.clearLayers(),this._markers=[];const t=(((n=this.ref("search"))==null?void 0:n.value)??"").toLowerCase(),s=[],a={};Object.keys(ue).forEach(r=>a[r]=0),this._allLocations.forEach(r=>{var m;const o=r.entity_type,l=ue[o];if(!l||!this._enabledTypes.has(o))return;const c=parseFloat(r.lat),d=parseFloat(r.lng);if(isNaN(c)||isNaN(d))return;const h=(m=this._entityCache[o])==null?void 0:m[r.entity_id],u=(h==null?void 0:h[l.nameField])||(h==null?void 0:h.name)||r.label||`${l.label} #${r.entity_id}`;if(t&&!`${u} ${r.address??""} ${r.label??""}`.toLowerCase().includes(t))return;a[o]++,s.push([c,d]);const f=e.marker([c,d],{icon:e.divIcon({className:"",iconSize:[32,32],html:`<div style="background:${l.color};color:#fff;border-radius:50%;width:32px;height:32px;display:flex;align-items:center;justify-content:center;border:2px solid #fff;box-shadow:0 2px 6px rgba(0,0,0,.3);font-size:14px;">${l.icon}</div>`})});f.bindTooltip(`
                <b>${l.icon} ${this.escape(u)}</b>
                <br><small style="color:#94a3b8;">${l.label}</small>
                ${r.label?"<br><b>📌 "+this.escape(r.label)+"</b>":""}
                ${r.address?"<br><small>"+this.escape(r.address)+"</small>":""}
            `,{direction:"top"}),f.on("click",()=>this._showEntityPopup(o,r.entity_id,u,r)),f.addTo(this._layer),this._markers.push(f)}),this.ref("filterBar").querySelectorAll(".umap-filter-chip").forEach(r=>{const o=r.dataset.type,l=r.querySelector(".umap-count");l&&(l.textContent=a[o]??0)});const i=Object.values(a).reduce((r,o)=>r+o,0);this.ref("totalLbl").textContent=`📍 مجموع: ${i} نقطه`,s.length&&s.length<200&&this._map.fitBounds(s,{padding:[40,40],maxZoom:14})}_showEntityPopup(e,t,s,a){const i=ue[e],n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
        <div class="acc-modal" style="max-width:420px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${i.icon} ${this.escape(s)}</div>
            <div style="background:${i.color}1a;padding:8px 12px;border-radius:6px;font-size:12px;color:${i.color};margin-bottom:12px;font-weight:600;">
                ${i.label}
            </div>
            ${a.label?`<div style="margin-bottom:6px;"><b>📌 برچسب:</b> ${this.escape(a.label)}</div>`:""}
            ${a.address?`<div style="margin-bottom:6px;"><b>📍 آدرس:</b> ${this.escape(a.address)}</div>`:""}
            <div style="margin-bottom:6px;"><b>🌐 مختصات:</b> <bdi dir="ltr">${a.lat}, ${a.lng}</bdi></div>
            ${a.parcel_id?`<div style="margin-bottom:6px;color:#3b82f6;"><b>🔗 پارسل:</b> #${a.parcel_id}</div>`:""}
            <div class="acc-modal__actions">
                <button class="acc-btn acc-btn--secondary" data-action="close">بستن</button>
            </div>
        </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector("[data-action=close]").addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const ht=[{key:"map",icon:"🗺️",title:"نقشه",Class:pr},{key:"parcels",icon:"📁",title:"پرونده‌ها",Class:fr},{key:"layers",icon:"🏙️",title:"لایه‌ها",Class:mr},{key:"universal",icon:"🌐",title:"نقشه عمومی",Class:vr}];class Cs extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._active="map",this._sections={}}async template(){const t=ht.map(a=>`
            <button class="gis-tab-btn ${a.key===this._active?"gis-tab-btn--active":""}"
                    data-section="${a.key}">
                ${a.icon} ${a.title}
            </button>
        `).join(""),s=ht.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="gis-tab-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".gis-tab-btn").forEach(t=>this.on(t,"click",()=>this._switch(t.dataset.section))),await this._mount(this._active),this._updateNavVisibility()}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".gis-tab-btn").forEach(s=>s.classList.toggle("gis-tab-btn--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t),this._updateNavVisibility())}_updateNavVisibility(){const t=this.ref("navBar");t&&(t.style.display=this._active==="map"?"none":"")}async _mount(t){if(this._sections[t])return;const s=ht.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api,gisView:this});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(Cs,"title","🗺️ نقشه هوشمند"),E.register("gis",Cs);const Ie={purchase:{label:"خرید ملک",icon:"🏠",color:"#3b82f6",bg:"#eff6ff",border:"#bfdbfe"},construction:{label:"مشارکت در ساخت",icon:"🏗️",color:"#f97316",bg:"#fff7ed",border:"#fed7aa"},sale:{label:"فروش واحد",icon:"🔑",color:"#10b981",bg:"#f0fdf4",border:"#a7f3d0"},lease:{label:"اجاره",icon:"📋",color:"#8b5cf6",bg:"#f5f3ff",border:"#ddd6fe"},consulting:{label:"مشاوره",icon:"💼",color:"#6b7280",bg:"#f9fafb",border:"#e5e7eb"}},ae={draft:{label:"پیش‌نویس",color:"#94a3b8",bg:"#f8fafc"},active:{label:"فعال",color:"#10b981",bg:"#f0fdf4"},completed:{label:"تکمیل‌شده",color:"#3b82f6",bg:"#eff6ff"},terminated:{label:"فسخ‌شده",color:"#ef4444",bg:"#fef2f2"},suspended:{label:"معلق",color:"#f59e0b",bg:"#fffbeb"}},Ts={seller:{label:"فروشنده",color:"#3b82f6"},buyer:{label:"خریدار",color:"#10b981"},contractor:{label:"پیمانکار",color:"#f97316"},consultant:{label:"مشاور",color:"#8b5cf6"},guarantor:{label:"ضامن",color:"#f59e0b"},owner:{label:"مالک",color:"#6b7280"},other:{label:"سایر",color:"#94a3b8"}},br=`
.cl-wrap { display:flex;height:calc(100vh - 120px);overflow:hidden;direction:rtl;font-family:inherit; }

/* ── sidebar لیست ── */
.cl-sidebar {
    width:340px;flex-shrink:0;display:flex;flex-direction:column;
    border-left:1px solid #e2e8f0;background:#fafafa;
    transition:width .25s;
}
.cl-toolbar {
    padding:14px;border-bottom:1px solid #e2e8f0;background:#fff;
    display:flex;flex-direction:column;gap:8px;
}
.cl-toolbar-top { display:flex;gap:6px;align-items:center; }
.cl-search {
    flex:1;padding:8px 12px;border:1.5px solid #e2e8f0;border-radius:10px;
    font-size:.82rem;font-family:inherit;background:#f8fafc;
    transition:border-color .2s,background .2s;
}
.cl-search:focus { outline:none;border-color:#3b82f6;background:#fff; }
.cl-filter-row { display:flex;gap:6px; }
.cl-sel {
    flex:1;padding:6px 8px;border:1.5px solid #e2e8f0;border-radius:8px;
    font-size:.78rem;font-family:inherit;background:#fff;
}
.cl-btn {
    padding:7px 14px;border-radius:10px;border:1.5px solid #e2e8f0;
    background:#fff;font-size:.78rem;font-weight:700;cursor:pointer;
    font-family:inherit;color:#374151;transition:all .15s;white-space:nowrap;
}
.cl-btn:hover { border-color:#cbd5e1;background:#f8fafc; }
.cl-btn--primary { background:#3b82f6;color:#fff;border-color:#2563eb; }
.cl-btn--primary:hover { background:#2563eb; }
.cl-btn--orange { background:#f97316;color:#fff;border-color:#ea580c; }
.cl-btn--orange:hover { background:#ea580c; }
.cl-btn--sm { padding:5px 10px;font-size:.72rem; }
.cl-btn--xs { padding:3px 8px;font-size:.68rem;border-radius:7px; }

/* آمار sidebar */
.cl-stats { display:grid;grid-template-columns:1fr 1fr;gap:6px;padding:12px 14px;border-bottom:1px solid #e2e8f0; }
.cl-stat { background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:8px 10px;text-align:center;box-shadow:0 1px 3px rgba(0,0,0,.03); }
.cl-stat-n { font-size:1.1rem;font-weight:800;line-height:1; }
.cl-stat-l { font-size:.68rem;color:#94a3b8;margin-top:2px; }

/* لیست کارت‌ها */
.cl-list { flex:1;overflow-y:auto;padding:10px 8px; }
.cl-list::-webkit-scrollbar { width:4px; }
.cl-list::-webkit-scrollbar-thumb { background:#e2e8f0;border-radius:99px; }

/* کارت */
.cl-card {
    background:#fff;border:1.5px solid #e2e8f0;border-radius:14px;
    padding:12px 14px;margin-bottom:8px;cursor:pointer;
    transition:all .18s;position:relative;overflow:hidden;
    animation:cardIn .3s ease both;
}
.cl-card::before {
    content:'';position:absolute;top:0;right:0;bottom:0;width:4px;
    border-radius:0 4px 4px 0;background:var(--tc,#94a3b8);
}
@keyframes cardIn { from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none} }
.cl-card:hover { border-color:#cbd5e1;box-shadow:0 4px 16px rgba(0,0,0,.06);transform:translateY(-1px); }
.cl-card--active { border-color:#3b82f6;background:#eff6ff;box-shadow:0 4px 20px rgba(59,130,246,.12); }

.cl-card-head { display:flex;align-items:flex-start;gap:10px;margin-bottom:6px; }
.cl-card-icon { width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:1.2rem;flex-shrink:0; }
.cl-card-title { font-size:.85rem;font-weight:700;color:#1e293b;line-height:1.3; }
.cl-card-num { font-size:.7rem;color:#94a3b8;margin-top:2px;font-family:monospace; }

.cl-card-badges { display:flex;gap:4px;flex-wrap:wrap;margin-bottom:6px;padding-right:48px; }
.cl-badge {
    font-size:.66rem;font-weight:700;padding:2px 7px;border-radius:20px;border:1.5px solid;
}
.cl-card-amount { font-size:.82rem;font-weight:800;color:#1e293b;padding-right:48px; }
.cl-card-amount span { font-size:.68rem;color:#94a3b8;font-weight:400; }
.cl-card-parties { font-size:.72rem;color:#64748b;padding-right:48px;margin-top:3px;
    white-space:nowrap;overflow:hidden;text-overflow:ellipsis; }

.cl-progress { margin:8px 0 4px;padding-right:48px; }
.cl-progress-bar { height:4px;background:#f1f5f9;border-radius:99px;overflow:hidden; }
.cl-progress-fill { height:100%;border-radius:99px;transition:width .6s ease; }
.cl-progress-pct { font-size:.65rem;color:#94a3b8;margin-top:2px;text-align:left; }

/* ── پانل جزئیات ── */
.cl-detail {
    flex:1;display:flex;flex-direction:column;
    background:#fff;overflow:hidden;
}
.cl-detail-empty {
    flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;
    color:#cbd5e1;gap:12px;
}
.cl-detail-empty-icon { font-size:3.5rem;opacity:.4; }

/* هدر جزئیات */
.cl-detail-head {
    padding:18px 24px 14px;border-bottom:1px solid #f1f5f9;
    display:flex;align-items:flex-start;gap:16px;
    background:linear-gradient(135deg,var(--hbg,#f8fafc) 0%,#fff 60%);
}
.cl-detail-icon { width:52px;height:52px;border-radius:14px;display:flex;align-items:center;justify-content:center;font-size:1.6rem;flex-shrink:0; }
.cl-detail-title { font-size:1rem;font-weight:800;color:#1e293b; }
.cl-detail-sub { font-size:.75rem;color:#64748b;margin-top:4px;display:flex;gap:10px;flex-wrap:wrap;align-items:center; }
.cl-detail-actions { display:flex;gap:6px;margin-top:10px;flex-wrap:wrap; }

/* خلاصه مالی */
.cl-fin {
    display:grid;grid-template-columns:repeat(3,1fr);gap:10px;
    padding:14px 24px;border-bottom:1px solid #f1f5f9;
    background:#fafafa;
}
.cl-fin-card { background:#fff;border:1px solid #e2e8f0;border-radius:12px;padding:10px 12px;text-align:center; }
.cl-fin-lbl { font-size:.7rem;color:#94a3b8;margin-bottom:4px; }
.cl-fin-val { font-size:1rem;font-weight:800; }
.cl-fin-progress { padding:0 24px 12px;border-bottom:1px solid #f1f5f9; }
.cl-fp-row { display:flex;justify-content:space-between;font-size:.72rem;color:#94a3b8;margin-bottom:4px; }
.cl-fp-bar { height:6px;background:#f1f5f9;border-radius:99px;overflow:hidden; }
.cl-fp-fill { height:100%;border-radius:99px;transition:width .8s ease; }

/* تب‌ها */
.cl-tabs { display:flex;gap:2px;padding:10px 24px 0;border-bottom:1px solid #f1f5f9;background:#fff; }
.cl-tab {
    padding:8px 16px;font-size:.8rem;font-weight:600;cursor:pointer;
    border:none;background:none;color:#64748b;border-bottom:2.5px solid transparent;
    font-family:inherit;transition:all .15s;
}
.cl-tab:hover { color:#1e293b; }
.cl-tab--active { color:#3b82f6;border-bottom-color:#3b82f6; }

/* محتوای تب */
.cl-tab-body { flex:1;overflow-y:auto;padding:16px 24px; }
.cl-tab-body::-webkit-scrollbar { width:4px; }
.cl-tab-body::-webkit-scrollbar-thumb { background:#e2e8f0;border-radius:99px; }

/* جزئیات تب */
.cl-info-grid { display:grid;grid-template-columns:1fr 1fr;gap:8px;margin-bottom:14px; }
.cl-info-box { background:#f8fafc;border-radius:10px;padding:8px 12px; }
.cl-info-box-lbl { font-size:.7rem;color:#94a3b8;margin-bottom:2px; }
.cl-info-box-val { font-size:.88rem;color:#1e293b;font-weight:600; }

/* کارت طرف قرارداد */
.cl-party-card {
    background:#f8fafc;border:1.5px solid #e2e8f0;border-radius:12px;
    padding:12px 14px;margin-bottom:8px;display:flex;align-items:flex-start;gap:12px;
}
.cl-party-avatar { width:40px;height:40px;border-radius:10px;display:flex;align-items:center;justify-content:center;font-size:1.1rem;flex-shrink:0; }
.cl-party-info { flex:1;min-width:0; }
.cl-party-name { font-size:.88rem;font-weight:700;color:#1e293b; }
.cl-party-meta { font-size:.72rem;color:#64748b;margin-top:3px;display:flex;gap:10px;flex-wrap:wrap; }

/* ردیف قسط */
.cl-payment-row {
    display:flex;align-items:center;gap:10px;padding:10px 12px;
    border:1.5px solid #e2e8f0;border-radius:10px;margin-bottom:6px;
    background:#fff;transition:border-color .15s;
}
.cl-payment-row--overdue { border-color:#fecaca;background:#fef2f2; }
.cl-payment-row--paid { background:#f0fdf4;border-color:#a7f3d0;opacity:.8; }
.cl-pay-no { width:22px;height:22px;border-radius:6px;background:#f1f5f9;font-size:.7rem;font-weight:800;color:#64748b;display:flex;align-items:center;justify-content:center;flex-shrink:0; }
.cl-pay-body { flex:1;min-width:0; }
.cl-pay-amount { font-size:.88rem;font-weight:700;color:#1e293b; }
.cl-pay-meta { font-size:.7rem;color:#64748b;margin-top:2px; }
.cl-pay-status { font-size:.68rem;font-weight:700;padding:2px 8px;border-radius:20px;border:1.5px solid;white-space:nowrap;flex-shrink:0; }
.cl-pay-actions { display:flex;gap:4px;flex-shrink:0; }

/* متن قرارداد */
.cl-contract-html { padding:4px 0;max-width:100%; }

/* مودال */
.cl-overlay { position:fixed;inset:0;background:rgba(0,0,0,.45);z-index:2000;display:flex;align-items:center;justify-content:center;padding:16px; }
.cl-modal { background:#fff;border-radius:20px;width:100%;max-width:560px;max-height:92vh;overflow-y:auto;box-shadow:0 20px 60px rgba(0,0,0,.2);animation:modalIn .22s ease; }
@keyframes modalIn { from{opacity:0;transform:scale(.95)}to{opacity:1;transform:none} }
.cl-modal-head { padding:18px 20px 14px;border-bottom:1px solid #f1f5f9;display:flex;align-items:center;gap:10px; }
.cl-modal-title { font-size:.95rem;font-weight:800;color:#1e293b;flex:1; }
.cl-modal-body { padding:18px 20px; }
.cl-modal-actions { display:flex;gap:8px;justify-content:flex-end;padding:12px 20px;border-top:1px solid #f1f5f9; }
.cl-form-row { display:grid;grid-template-columns:1fr 1fr;gap:10px; }
.cl-fg { display:flex;flex-direction:column;gap:4px;margin-bottom:10px; }
.cl-fg label { font-size:.74rem;color:#475569;font-weight:600; }
.cl-fg input,.cl-fg select,.cl-fg textarea { padding:8px 10px;border:1.5px solid #e2e8f0;border-radius:9px;font-size:.83rem;font-family:inherit;transition:border-color .2s;width:100%;box-sizing:border-box; }
.cl-fg input:focus,.cl-fg select:focus,.cl-fg textarea:focus { outline:none;border-color:#3b82f6;box-shadow:0 0 0 3px rgba(59,130,246,.1); }
.cl-section-divider { font-size:.72rem;font-weight:700;color:#94a3b8;text-transform:uppercase;letter-spacing:.06em;padding:6px 0 4px;border-bottom:1px solid #f1f5f9;margin-bottom:10px;grid-column:1/-1; }

/* toast */
.cl-toast { position:fixed;bottom:28px;left:50%;transform:translateX(-50%);background:#1e293b;color:#fff;padding:12px 24px;border-radius:12px;font-size:.84rem;font-weight:600;z-index:9999;box-shadow:0 8px 30px rgba(0,0,0,.2);direction:rtl;white-space:nowrap;animation:toastIn .2s ease; }
@keyframes toastIn { from{opacity:0;transform:translateX(-50%) translateY(12px)}to{opacity:1;transform:translateX(-50%) translateY(0)} }

/* پانل قرارداد مشارکت ویزارد */
.cl-partner-modal { max-width:700px; }
.cl-partner-grid { display:grid;grid-template-columns:1fr 1fr;gap:10px; }
`;class gr extends x{constructor(e={}){super(e),this._contracts=[],this._selected=null,this._activeTab="details",this._parcels=[],this._projects=[],this._injectCSS()}_injectCSS(){if(document.getElementById("cl-styles"))return;const e=document.createElement("style");e.id="cl-styles",e.textContent=br,document.head.appendChild(e)}async template(){return'<div data-ref="root" style="height:100%;overflow:hidden;"></div>'}async afterRender(){await this._loadLookups(),await this._render()}async _loadLookups(){try{const[e,t]=await Promise.all([this.api.get("/gis/districts").catch(()=>null),this.api.get("/pc/projects",{per_page:200}).catch(()=>null)]);this._parcels=(e==null?void 0:e.data)??[],this._projects=(t==null?void 0:t.data)??[]}catch{}}async _render(){const e=this.ref("root");e.innerHTML=`
        <div class="cl-wrap">
            <!-- sidebar -->
            <div class="cl-sidebar">
                <div class="cl-toolbar">
                    <div class="cl-toolbar-top">
                        <input type="text" class="cl-search" data-ref="searchInp" placeholder="🔍 جستجو در قراردادها…">
                        <button class="cl-btn cl-btn--primary cl-btn--sm" data-ref="addBtn">➕ جدید</button>
                        <button class="cl-btn cl-btn--orange cl-btn--sm" data-ref="tplBtn" title="قالب مشارکت در ساخت">📄</button>
                    </div>
                    <div class="cl-filter-row">
                        <select class="cl-sel" data-ref="typeSel">
                            <option value="">همه انواع</option>
                            ${Object.entries(Ie).map(([t,s])=>`<option value="${t}">${s.icon} ${s.label}</option>`).join("")}
                        </select>
                        <select class="cl-sel" data-ref="statusSel">
                            <option value="">همه وضعیت‌ها</option>
                            ${Object.entries(ae).map(([t,s])=>`<option value="${t}">${s.label}</option>`).join("")}
                        </select>
                    </div>
                </div>
                <div class="cl-stats" data-ref="statsBar">
                    <div class="cl-stat"><div class="cl-stat-n" style="color:#3b82f6">—</div><div class="cl-stat-l">کل</div></div>
                    <div class="cl-stat"><div class="cl-stat-n" style="color:#10b981">—</div><div class="cl-stat-l">فعال</div></div>
                    <div class="cl-stat"><div class="cl-stat-n" style="color:#f59e0b">—</div><div class="cl-stat-l">پیش‌نویس</div></div>
                    <div class="cl-stat"><div class="cl-stat-n" style="color:#3b82f6">—</div><div class="cl-stat-l">تکمیل</div></div>
                </div>
                <div class="cl-list" data-ref="listBody"></div>
            </div>

            <!-- پانل جزئیات -->
            <div class="cl-detail" data-ref="detailPane">
                <div class="cl-detail-empty" data-ref="detailEmpty">
                    <span class="cl-detail-empty-icon">📋</span>
                    <span style="font-size:.9rem;font-weight:600">یک قرارداد انتخاب کنید</span>
                    <span style="font-size:.78rem">برای مشاهده جزئیات روی کارت کلیک کنید</span>
                </div>
                <div style="display:none;flex:1;flex-direction:column;overflow:hidden;" data-ref="detailContent">
                    <div data-ref="detailHead"></div>
                    <div class="cl-fin" data-ref="detailFin"></div>
                    <div class="cl-fin-progress" data-ref="detailFp"></div>
                    <div class="cl-tabs" data-ref="detailTabs"></div>
                    <div class="cl-tab-body" data-ref="detailTabBody"></div>
                </div>
            </div>
        </div>`,e.querySelectorAll("[data-ref]").forEach(t=>{this.refs[t.dataset.ref]=t}),this.on(this.ref("searchInp"),"input",()=>this._loadList()),this.on(this.ref("typeSel"),"change",()=>this._loadList()),this.on(this.ref("statusSel"),"change",()=>this._loadList()),this.on(this.ref("addBtn"),"click",()=>this._openContractModal()),this.on(this.ref("tplBtn"),"click",()=>this._openPartnershipWizard()),await this._loadList()}async _loadList(){var t,s,a;const e=this.ref("listBody");e.innerHTML='<div style="display:flex;justify-content:center;padding:40px;"><div class="acc-spinner"></div></div>';try{const i={},n=(t=this.ref("searchInp"))==null?void 0:t.value,r=(s=this.ref("typeSel"))==null?void 0:s.value,o=(a=this.ref("statusSel"))==null?void 0:a.value;n&&(i.search=n),r&&(i.type=r),o&&(i.status=o);const l=await this.api.get("/contracts",i);this._contracts=(l==null?void 0:l.data)??[],this._updateStats(),this._renderList()}catch{e.innerHTML='<div style="padding:20px;color:#ef4444;font-size:.82rem;">خطا در بارگذاری</div>'}}_updateStats(){const e=this.ref("statsBar");if(!e)return;const t=e.querySelectorAll(".cl-stat-n"),s=this._contracts;t[0].textContent=s.length,t[1].textContent=s.filter(a=>a.status==="active").length,t[2].textContent=s.filter(a=>a.status==="draft").length,t[3].textContent=s.filter(a=>a.status==="completed").length}_renderList(){const e=this.ref("listBody");if(!this._contracts.length){e.innerHTML=`<div style="text-align:center;padding:48px 16px;color:#94a3b8;">
                <div style="font-size:2.5rem;margin-bottom:10px;opacity:.4;">📋</div>
                <div style="font-size:.85rem;">قراردادی یافت نشد</div>
            </div>`;return}e.innerHTML="",this._contracts.forEach((t,s)=>{var d;const a=Ie[t.type]||{label:t.type,icon:"📄",color:"#94a3b8",bg:"#f8fafc"},i=ae[t.status]||ae.draft,n=parseFloat(t.paid_amount||0),r=parseFloat(t.total_amount||0),o=r>0?Math.round(n/r*100):0,l=((d=this._selected)==null?void 0:d.id)==t.id,c=document.createElement("div");c.className=`cl-card${l?" cl-card--active":""}`,c.style.cssText=`--tc:${a.color};animation-delay:${s*50}ms`,c.innerHTML=`
                <div class="cl-card-head">
                    <div class="cl-card-icon" style="background:${a.bg}">${a.icon}</div>
                    <div style="flex:1;min-width:0">
                        <div class="cl-card-title">${this.escape(t.title)}</div>
                        ${t.contract_number?`<div class="cl-card-num">${this.escape(t.contract_number)}</div>`:""}
                    </div>
                </div>
                <div class="cl-card-badges">
                    <span class="cl-badge" style="color:${a.color};border-color:${a.color};background:${a.bg}">${a.icon} ${a.label}</span>
                    <span class="cl-badge" style="color:${i.color};border-color:${i.color};background:${i.bg}">
                        <span style="display:inline-block;width:5px;height:5px;border-radius:50%;background:${i.color};margin-left:4px;vertical-align:middle"></span>${i.label}
                    </span>
                </div>
                ${r>0?`<div class="cl-card-amount">${this._fmt(r)} <span>ریال</span></div>`:""}
                ${t.party_names?`<div class="cl-card-parties">👥 ${this.escape(t.party_names)}</div>`:""}
                ${r>0?`
                <div class="cl-progress">
                    <div class="cl-progress-bar"><div class="cl-progress-fill" style="width:${o}%;background:${a.color}"></div></div>
                    <div class="cl-progress-pct">${o}٪ پرداخت‌شده</div>
                </div>`:""}`,c.addEventListener("click",()=>this._openDetail(t)),e.appendChild(c)})}async _openDetail(e){this._selected=e,this._renderList(),this.ref("detailEmpty").style.display="none",this.ref("detailContent").style.display="flex";const t=this.ref("detailHead"),s=this.ref("detailFin"),a=this.ref("detailFp"),i=this.ref("detailTabs"),n=this.ref("detailTabBody");t.innerHTML='<div style="padding:18px 24px;"><div class="acc-spinner" style="width:24px;height:24px;border-width:2px;margin:0"></div></div>',s.innerHTML=n.innerHTML=i.innerHTML="";try{const r=await this.api.get(`/contracts/${e.id}`),o=r==null?void 0:r.data;if(!o)return;this._selected=o;const l=Ie[o.type]||{label:o.type,icon:"📄",color:"#3b82f6",bg:"#eff6ff"},c=ae[o.status]||ae.draft,d=o.financial_summary||{},h=d.progress_pct||0;t.style.cssText=`--hbg:${l.bg}`,t.innerHTML=`
            <div class="cl-detail-head" style="--hbg:${l.bg}">
                <div class="cl-detail-icon" style="background:${l.bg}">${l.icon}</div>
                <div style="flex:1;min-width:0">
                    <div class="cl-detail-title">${this.escape(o.title)}</div>
                    <div class="cl-detail-sub">
                        <span class="cl-badge" style="color:${l.color};border-color:${l.color};background:${l.bg}">${l.label}</span>
                        <span class="cl-badge" style="color:${c.color};border-color:${c.color};background:${c.bg}">${c.label}</span>
                        ${o.contract_number?`<span style="font-family:monospace;font-size:.72rem;color:#94a3b8;">№ ${this.escape(o.contract_number)}</span>`:""}
                    </div>
                    <div class="cl-detail-actions">
                        <button class="cl-btn cl-btn--sm cl-btn--primary" data-ref="editBtn">✏️ ویرایش</button>
                        <button class="cl-btn cl-btn--sm" style="background:#fef2f2;color:#ef4444;border-color:#fecaca;" data-ref="deleteBtn">🗑️ فسخ</button>
                    </div>
                </div>
            </div>`,t.querySelectorAll("[data-ref]").forEach(m=>{this.refs[m.dataset.ref]=m}),this.on(this.ref("editBtn"),"click",()=>this._openContractModal(o)),this.on(this.ref("deleteBtn"),"click",async()=>{confirm(`فسخ قرارداد "${o.title}"؟`)&&(await this.api.delete(`/contracts/${o.id}`),this._toast("قرارداد فسخ شد","🗑️","#ef4444"),this._selected=null,this.ref("detailEmpty").style.display="flex",this.ref("detailContent").style.display="none",await this._loadList())}),s.innerHTML=`
                <div class="cl-fin-card">
                    <div class="cl-fin-lbl">مبلغ کل</div>
                    <div class="cl-fin-val" style="color:#1e293b">${this._fmt(d.total)}</div>
                    <div style="font-size:.68rem;color:#94a3b8;">ریال</div>
                </div>
                <div class="cl-fin-card">
                    <div class="cl-fin-lbl">پرداخت‌شده</div>
                    <div class="cl-fin-val" style="color:#10b981">${this._fmt(d.paid)}</div>
                    <div style="font-size:.68rem;color:#94a3b8;">ریال</div>
                </div>
                <div class="cl-fin-card">
                    <div class="cl-fin-lbl">مانده</div>
                    <div class="cl-fin-val" style="color:#ef4444">${this._fmt(d.remaining)}</div>
                    <div style="font-size:.68rem;color:#94a3b8;">ریال</div>
                </div>`,a.innerHTML=`
                <div class="cl-fp-row"><span>پیشرفت پرداخت</span><span style="font-weight:700;color:${l.color}">${h}٪</span></div>
                <div class="cl-fp-bar"><div class="cl-fp-fill" style="width:${h}%;background:${l.color}"></div></div>`;const u=o.description&&o.description.trim().startsWith("<"),f=[{key:"details",label:"📋 جزئیات"},{key:"parties",label:`👥 طرفین (${(o.parties||[]).length})`},{key:"payments",label:`💰 اقساط (${(o.payments||[]).length})`},...u?[{key:"contract_text",label:"📄 متن قرارداد"}]:[]];i.innerHTML=f.map(m=>`<button class="cl-tab${this._activeTab===m.key?" cl-tab--active":""}" data-tab="${m.key}">${m.label}</button>`).join(""),i.querySelectorAll(".cl-tab").forEach(m=>{m.addEventListener("click",()=>{i.querySelectorAll(".cl-tab").forEach(b=>b.classList.remove("cl-tab--active")),m.classList.add("cl-tab--active"),this._activeTab=m.dataset.tab,this._renderTabBody(m.dataset.tab,o)})}),this._renderTabBody(this._activeTab,o)}catch{t.innerHTML='<div style="padding:20px;color:#ef4444;font-size:.82rem;">خطا در بارگذاری</div>'}}_renderTabBody(e,t){const s=this.ref("detailTabBody");switch(e){case"details":s.innerHTML=this._tabDetails(t);break;case"parties":s.innerHTML=this._tabParties(t.parties||[]),this._bindPartyActions(t);break;case"payments":s.innerHTML=this._tabPayments(t.payments||[],t),this._bindPayActions(t);break;case"contract_text":s.innerHTML=`<div class="cl-contract-html">${t.description}</div>`;break;default:s.innerHTML=""}}_tabDetails(e){const t=(s,a)=>a?`<div class="cl-info-box"><div class="cl-info-box-lbl">${s}</div><div class="cl-info-box-val">${a}</div></div>`:"";return`
        <div class="cl-info-grid">
            ${t("📅 تاریخ تنظیم",e.contract_date)}
            ${t("🚀 تاریخ شروع",e.start_date)}
            ${t("🏁 تاریخ پایان",e.end_date)}
            ${t("💱 ارز",e.currency)}
            ${t("👤 ثبت‌کننده",e.created_by_name)}
        </div>
        ${e.description&&!e.description.trim().startsWith("<")?`
        <div style="background:#f8fafc;border-right:3px solid #3b82f6;border-radius:10px;padding:10px 14px;font-size:.82rem;color:#475569;line-height:1.8;">
            ${this.escape(e.description)}
        </div>`:""}
        ${e.notes?`<div style="margin-top:10px;background:#fffbeb;border-right:3px solid #f59e0b;border-radius:10px;padding:10px 14px;font-size:.78rem;color:#92400e;">
            📝 ${this.escape(e.notes)}
        </div>`:""}
        ${e.parcel?`<div style="margin-top:10px;background:#eff6ff;border-radius:10px;padding:10px 14px;font-size:.78rem;color:#1e40af;">
            📍 پلاک ${this.escape(e.parcel.code||"—")} — ${this.escape(e.parcel.address||"")}
        </div>`:""}`}_tabParties(e){return`<div>
            <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:12px;">
                <span style="font-size:.78rem;font-weight:700;color:#64748b;">طرفین قرارداد</span>
                <button class="cl-btn cl-btn--sm" data-action="add-party">+ افزودن طرف</button>
            </div>
            ${e.map(s=>{const a=Ts[s.role]||{label:s.role,color:"#94a3b8"};return`<div class="cl-party-card">
                <div class="cl-party-avatar" style="background:${a.color}18;color:${a.color}">
                    ${s.is_company=="1"?"🏢":"👤"}
                </div>
                <div class="cl-party-info">
                    <div class="cl-party-name">${this.escape(s.name)}</div>
                    ${s.is_company=="1"&&s.company_name?`<div style="font-size:.72rem;color:#64748b;">🏢 ${this.escape(s.company_name)}</div>`:""}
                    <div class="cl-party-meta">
                        <span class="cl-badge" style="color:${a.color};border-color:${a.color};background:${a.color}18">${a.label}</span>
                        ${s.national_id?`<span>🪪 ${this.escape(s.national_id)}</span>`:""}
                        ${s.phone?`<span>📞 ${this.escape(s.phone)}</span>`:""}
                    </div>
                </div>
                <div style="display:flex;gap:4px;">
                    <button class="cl-btn cl-btn--xs" data-edit-party="${s.id}">✏️</button>
                    <button class="cl-btn cl-btn--xs" style="background:#fef2f2;color:#ef4444;border-color:#fecaca;" data-del-party="${s.id}">🗑️</button>
                </div>
            </div>`}).join("")||'<div style="text-align:center;padding:24px;color:#94a3b8;font-size:.8rem;">طرفی ثبت نشده</div>'}
        </div>`}_bindPartyActions(e){var s;const t=this.ref("detailTabBody");(s=t.querySelector('[data-action="add-party"]'))==null||s.addEventListener("click",()=>this._openPartyModal(e.id)),t.querySelectorAll("[data-edit-party]").forEach(a=>{const i=(e.parties||[]).find(n=>String(n.id)===a.dataset.editParty);i&&a.addEventListener("click",()=>this._openPartyModal(e.id,i))}),t.querySelectorAll("[data-del-party]").forEach(a=>{a.addEventListener("click",async()=>{confirm("حذف این طرف؟")&&(await this.api.delete(`/contracts/${e.id}/parties/${a.dataset.delParty}`),this._toast("حذف شد","🗑️"),this._openDetail(e))})})}_tabPayments(e,t){const s=new Date().toISOString().split("T")[0],a={paid:{label:"✅ پرداخت‌شد",color:"#10b981",bg:"#f0fdf4",border:"#a7f3d0"},overdue:{label:"⚠️ سررسید گذشت",color:"#ef4444",bg:"#fef2f2",border:"#fecaca"},partial:{label:"🟡 جزئی",color:"#f59e0b",bg:"#fffbeb",border:"#fde68a"},pending:{label:"⏳ در انتظار",color:"#94a3b8",bg:"#f8fafc",border:"#e2e8f0"},cancelled:{label:"❌ لغو",color:"#94a3b8",bg:"#f8fafc",border:"#e2e8f0"}},i=e.map(r=>{const o=r.status==="overdue"||r.status==="pending"&&r.due_date&&r.due_date<s,l=a[o?"overdue":r.status]||a.pending;return`
            <div class="cl-payment-row ${o?"cl-payment-row--overdue":""} ${r.status==="paid"?"cl-payment-row--paid":""}">
                <div class="cl-pay-no">${r.installment_no}</div>
                <div class="cl-pay-body">
                    <div class="cl-pay-amount">${this._fmt(r.amount)} ریال</div>
                    <div class="cl-pay-meta">
                        ${r.description?this.escape(r.description)+" · ":""}
                        ${r.due_date?`📅 ${r.due_date}`:""}
                        ${r.paid_date?` · ✅ ${r.paid_date}`:""}
                    </div>
                </div>
                <span class="cl-pay-status" style="color:${l.color};border-color:${l.border};background:${l.bg}">${l.label}</span>
                <div class="cl-pay-actions">
                    ${r.status!=="paid"&&r.status!=="cancelled"?`<button class="cl-btn cl-btn--xs" style="background:#f0fdf4;color:#166534;border-color:#a7f3d0;" data-pay-inst="${r.id}">💰</button>`:""}
                    <button class="cl-btn cl-btn--xs" style="color:#ef4444;border-color:#fecaca;" data-del-pay="${r.id}">🗑️</button>
                </div>
            </div>`}).join("")||'<div style="text-align:center;padding:24px;color:#94a3b8;font-size:.8rem;">قسطی تعریف نشده</div>',n=e.reduce((r,o)=>r+parseFloat(o.paid_amount||0),0);return`<div>
            <div style="display:flex;align-items:center;justify-content:space-between;margin-bottom:10px;">
                <span style="font-size:.78rem;font-weight:700;color:#64748b;">برنامه پرداخت</span>
                <button class="cl-btn cl-btn--sm" data-action="add-payment">+ افزودن قسط</button>
            </div>
            ${i}
            ${e.length?`
            <div style="margin-top:12px;padding:10px 12px;background:#f8fafc;border-radius:10px;display:flex;justify-content:space-between;font-size:.78rem;">
                <span>جمع پرداخت‌شده: <b style="color:#10b981;">${this._fmt(n)} ریال</b></span>
                <span>مانده: <b style="color:#ef4444;">${this._fmt(parseFloat(t.total_amount||0)-n)} ریال</b></span>
            </div>`:""}
        </div>`}_bindPayActions(e){var s;const t=this.ref("detailTabBody");(s=t.querySelector('[data-action="add-payment"]'))==null||s.addEventListener("click",()=>this._openPaymentModal(e.id)),t.querySelectorAll("[data-pay-inst]").forEach(a=>{a.addEventListener("click",()=>this._openPayNowModal(e.id,a.dataset.payInst,e))}),t.querySelectorAll("[data-del-pay]").forEach(a=>{a.addEventListener("click",async()=>{confirm("حذف این قسط؟")&&(await this.api.delete(`/contracts/${e.id}/payments/${a.dataset.delPay}`),this._toast("قسط حذف شد","🗑️"),this._openDetail(e))})})}_openContractModal(e=null){const t=!!e,s=i=>(e==null?void 0:e.type)===i?"selected":"",a=i=>(e==null?void 0:e.status)===i?"selected":"";this._modal(`📋 ${t?"ویرایش قرارداد":"قرارداد جدید"}`,`
        <div class="cl-fg"><label>عنوان *</label><input name="title" required value="${this.escape((e==null?void 0:e.title)||"")}"></div>
        <div class="cl-form-row">
            <div class="cl-fg"><label>نوع</label>
                <select name="type">
                    ${Object.entries(Ie).map(([i,n])=>`<option value="${i}" ${s(i)}>${n.icon} ${n.label}</option>`).join("")}
                </select>
            </div>
            <div class="cl-fg"><label>وضعیت</label>
                <select name="status">
                    ${Object.entries(ae).map(([i,n])=>`<option value="${i}" ${a(i)}>${n.label}</option>`).join("")}
                </select>
            </div>
        </div>
        <div class="cl-form-row">
            <div class="cl-fg"><label>شماره قرارداد</label><input name="contract_number" value="${this.escape((e==null?void 0:e.contract_number)||"")}"></div>
            <div class="cl-fg"><label>مبلغ کل (ریال) *</label><input name="total_amount" type="number" min="0" required value="${(e==null?void 0:e.total_amount)||""}"></div>
        </div>
        <div class="cl-form-row">
            <div class="cl-fg"><label>تاریخ تنظیم</label><input name="contract_date" type="date" value="${(e==null?void 0:e.contract_date)||""}"></div>
            <div class="cl-fg"><label>تاریخ شروع</label><input name="start_date" type="date" value="${(e==null?void 0:e.start_date)||""}"></div>
        </div>
        <div class="cl-fg"><label>تاریخ پایان</label><input name="end_date" type="date" value="${(e==null?void 0:e.end_date)||""}"></div>
        <div class="cl-fg"><label>توضیحات</label><textarea name="description" rows="3">${this.escape((e==null?void 0:e.description)||"")}</textarea></div>
        <div class="cl-fg"><label>یادداشت</label><textarea name="notes" rows="2">${this.escape((e==null?void 0:e.notes)||"")}</textarea></div>
        `,t?"ذخیره تغییرات":"ایجاد قرارداد",async(i,n,r)=>{["contract_date","start_date","end_date","parcel_id","project_id"].forEach(o=>{i[o]||delete i[o]}),t?await this.api.put(`/contracts/${e.id}`,i):await this.api.post("/contracts",i),r(),this._toast(t?"قرارداد به‌روز شد":"قرارداد ثبت شد","✅"),await this._loadList(),t&&this._openDetail({id:e.id})})}_openPartyModal(e,t=null){const s=!!t,a=t||{},i=n=>a.role===n?"selected":"";this._modal(`👥 ${s?"ویرایش":"افزودن"} طرف قرارداد`,`
        <div class="cl-fg"><label>نقش *</label>
            <select name="role">
                ${Object.entries(Ts).map(([n,r])=>`<option value="${n}" ${i(n)}>${r.label}</option>`).join("")}
            </select>
        </div>
        <div class="cl-fg"><label>نام / نام خانوادگی *</label><input name="name" required value="${this.escape(a.name||"")}"></div>
        <div class="cl-form-row">
            <div class="cl-fg"><label>کد ملی</label><input name="national_id" value="${this.escape(a.national_id||"")}"></div>
            <div class="cl-fg"><label>تلفن</label><input name="phone" type="tel" value="${this.escape(a.phone||"")}"></div>
        </div>
        <div class="cl-fg">
            <label style="display:flex;gap:8px;align-items:center;cursor:pointer;">
                <input type="checkbox" name="is_company" value="1" ${a.is_company=="1"?"checked":""}> شخص حقوقی
            </label>
        </div>
        <div class="cl-form-row">
            <div class="cl-fg"><label>نام شرکت</label><input name="company_name" value="${this.escape(a.company_name||"")}"></div>
            <div class="cl-fg"><label>شناسه ثبت</label><input name="company_reg" value="${this.escape(a.company_reg||"")}"></div>
        </div>
        `,s?"ذخیره":"افزودن",async(n,r,o)=>{n.is_company=n.is_company?1:0,s?await this.api.put(`/contracts/${e}/parties/${a.id}`,n):await this.api.post(`/contracts/${e}/parties`,n),o(),this._toast("ذخیره شد","✅"),this._openDetail({id:e})})}_openPaymentModal(e){this._modal("💰 افزودن قسط",`
        <div class="cl-fg"><label>شرح</label><input name="description" placeholder="مثلاً: پیش‌پرداخت، قسط اول…"></div>
        <div class="cl-form-row">
            <div class="cl-fg"><label>مبلغ (ریال) *</label><input name="amount" type="number" min="0" required></div>
            <div class="cl-fg"><label>سررسید</label><input name="due_date" type="date"></div>
        </div>
        <div class="cl-fg"><label>یادداشت</label><textarea name="notes" rows="2"></textarea></div>
        `,"افزودن قسط",async(t,s,a)=>{t.due_date||delete t.due_date,await this.api.post(`/contracts/${e}/payments`,t),a(),this._toast("قسط افزوده شد","✅"),this._openDetail({id:e})})}_openPayNowModal(e,t,s){const a=(s.payments||[]).find(i=>String(i.id)===String(t));a&&this._modal("💰 ثبت پرداخت",`
        <div style="background:#f0fdf4;border-radius:10px;padding:10px 14px;font-size:.83rem;margin-bottom:14px;">
            ${a.description?this.escape(a.description)+" — ":""}
            مبلغ قسط: <b>${this._fmt(a.amount)} ریال</b>
        </div>
        <div class="cl-form-row">
            <div class="cl-fg"><label>مبلغ پرداخت‌شده (ریال)</label><input name="paid_amount" type="number" min="0" value="${a.amount}"></div>
            <div class="cl-fg"><label>تاریخ پرداخت</label><input name="paid_date" type="date" value="${new Date().toISOString().split("T")[0]}"></div>
        </div>
        `,"✅ ثبت پرداخت",async(i,n,r)=>{await this.api.post(`/contracts/${e}/payments/${t}/pay`,i),r(),this._toast("پرداخت ثبت شد","✅","#10b981"),this._openDetail({id:e})},"#10b981")}_openPartnershipWizard(){const e=document.createElement("div");e.className="cl-overlay",e.innerHTML=`
        <div class="cl-modal cl-partner-modal" style="max-width:700px;">
            <div class="cl-modal-head" style="background:linear-gradient(135deg,#f97316,#ea580c);border-radius:20px 20px 0 0;color:#fff;">
                <span style="font-size:1.4rem;">🏗️</span>
                <div class="cl-modal-title" style="color:#fff;">قرارداد مشارکت در ساخت — ۱۱ ماده حقوقی</div>
                <button class="cl-btn cl-btn--xs" style="background:rgba(255,255,255,.2);color:#fff;border-color:transparent;" data-close>✕</button>
            </div>
            <div class="cl-modal-body">
                <div id="cl-partner-preview" style="display:none;border:1px solid #e2e8f0;border-radius:10px;padding:12px;margin-bottom:16px;max-height:300px;overflow-y:auto;background:#fafafa;"></div>
                <form id="cl-partner-form">
                <div class="cl-partner-grid">
                    <div class="cl-section-divider">طرف اول — مالک</div>
                    <div class="cl-fg"><label>نام و نام خانوادگی *</label><input name="owner_name" required placeholder="علی رضایی"></div>
                    <div class="cl-fg"><label>کد ملی</label><input name="owner_nid" placeholder="0012345678" dir="ltr"></div>
                    <div class="cl-fg"><label>تلفن</label><input name="owner_phone" placeholder="09…" dir="ltr"></div>
                    <div class="cl-fg"><label>آدرس</label><input name="owner_address" placeholder="شیراز، خ…"></div>
                    <div class="cl-section-divider">طرف دوم — پیمانکار</div>
                    <div class="cl-fg"><label>نام و نام خانوادگی *</label><input name="contractor_name" required placeholder="محمد محمدی"></div>
                    <div class="cl-fg"><label>کد ملی</label><input name="contractor_nid" dir="ltr"></div>
                    <div class="cl-fg"><label>تلفن</label><input name="contractor_phone" dir="ltr"></div>
                    <div class="cl-fg"><label>آدرس</label><input name="contractor_address"></div>
                    <div class="cl-section-divider">مشخصات ملک</div>
                    <div class="cl-fg"><label>توضیح ملک / پلاک</label><input name="parcel_description" placeholder="پلاک ثبتی ۱۲۳/۴"></div>
                    <div class="cl-fg"><label>کد نوسازی</label><input name="renovation_code"></div>
                    <div class="cl-fg"><label>مساحت (م²)</label><input name="area_sqm" type="number" placeholder="200"></div>
                    <div class="cl-fg"><label>طبقات مجاز</label><input name="floors" type="number" placeholder="4"></div>
                    <div class="cl-fg"><label>شهر</label><input name="city" value="شیراز"></div>
                    <div></div>
                    <div class="cl-section-divider">شرایط مالی</div>
                    <div class="cl-fg"><label>سهم مالک (%)</label><input name="owner_percent" type="number" value="50" min="0" max="100"></div>
                    <div class="cl-fg"><label>سهم پیمانکار (%)</label><input name="contractor_percent" type="number" value="50" min="0" max="100"></div>
                    <div class="cl-fg"><label>مدت اجرا (ماه)</label><input name="duration_months" type="number" value="24" min="1"></div>
                    <div class="cl-fg"><label>پیش‌پرداخت (تومان)</label><input name="advance_amount" type="number" placeholder="500000000"></div>
                    <div class="cl-fg"><label>جریمه روزانه (تومان)</label><input name="penalty_daily" type="number" placeholder="1000000"></div>
                    <div class="cl-fg"><label>مبلغ کل (ریال)</label><input name="total_amount" type="number" placeholder="0"></div>
                </div>
                </form>
            </div>
            <div class="cl-modal-actions">
                <button class="cl-btn" data-close>انصراف</button>
                <button class="cl-btn" id="cl-preview-btn" style="background:#eff6ff;color:#1d4ed8;border-color:#bfdbfe;">👁️ پیش‌نمایش</button>
                <button class="cl-btn cl-btn--orange" id="cl-save-tpl-btn">✅ ثبت قرارداد</button>
            </div>
        </div>`,document.body.appendChild(e);const t=()=>e.remove();e.querySelectorAll("[data-close]").forEach(a=>a.addEventListener("click",t)),e.addEventListener("click",a=>{a.target===e&&t()});const s=()=>Object.fromEntries(new FormData(e.querySelector("#cl-partner-form")).entries());e.querySelector("#cl-preview-btn").addEventListener("click",async()=>{var i;const a=e.querySelector("#cl-partner-preview");a.innerHTML='<div style="text-align:center;padding:20px;"><div class="acc-spinner"></div></div>',a.style.display="block";try{const n=await this.api.get("/contracts/template/partnership-construction",s());a.innerHTML=((i=n==null?void 0:n.data)==null?void 0:i.html)??"<p>خطا</p>"}catch{a.innerHTML='<p style="color:red">خطا در ارتباط با سرور</p>'}}),e.querySelector("#cl-save-tpl-btn").addEventListener("click",async()=>{const a=e.querySelector("#cl-save-tpl-btn");a.disabled=!0,a.textContent="⏳ در حال ثبت…";try{const i=await this.api.post("/contracts/from-template",s());i!=null&&i.contract_id&&(t(),this._toast("قرارداد مشارکت ثبت شد","✅"),await this._loadList(),this._openDetail({id:i.contract_id}))}catch(i){alert("خطا: "+((i==null?void 0:i.message)||"")),a.disabled=!1,a.textContent="✅ ثبت قرارداد"}})}_modal(e,t,s,a,i="#3b82f6"){const n=document.createElement("div");n.className="cl-overlay",n.innerHTML=`
        <div class="cl-modal">
            <div class="cl-modal-head">
                <div class="cl-modal-title">${e}</div>
                <button class="cl-btn cl-btn--xs" data-close>✕</button>
            </div>
            <div class="cl-modal-body"><form>${t}</form></div>
            <div class="cl-modal-actions">
                <button class="cl-btn" data-close>انصراف</button>
                <button class="cl-btn" style="background:${i};color:#fff;border-color:${i};" data-submit>${s}</button>
            </div>
        </div>`,document.body.appendChild(n);const r=()=>n.remove();return n.querySelectorAll("[data-close]").forEach(o=>o.addEventListener("click",r)),n.addEventListener("click",o=>{o.target===n&&r()}),n.querySelector("[data-submit]").addEventListener("click",async()=>{const o=n.querySelector("[data-submit]"),l=n.querySelector("form");if(l.reportValidity()){o.disabled=!0,o.textContent="⏳…";try{await a(Object.fromEntries(new FormData(l).entries()),o,r)}catch(c){alert("خطا: "+((c==null?void 0:c.message)||"")),o.disabled=!1,o.textContent=s}}}),n}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}_toast(e,t="✅",s="#1e293b"){const a=document.createElement("div");a.className="cl-toast",a.style.background=s,a.innerHTML=`${t} ${e}`,document.body.appendChild(a),setTimeout(()=>{a.style.opacity="0",a.style.transition="opacity .3s",setTimeout(()=>a.remove(),300)},2800)}}const Ms={purchase:"#3b82f6",construction:"#f97316",sale:"#10b981",lease:"#8b5cf6",consulting:"#6b7280"},yr={purchase:"خرید ملک",construction:"پیمانکاری",sale:"فروش واحد",lease:"اجاره",consulting:"مشاوره"};class _r extends x{async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._render()}async _render(){const e=this.ref("root");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t=await this.api.get("/contracts/payments/upcoming"),s=(t==null?void 0:t.data)??[];this._renderPayments(e,s)}catch{e.innerHTML='<div class="acc-error">خطا در بارگذاری</div>'}}_renderPayments(e,t){if(!t.length){e.innerHTML='<div class="acc-empty" style="margin-top:40px;">هیچ قسط معوقی وجود ندارد ✅</div>';return}const s=new Date().toISOString().split("T")[0],a=t.filter(u=>u.due_date&&u.due_date<s),i=t.filter(u=>!u.due_date||u.due_date<s?!1:(new Date(u.due_date)-new Date(s))/864e5<=7),n=t.filter(u=>!u.due_date||u.due_date<s?!1:(new Date(u.due_date)-new Date(s))/864e5>7),r=a.reduce((u,f)=>u+parseFloat(f.amount||0),0),o=i.reduce((u,f)=>u+parseFloat(f.amount||0),0),l=n.reduce((u,f)=>u+parseFloat(f.amount||0),0),c=u=>new Intl.NumberFormat("fa-IR").format(Math.round(u)),d=u=>`
            <div class="contract-cal-item" style="border-right:3px solid ${Ms[u.contract_type]||"#94a3b8"}">
                <div class="contract-cal-item__meta">
                    <span class="contract-type-badge" style="background:${Ms[u.contract_type]||"#94a3b8"};font-size:10px;">
                        ${yr[u.contract_type]||u.contract_type}
                    </span>
                    ${u.contract_number?`<span style="font-size:11px;color:#94a3b8;">№ ${u.contract_number}</span>`:""}
                    ${u.parcel_code?`<span style="font-size:11px;color:#64748b;">📍 پلاک ${u.parcel_code}</span>`:""}
                </div>
                <div class="contract-cal-item__title">${u.contract_title||"—"}</div>
                <div class="contract-cal-item__desc">${u.description||`قسط ${u.installment_no}`}</div>
                <div style="display:flex;justify-content:space-between;align-items:center;margin-top:6px;">
                    <b style="font-size:15px;color:#1e293b;">${c(u.amount)} ریال</b>
                    <span style="font-size:11px;color:#64748b;">
                        📅 ${u.due_date}
                        ${u.days_until!==null?u.days_until<0?`<span style="color:#ef4444;">(${Math.abs(u.days_until)} روز گذشته)</span>`:`<span style="color:#64748b;">(${u.days_until} روز دیگر)</span>`:""}
                    </span>
                </div>
            </div>`,h=(u,f,m,b)=>m.length?`
            <div class="contract-cal-section">
                <div class="contract-cal-section__header" style="border-right:4px solid ${f};">
                    <span>${u}</span>
                    <span class="contract-cal-total">${c(b)} ریال — ${m.length} قسط</span>
                </div>
                ${m.map(d).join("")}
            </div>`:"";e.innerHTML=`
        <div style="max-width:700px;">
            <div style="display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:24px;">
                <div class="contract-kpi-card" style="border-top:3px solid #ef4444;">
                    <div class="contract-kpi-label">⚠️ سررسیدگذشته</div>
                    <div class="contract-kpi-value" style="color:#ef4444;">${c(r)}</div>
                    <div class="contract-kpi-sub">${a.length} قسط — ریال</div>
                </div>
                <div class="contract-kpi-card" style="border-top:3px solid #f59e0b;">
                    <div class="contract-kpi-label">📅 این هفته</div>
                    <div class="contract-kpi-value" style="color:#d97706;">${c(o)}</div>
                    <div class="contract-kpi-sub">${i.length} قسط — ریال</div>
                </div>
                <div class="contract-kpi-card" style="border-top:3px solid #3b82f6;">
                    <div class="contract-kpi-label">🔜 آینده</div>
                    <div class="contract-kpi-value" style="color:#3b82f6;">${c(l)}</div>
                    <div class="contract-kpi-sub">${n.length} قسط — ریال</div>
                </div>
            </div>
            ${h("⚠️ سررسیدگذشته — فوری","#ef4444",a,r)}
            ${h("📅 این هفته","#f59e0b",i,o)}
            ${h("🔜 اقساط آینده","#3b82f6",n,l)}
            ${!a.length&&!i.length&&!n.length?'<div class="acc-empty" style="margin-top:40px;">همه اقساط تسویه شده است ✅</div>':""}
        </div>`}}const ut=[{key:"list",icon:"📋",title:"قراردادها",Class:gr},{key:"calendar",icon:"💰",title:"برنامه پرداخت",Class:_r}];class Rs extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._active="list",this._sections={}}async template(){const t=ut.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
            </div>
        `).join(""),s=ut.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>this.on(t,"click",()=>this._switch(t.dataset.section))),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=ut.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(Rs,"title","📋 قراردادها"),E.register("contracts",Rs);const qs={available:"#10b981",reserved:"#f59e0b",sold:"#3b82f6",transferred:"#6b7280",cancelled:"#ef4444"},De={available:"آزاد",reserved:"رزروشده",sold:"فروخته‌شده",transferred:"تحویل‌شده",cancelled:"لغوشده"},ft={residential:"مسکونی",commercial:"تجاری",office:"اداری",parking:"پارکینگ",storage:"انباری"},mt={residential:"🏠",commercial:"🏪",office:"🏢",parking:"🚗",storage:"📦"},Hs={north:"شمالی",south:"جنوبی",east:"شرقی",west:"غربی",corner:"گوشه",inner:"حیاطی"};class xr extends x{constructor(e={}){super(e),this._units=[],this._projects=[],this._filter={project_id:"",status:"",type:""}}async template(){return'<div data-ref="root"></div>'}async afterRender(){try{const e=await this.api.get("/pc/projects",{per_page:200});this._projects=(e==null?void 0:e.data)??[]}catch{}await this._render()}async _render(){const e=this.ref("root"),t='<option value="">همه پروژه‌ها</option>'+this._projects.map(s=>`<option value="${s.id}">${this.escape(s.name)}</option>`).join("");e.innerHTML=`
        <div class="unit-toolbar">
            <select class="event-type-filter" data-ref="projSel">${t}</select>
            <select class="event-type-filter" data-ref="statusSel">
                <option value="">همه وضعیت‌ها</option>
                ${Object.entries(De).map(([s,a])=>`<option value="${s}">${a}</option>`).join("")}
            </select>
            <select class="event-type-filter" data-ref="typeSel">
                <option value="">همه انواع</option>
                ${Object.entries(ft).map(([s,a])=>`<option value="${s}">${a}</option>`).join("")}
            </select>
            <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">➕ واحد جدید</button>
            <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
        </div>
        <!-- KPI -->
        <div class="unit-kpi-row" data-ref="kpiRow"></div>
        <!-- پلان طبقات -->
        <div data-ref="floorPlan" class="unit-floor-plan"></div>`,e.querySelectorAll("[data-ref]").forEach(s=>{this.refs[s.dataset.ref]=s}),this.on(this.ref("projSel"),"change",()=>{this._filter.project_id=this.ref("projSel").value,this._load()}),this.on(this.ref("statusSel"),"change",()=>{this._filter.status=this.ref("statusSel").value,this._load()}),this.on(this.ref("typeSel"),"change",()=>{this._filter.type=this.ref("typeSel").value,this._load()}),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openUnitModal()),await this._load()}async _load(){this.ref("floorPlan").innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';const e={};this._filter.project_id&&(e.project_id=this._filter.project_id),this._filter.status&&(e.status=this._filter.status),this._filter.type&&(e.type=this._filter.type);try{const t=await this.api.get("/units",e);this._units=(t==null?void 0:t.data)??[],this._renderKPI(),this._renderFloorPlan()}catch{this.ref("floorPlan").innerHTML='<div class="acc-error">خطا در بارگذاری</div>'}}_renderKPI(){const e=this.ref("kpiRow"),t=this._units.length,s=this._units.filter(c=>c.status==="available").length,a=this._units.filter(c=>c.status==="reserved").length,i=this._units.filter(c=>c.status==="sold").length,n=this._units.filter(c=>c.status==="transferred").length,r=c=>new Intl.NumberFormat("fa-IR").format(Math.round(c)),o=this._units.reduce((c,d)=>c+parseFloat(d.base_price||0),0),l=this._units.filter(c=>["sold","transferred"].includes(c.status)).reduce((c,d)=>c+parseFloat(d.base_price||0),0);e.innerHTML=`
        <div class="unit-kpi" style="border-top:3px solid #1e293b;">
            <div class="unit-kpi-label">کل واحدها</div>
            <div class="unit-kpi-value">${t}</div>
        </div>
        <div class="unit-kpi" style="border-top:3px solid #10b981;">
            <div class="unit-kpi-label">🟢 آزاد</div>
            <div class="unit-kpi-value" style="color:#10b981;">${s}</div>
        </div>
        <div class="unit-kpi" style="border-top:3px solid #f59e0b;">
            <div class="unit-kpi-label">🟡 رزروشده</div>
            <div class="unit-kpi-value" style="color:#f59e0b;">${a}</div>
        </div>
        <div class="unit-kpi" style="border-top:3px solid #3b82f6;">
            <div class="unit-kpi-label">🔵 فروخته‌شده</div>
            <div class="unit-kpi-value" style="color:#3b82f6;">${i+n}</div>
        </div>
        <div class="unit-kpi" style="border-top:3px solid #8b5cf6;">
            <div class="unit-kpi-label">💰 ارزش فروخته‌شده</div>
            <div class="unit-kpi-value" style="color:#8b5cf6;font-size:14px;">${r(l)}</div>
            <div class="unit-kpi-sub">از ${r(o)} ریال</div>
        </div>`}_renderFloorPlan(){const e=this.ref("floorPlan");if(!this._units.length){e.innerHTML='<div class="acc-empty" style="margin-top:40px;">واحدی ثبت نشده است.</div>';return}const t={};this._units.forEach(a=>{const i=a.floor??0;t[i]||(t[i]=[]),t[i].push(a)});const s=Object.keys(t).map(Number).sort((a,i)=>i-a);e.innerHTML="",s.forEach(a=>{const i=t[a],n=document.createElement("div");n.className="unit-floor",n.innerHTML=`
                <div class="unit-floor-label">
                    ${a===0?"همکف":a===-1?"زیرزمین":`طبقه ${a}`}
                    <span style="font-size:11px;color:#94a3b8;margin-right:6px;">${i.length} واحد</span>
                </div>
                <div class="unit-floor-cells">
                    ${i.map(r=>{const o=qs[r.status]||"#94a3b8",l=mt[r.type]||"🏢",c=r.customer_name?`<div class="unit-cell-buyer">👤 ${this.escape(r.customer_name)}</div>`:"";return`
                        <div class="unit-cell" style="border-top:3px solid ${o};"
                             data-id="${r.id}" title="${De[r.status]||r.status}">
                            <div class="unit-cell-icon">${l}</div>
                            <div class="unit-cell-num">${this.escape(r.unit_number)}</div>
                            ${r.area_sqm?`<div class="unit-cell-area">${r.area_sqm} م²</div>`:""}
                            <div class="unit-cell-status" style="color:${o};">${De[r.status]||r.status}</div>
                            ${c}
                        </div>`}).join("")}
                </div>`,n.querySelectorAll(".unit-cell").forEach(r=>{const o=this._units.find(l=>String(l.id)===r.dataset.id);o&&r.addEventListener("click",()=>this._openUnitDetail(o))}),e.appendChild(n)})}_openUnitDetail(e){var r,o;const t=qs[e.status]||"#94a3b8",s=l=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(l||0))),a=(l,c)=>c?`<div class="gis-info-row"><span class="gis-info-label">${l}</span><span class="gis-info-value">${c}</span></div>`:"",i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
        <div class="acc-modal" style="max-width:440px;">
            <button class="acc-modal__close">✕</button>
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;">
                <div>
                    <div style="font-size:18px;font-weight:800;color:#1e293b;">
                        ${mt[e.type]||"🏢"} واحد ${this.escape(e.unit_number)}
                    </div>
                    <div style="font-size:12px;color:#64748b;">
                        ${e.floor===0?"همکف":e.floor===-1?"زیرزمین":"طبقه "+e.floor}
                        ${e.project_name?" — "+this.escape(e.project_name):""}
                    </div>
                </div>
                <span style="background:${t};color:#fff;padding:4px 12px;border-radius:8px;font-size:12px;font-weight:700;">
                    ${De[e.status]||e.status}
                </span>
            </div>

            <div class="gis-info-divider">مشخصات</div>
            ${a("نوع",ft[e.type])}
            ${a("مساحت ناخالص",e.area_sqm?e.area_sqm+" م²":null)}
            ${a("مساحت مفید",e.area_useful_sqm?e.area_useful_sqm+" م²":null)}
            ${a("دید",Hs[e.view_direction])}
            <div style="display:flex;gap:10px;margin:8px 0;font-size:12px;color:#64748b;">
                ${e.has_parking=="1"?"<span>🚗 پارکینگ</span>":""}
                ${e.has_storage=="1"?"<span>📦 انباری</span>":""}
                ${e.has_balcony=="1"?"<span>🏠 بالکن</span>":""}
            </div>

            <div class="gis-info-divider">قیمت</div>
            ${a("قیمت پایه",e.base_price?s(e.base_price)+" ریال":null)}
            ${a("قیمت هر متر",e.price_per_sqm?s(e.price_per_sqm)+" ریال":null)}

            ${e.customer_name?`
            <div class="gis-info-divider">خریدار</div>
            <div style="background:#eff6ff;border-radius:8px;padding:10px 12px;">
                <div style="font-weight:700;">👤 ${this.escape(e.customer_name)}</div>
                ${e.customer_phone?`<div style="font-size:12px;color:#64748b;">📞 ${e.customer_phone}</div>`:""}
            </div>`:""}

            <div class="acc-modal__actions" style="margin-top:16px;">
                <button class="acc-btn acc-btn--secondary" data-action="edit">✏️ ویرایش واحد</button>
                ${e.status==="available"?'<button class="acc-btn acc-btn--success" data-action="sell">💰 رزرو/فروش</button>':""}
                ${["reserved","sold"].includes(e.status)?'<button class="acc-btn acc-btn--primary" data-action="view-sale">📋 مشاهده فروش</button>':""}
            </div>
        </div>`,document.body.appendChild(i);const n=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",n),i.addEventListener("click",l=>{l.target===i&&n()}),(r=i.querySelector('[data-action="edit"]'))==null||r.addEventListener("click",()=>{n(),this._openUnitModal(e)}),(o=i.querySelector('[data-action="sell"]'))==null||o.addEventListener("click",()=>{n(),this._openSaleModal(e)})}_openUnitModal(e=null){const t=!!e,s=e||{},a='<option value="">— بدون پروژه —</option>'+this._projects.map(u=>`<option value="${u.id}" ${s.project_id==u.id?"selected":""}>${this.escape(u.name)}</option>`).join(""),i=u=>s.type===u?"selected":"",n=u=>s.view_direction===u?"selected":"",r=document.createElement("div");r.className="acc-modal-overlay",r.innerHTML=`
        <div class="acc-modal" style="max-width:500px;max-height:90vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🏢 ${t?"ویرایش":"افزودن"} واحد</div>
            <form>
                <div class="acc-form-group"><label>پروژه</label>
                    <select name="project_id">${a}</select>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>شماره واحد *</label>
                        <input name="unit_number" required value="${this.escape(s.unit_number||"")}">
                    </div>
                    <div class="acc-form-group"><label>طبقه *</label>
                        <input name="floor" type="number" value="${s.floor??"0"}" required>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>بلوک/برج</label>
                        <input name="block" value="${this.escape(s.block||"")}">
                    </div>
                    <div class="acc-form-group"><label>نوع</label>
                        <select name="type">
                            <option value="residential" ${i("residential")}>🏠 مسکونی</option>
                            <option value="commercial"  ${i("commercial")}>🏪 تجاری</option>
                            <option value="office"      ${i("office")}>🏢 اداری</option>
                            <option value="parking"     ${i("parking")}>🚗 پارکینگ</option>
                            <option value="storage"     ${i("storage")}>📦 انباری</option>
                        </select>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>مساحت ناخالص (م²)</label>
                        <input name="area_sqm" type="number" step="0.1" value="${s.area_sqm||""}">
                    </div>
                    <div class="acc-form-group"><label>مساحت مفید (م²)</label>
                        <input name="area_useful_sqm" type="number" step="0.1" value="${s.area_useful_sqm||""}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>قیمت پایه (ریال)</label>
                        <input name="base_price" type="number" id="base-price-inp" value="${s.base_price||""}">
                    </div>
                    <div class="acc-form-group"><label>قیمت هر متر (ریال)</label>
                        <input name="price_per_sqm" type="number" id="psqm-inp" value="${s.price_per_sqm||""}">
                    </div>
                </div>
                <div class="acc-form-group"><label>دید</label>
                    <select name="view_direction">
                        <option value="">— بدون انتخاب —</option>
                        ${Object.entries(Hs).map(([u,f])=>`<option value="${u}" ${n(u)}>${f}</option>`).join("")}
                    </select>
                </div>
                <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin:10px 0;">
                    <label style="font-size:13px;display:flex;gap:6px;align-items:center;">
                        <input type="checkbox" name="has_parking" value="1" ${s.has_parking=="1"?"checked":""}> 🚗 پارکینگ
                    </label>
                    <label style="font-size:13px;display:flex;gap:6px;align-items:center;">
                        <input type="checkbox" name="has_storage" value="1" ${s.has_storage=="1"?"checked":""}> 📦 انباری
                    </label>
                    <label style="font-size:13px;display:flex;gap:6px;align-items:center;">
                        <input type="checkbox" name="has_balcony" value="1" ${s.has_balcony=="1"?"checked":""}> 🏠 بالکن
                    </label>
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="2">${this.escape(s.notes||"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"افزودن واحد"}</button>
                </div>
            </form>
        </div>`,document.body.appendChild(r);const o=()=>r.remove();r.querySelector(".acc-modal__close").addEventListener("click",o),r.querySelector('[data-action="cancel"]').addEventListener("click",o),r.addEventListener("click",u=>{u.target===r&&o()});const l=r.querySelector('[name="area_sqm"]'),c=r.querySelector('[name="price_per_sqm"]'),d=r.querySelector('[name="base_price"]'),h=()=>{const u=parseFloat(l.value)||0,f=parseFloat(c.value)||0;u>0&&f>0&&!d.value&&(d.value=Math.round(u*f))};c.addEventListener("input",h),l.addEventListener("input",h),r.querySelector("form").addEventListener("submit",async u=>{u.preventDefault();const f=Object.fromEntries(new FormData(u.target).entries());["has_parking","has_storage","has_balcony"].forEach(b=>{f[b]=f[b]?1:0}),["block","view_direction","notes"].forEach(b=>{f[b]||delete f[b]});const m=u.target.querySelector('[type="submit"]');m.disabled=!0;try{t?await this.api.put(`/units/${e.id}`,f):await this.api.post("/units",f),o(),this._toast(t?"✅ واحد به‌روز شد":"✅ واحد افزوده شد"),await this._load()}catch(b){alert("خطا: "+((b==null?void 0:b.message)||"")),m.disabled=!1}})}async _openSaleModal(e){let t=[];try{const r=await this.api.get("/sale-customers");t=(r==null?void 0:r.data)??[]}catch{}const s='<option value="">— انتخاب مشتری —</option>'+t.map(r=>`<option value="${r.id}">${this.escape(r.name)} ${r.phone?"— "+r.phone:""}</option>`).join(""),a=r=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(r||0))),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
        <div class="acc-modal" style="max-width:460px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">💰 رزرو/فروش واحد ${this.escape(e.unit_number)}</div>
            <div style="background:#f0fdf4;border-radius:8px;padding:8px 12px;font-size:12px;color:#166534;margin-bottom:14px;">
                ${mt[e.type]||"🏢"} ${ft[e.type]} | طبقه ${e.floor} |
                ${e.area_sqm?e.area_sqm+" م² |":""} قیمت پایه: ${a(e.base_price)} ریال
            </div>
            <form>
                <div class="acc-form-group">
                    <label>مشتری *</label>
                    <select name="customer_id" required>${s}</select>
                    <button type="button" class="acc-btn acc-btn--secondary acc-btn--sm" style="margin-top:6px;" data-action="new-customer">
                        ➕ مشتری جدید
                    </button>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>قیمت فروش (ریال) *</label>
                        <input name="sale_price" type="number" required value="${e.base_price||""}">
                    </div>
                    <div class="acc-form-group"><label>نوع پرداخت</label>
                        <select name="payment_type">
                            <option value="installment">اقساطی</option>
                            <option value="cash">نقدی</option>
                            <option value="mixed">ترکیبی</option>
                        </select>
                    </div>
                </div>
                <div class="acc-form-group"><label>تاریخ رزرو</label>
                    <input name="reservation_date" type="date" value="${new Date().toISOString().split("T")[0]}">
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="2"></textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--success">✅ ثبت رزرو</button>
                </div>
            </form>
        </div>`,document.body.appendChild(i);const n=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",n),i.querySelector('[data-action="cancel"]').addEventListener("click",n),i.addEventListener("click",r=>{r.target===i&&n()}),i.querySelector('[data-action="new-customer"]').addEventListener("click",()=>{n(),this._openQuickCustomerModal(e)}),i.querySelector("form").addEventListener("submit",async r=>{r.preventDefault();const o=Object.fromEntries(new FormData(r.target).entries());o.unit_id=e.id;const l=r.target.querySelector('[type="submit"]');l.disabled=!0;try{await this.api.post("/sales",o),n(),this._toast("✅ رزرو ثبت شد","#10b981"),await this._load()}catch(c){alert("خطا: "+((c==null?void 0:c.message)||"")),l.disabled=!1}})}_openQuickCustomerModal(e){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:380px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">👤 مشتری جدید</div>
            <form>
                <div class="acc-form-group"><label>نام *</label><input name="name" required></div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد ملی</label><input name="national_id"></div>
                    <div class="acc-form-group"><label>تلفن</label><input name="phone" type="tel"></div>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ثبت و ادامه</button>
                </div>
            </form>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector('[data-action="cancel"]').addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries()),n=a.target.querySelector('[type="submit"]');n.disabled=!0;try{await this.api.post("/sale-customers",i),s(),this._toast("✅ مشتری ثبت شد"),this._openSaleModal(e)}catch(r){alert("خطا: "+((r==null?void 0:r.message)||"")),n.disabled=!1}})}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;direction:rtl;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const vt={reserved:"#f59e0b",active:"#3b82f6",completed:"#10b981",cancelled:"#ef4444"},bt={reserved:"رزروشده",active:"قرارداد‌شده",completed:"تحویل‌شده",cancelled:"لغوشده"},wr={residential:"مسکونی",commercial:"تجاری",office:"اداری",parking:"پارکینگ",storage:"انباری"};class $r extends x{constructor(e={}){super(e),this._sales=[],this._filter={status:"",project_id:""},this._projects=[]}async template(){return'<div data-ref="root"></div>'}async afterRender(){try{const e=await this.api.get("/pc/projects",{per_page:200});this._projects=(e==null?void 0:e.data)??[]}catch{}await this._render()}async _render(){const e=this.ref("root"),t='<option value="">همه پروژه‌ها</option>'+this._projects.map(s=>`<option value="${s.id}">${this.escape(s.name)}</option>`).join("");e.innerHTML=`
        <div style="display:flex;gap:10px;align-items:center;margin-bottom:16px;flex-wrap:wrap;">
            <select class="event-type-filter" data-ref="projSel">${t}</select>
            <select class="event-type-filter" data-ref="statusSel">
                <option value="">همه وضعیت‌ها</option>
                ${Object.entries(bt).map(([s,a])=>`<option value="${s}">${a}</option>`).join("")}
            </select>
            <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
            <span data-ref="countLbl" style="font-size:12px;color:#94a3b8;"></span>
        </div>
        <!-- Kanban Pipeline -->
        <div class="sales-pipeline" data-ref="pipeline"></div>`,e.querySelectorAll("[data-ref]").forEach(s=>{this.refs[s.dataset.ref]=s}),this.on(this.ref("projSel"),"change",()=>{this._filter.project_id=this.ref("projSel").value,this._load()}),this.on(this.ref("statusSel"),"change",()=>{this._filter.status=this.ref("statusSel").value,this._load()}),this.on(this.ref("refreshBtn"),"click",()=>this._load()),await this._load()}async _load(){this.ref("pipeline").innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';const e={};this._filter.project_id&&(e.project_id=this._filter.project_id),this._filter.status&&(e.status=this._filter.status);try{const t=await this.api.get("/sales",e);this._sales=(t==null?void 0:t.data)??[],this.ref("countLbl").textContent=`${this._sales.length} فروش`,this._renderPipeline()}catch{this.ref("pipeline").innerHTML='<div class="acc-error">خطا</div>'}}_renderPipeline(){const e=this.ref("pipeline"),t=i=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(i||0))),s=[{key:"reserved",label:"🟡 رزروشده"},{key:"active",label:"🔵 قرارداد‌شده"},{key:"completed",label:"✅ تحویل‌شده"}];if(!this._sales.length){e.innerHTML='<div class="acc-empty">فروشی ثبت نشده است.</div>';return}this._filter.status?e.innerHTML=`<div class="sales-list">${this._sales.map(i=>this._saleCard(i,t)).join("")}</div>`:e.innerHTML=`
            <div class="sales-kanban">
                ${s.map(i=>{const n=this._sales.filter(o=>o.status===i.key),r=n.reduce((o,l)=>o+parseFloat(l.sale_price||0),0);return`
                    <div class="sales-kanban-col">
                        <div class="sales-kanban-header" style="border-top:3px solid ${vt[i.key]}">
                            <span>${i.label}</span>
                            <span class="sales-kanban-count">${n.length}</span>
                        </div>
                        <div style="font-size:11px;color:#64748b;margin-bottom:8px;">${t(r)} ریال</div>
                        <div class="sales-kanban-body">
                            ${n.map(o=>this._saleCard(o,t)).join("")||'<div class="gis-empty-tab">—</div>'}
                        </div>
                    </div>`}).join("")}
            </div>`,e.querySelectorAll("[data-sale-id]").forEach(i=>{const n=this._sales.find(r=>String(r.id)===i.dataset.saleId);n&&i.addEventListener("click",()=>this._openSaleDetail(n))})}_saleCard(e,t){const s=vt[e.status]||"#94a3b8",a=e.sale_price>0?Math.round(e.paid_amount/e.sale_price*100):0;return`
        <div class="sale-card" data-sale-id="${e.id}" style="border-right:3px solid ${s};cursor:pointer;">
            <div style="display:flex;justify-content:space-between;align-items:start;">
                <div>
                    <div style="font-weight:700;font-size:13px;">واحد ${this.escape(e.unit_number)}</div>
                    <div style="font-size:11px;color:#64748b;">
                        ${e.project_name?this.escape(e.project_name)+" | ":""}
                        طبقه ${e.floor} | ${wr[e.unit_type]||e.unit_type}
                    </div>
                </div>
                <span style="font-size:10px;color:${s};font-weight:700;">${bt[e.status]}</span>
            </div>
            <div style="font-size:12px;margin-top:6px;">
                👤 ${e.customer_name?this.escape(e.customer_name):"—"}
            </div>
            <div style="font-weight:700;font-size:13px;margin-top:4px;">${t(e.sale_price)} ریال</div>
            ${e.sale_price>0?`
            <div class="contract-progress-bar" style="margin-top:6px;">
                <div class="contract-progress-fill" style="width:${a}%;background:${s}"></div>
            </div>
            <div style="font-size:10px;color:#94a3b8;margin-top:2px;">${a}٪ پرداخت‌شده</div>`:""}
        </div>`}_openSaleDetail(e){var r,o,l;const t=c=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(c||0))),s=vt[e.status]||"#94a3b8",a=e.sale_price>0?Math.round(parseFloat(e.paid_amount||0)/parseFloat(e.sale_price)*100):0,i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
        <div class="acc-modal" style="max-width:460px;">
            <button class="acc-modal__close">✕</button>
            <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;">
                <div>
                    <div style="font-size:16px;font-weight:800;">واحد ${this.escape(e.unit_number)} — طبقه ${e.floor}</div>
                    <div style="font-size:12px;color:#64748b;">${e.project_name||""}</div>
                </div>
                <span style="background:${s};color:#fff;padding:4px 10px;border-radius:8px;font-size:11px;font-weight:700;">
                    ${bt[e.status]}
                </span>
            </div>

            <div class="gis-info-divider">خریدار</div>
            <div style="font-weight:700;">👤 ${this.escape(e.customer_name||"—")}</div>
            ${e.customer_phone?`<div style="font-size:12px;color:#64748b;">📞 ${e.customer_phone}</div>`:""}

            <div class="gis-info-divider">مالی</div>
            <div class="gis-info-row"><span class="gis-info-label">قیمت فروش</span><span class="gis-info-value">${t(e.sale_price)} ریال</span></div>
            <div class="gis-info-row"><span class="gis-info-label">پرداخت‌شده</span><span class="gis-info-value" style="color:#10b981;">${t(e.paid_amount||0)} ریال</span></div>
            <div class="gis-info-row"><span class="gis-info-label">مانده</span><span class="gis-info-value" style="color:#ef4444;">${t(parseFloat(e.sale_price)-parseFloat(e.paid_amount||0))} ریال</span></div>
            <div class="contract-progress-bar"><div class="contract-progress-fill" style="width:${a}%;background:${s}"></div></div>

            <div class="gis-info-divider">تاریخ‌ها</div>
            ${e.reservation_date?`<div class="gis-info-row"><span class="gis-info-label">رزرو</span><span class="gis-info-value">${e.reservation_date}</span></div>`:""}
            ${e.sale_contract_date?`<div class="gis-info-row"><span class="gis-info-label">قرارداد</span><span class="gis-info-value">${e.sale_contract_date}</span></div>`:""}
            ${e.transfer_date?`<div class="gis-info-row"><span class="gis-info-label">تحویل</span><span class="gis-info-value">${e.transfer_date}</span></div>`:""}

            <div class="acc-modal__actions" style="margin-top:16px;flex-wrap:wrap;gap:8px;">
                ${e.status==="reserved"?'<button class="acc-btn acc-btn--primary" data-action="activate">📋 ثبت قرارداد</button>':""}
                ${e.status==="active"?'<button class="acc-btn acc-btn--success" data-action="transfer">🏠 تحویل واحد</button>':""}
                ${e.status!=="completed"&&e.status!=="cancelled"?'<button class="acc-btn acc-btn--danger" data-action="cancel">❌ لغو فروش</button>':""}
            </div>
        </div>`,document.body.appendChild(i);const n=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",n),i.addEventListener("click",c=>{c.target===i&&n()}),(r=i.querySelector('[data-action="activate"]'))==null||r.addEventListener("click",async()=>{const c=prompt("تاریخ انعقاد قرارداد (YYYY-MM-DD):",new Date().toISOString().split("T")[0]);c&&(await this.api.put(`/sales/${e.id}`,{status:"active",sale_contract_date:c}),n(),this._toast("✅ قرارداد ثبت شد","#3b82f6"),this._load())}),(o=i.querySelector('[data-action="transfer"]'))==null||o.addEventListener("click",async()=>{const c=prompt("تاریخ تحویل (YYYY-MM-DD):",new Date().toISOString().split("T")[0]);c&&(await this.api.post(`/sales/${e.id}/transfer`,{transfer_date:c}),n(),this._toast("✅ تحویل واحد ثبت شد","#10b981"),this._load())}),(l=i.querySelector('[data-action="cancel"]'))==null||l.addEventListener("click",async()=>{confirm("لغو این فروش؟")&&(await this.api.delete(`/sales/${e.id}`),n(),this._toast("❌ فروش لغو شد","#ef4444"),this._load())})}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;direction:rtl;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}class kr extends x{constructor(e={}){super(e),this._customers=[],this._search=""}async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._render()}async _render(){const e=this.ref("root");e.innerHTML=`
        <div style="display:flex;gap:10px;align-items:center;margin-bottom:16px;flex-wrap:wrap;">
            <input type="text" class="acc-input" data-ref="searchInp" placeholder="🔍 نام، کد ملی یا تلفن..."
                style="flex:1;min-width:200px;">
            <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">➕ مشتری جدید</button>
            <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
        </div>
        <div data-ref="body"></div>`,e.querySelectorAll("[data-ref]").forEach(t=>{this.refs[t.dataset.ref]=t}),this.on(this.ref("searchInp"),"input",()=>{this._search=this.ref("searchInp").value,this._load()}),this.on(this.ref("addBtn"),"click",()=>this._openCustomerModal()),this.on(this.ref("refreshBtn"),"click",()=>this._load()),await this._load()}async _load(){const e=this.ref("body");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';const t=this._search?{search:this._search}:{};try{const s=await this.api.get("/sale-customers",t);this._customers=(s==null?void 0:s.data)??[],this._renderList()}catch{e.innerHTML='<div class="acc-error">خطا</div>'}}_renderList(){const e=this.ref("body"),t=s=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(s||0)));if(!this._customers.length){e.innerHTML='<div class="acc-empty">مشتری‌ای ثبت نشده.</div>';return}e.innerHTML=`
        <div class="customer-grid">
            ${this._customers.map(s=>`
            <div class="customer-card" data-id="${s.id}">
                <div style="display:flex;justify-content:space-between;align-items:start;">
                    <div>
                        <div style="font-size:15px;font-weight:800;color:#1e293b;">
                            ${s.type==="company"?"🏢":"👤"} ${this.escape(s.name)}
                        </div>
                        ${s.company_name?`<div style="font-size:12px;color:#64748b;">🏢 ${this.escape(s.company_name)}</div>`:""}
                        ${s.national_id?`<div style="font-size:12px;color:#94a3b8;">کد ملی: ${s.national_id}</div>`:""}
                        ${s.phone?`<div style="font-size:12px;color:#64748b;">📞 ${s.phone}</div>`:""}
                    </div>
                    <div style="text-align:left;">
                        <div style="font-size:18px;font-weight:800;color:#3b82f6;">${s.sale_count||0}</div>
                        <div style="font-size:10px;color:#94a3b8;">واحد خریداری</div>
                    </div>
                </div>
                ${s.total_purchased>0?`
                <div style="font-size:12px;color:#10b981;margin-top:6px;font-weight:600;">
                    💰 مجموع خرید: ${t(s.total_purchased)} ریال
                </div>`:""}
                <div style="display:flex;gap:6px;margin-top:10px;">
                    <button class="gis-btn gis-btn--secondary gis-btn--sm" data-edit="${s.id}">✏️ ویرایش</button>
                    ${s.sale_count?"":`<button class="gis-btn gis-btn--danger gis-btn--sm" data-del="${s.id}">🗑️ حذف</button>`}
                </div>
            </div>`).join("")}
        </div>`,e.querySelectorAll("[data-edit]").forEach(s=>{const a=this._customers.find(i=>String(i.id)===s.dataset.edit);a&&s.addEventListener("click",()=>this._openCustomerModal(a))}),e.querySelectorAll("[data-del]").forEach(s=>{s.addEventListener("click",async()=>{if(confirm("حذف این مشتری؟"))try{await this.api.delete(`/sale-customers/${s.dataset.del}`),this._toast("🗑️ مشتری حذف شد"),this._load()}catch(a){alert("خطا: "+((a==null?void 0:a.message)||""))}})})}_openCustomerModal(e=null){const t=!!e,s=e||{},a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
        <div class="acc-modal" style="max-width:440px;max-height:90vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">👤 ${t?"ویرایش":"مشتری جدید"}</div>
            <form>
                <div style="display:flex;gap:12px;margin-bottom:12px;">
                    <label style="font-size:13px;display:flex;gap:6px;align-items:center;">
                        <input type="radio" name="type" value="individual" ${s.type!=="company"?"checked":""}> شخص حقیقی
                    </label>
                    <label style="font-size:13px;display:flex;gap:6px;align-items:center;">
                        <input type="radio" name="type" value="company" ${s.type==="company"?"checked":""}> شخص حقوقی
                    </label>
                </div>
                <div class="acc-form-group"><label>نام *</label>
                    <input name="name" required value="${this.escape(s.name||"")}">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد ملی / شناسه ملی</label>
                        <input name="national_id" value="${this.escape(s.national_id||"")}">
                    </div>
                    <div class="acc-form-group"><label>تلفن</label>
                        <input name="phone" type="tel" value="${this.escape(s.phone||"")}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تلفن دوم</label>
                        <input name="phone2" value="${this.escape(s.phone2||"")}">
                    </div>
                    <div class="acc-form-group"><label>ایمیل</label>
                        <input name="email" type="email" value="${this.escape(s.email||"")}">
                    </div>
                </div>
                <div class="acc-form-group"><label>نام شرکت</label>
                    <input name="company_name" value="${this.escape(s.company_name||"")}">
                </div>
                <div class="acc-form-group"><label>آدرس</label>
                    <textarea name="address" rows="2">${this.escape(s.address||"")}</textarea>
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="2">${this.escape(s.notes||"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"ثبت مشتری"}</button>
                </div>
            </form>
        </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector('[data-action="cancel"]').addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());["phone2","email","company_name","address","notes"].forEach(l=>{r[l]||delete r[l]});const o=n.target.querySelector('[type="submit"]');o.disabled=!0;try{t?await this.api.put(`/sale-customers/${e.id}`,r):await this.api.post("/sale-customers",r),i(),this._toast(t?"✅ ویرایش شد":"✅ مشتری ثبت شد"),this._load()}catch(l){alert("خطا: "+((l==null?void 0:l.message)||"")),o.disabled=!1}})}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;direction:rtl;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const gt=[{key:"units",icon:"🏢",title:"واحدها",Class:xr},{key:"sales",icon:"💰",title:"فروش",Class:$r},{key:"customers",icon:"👥",title:"مشتریان",Class:kr}];class Bs extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._active="units",this._sections={}}async template(){const t=gt.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
            </div>`).join(""),s=gt.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>`).join("");return`<div class="sp-section-nav" data-ref="navBar">${t}</div><div>${s}</div>`}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>this.on(t,"click",()=>this._switch(t.dataset.section))),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=gt.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(Bs,"title","🏢 فروش واحد"),E.register("unitsales",Bs);const fe={land:"خرید زمین",construction:"ساخت و ساز",permits:"مجوزها",design:"طراحی",marketing:"بازاریابی",finance_cost:"هزینه مالی",tax:"مالیات",sales_income:"درآمد فروش",investor:"آورده سرمایه‌گذار",loan:"تسهیلات",other:"سایر"},yt={land:"📍",construction:"🏗️",permits:"📋",design:"✏️",marketing:"📢",finance_cost:"💸",tax:"🏛️",sales_income:"💰",investor:"🤝",loan:"🏦",other:"📌"},Er={land:"#ef4444",construction:"#f97316",permits:"#f59e0b",design:"#8b5cf6",marketing:"#ec4899",finance_cost:"#dc2626",tax:"#b45309",sales_income:"#10b981",investor:"#3b82f6",loan:"#6366f1",other:"#94a3b8"};class Lr extends x{constructor(e={}){super(e),this._projects=[],this._projectId=null,this._data=null}async template(){return'<div data-ref="root"></div>'}async afterRender(){try{const e=await this.api.get("/pc/projects",{per_page:200});this._projects=(e==null?void 0:e.data)??[]}catch{}await this._render()}async _render(){const e=this.ref("root"),t='<option value="">— انتخاب پروژه —</option>'+this._projects.map(s=>`<option value="${s.id}" ${this._projectId==s.id?"selected":""}>${this.escape(s.name)}</option>`).join("");e.innerHTML=`
        <div style="display:flex;gap:10px;align-items:center;margin-bottom:20px;flex-wrap:wrap;">
            <select class="event-type-filter" data-ref="projSel" style="flex:1;max-width:320px;">${t}</select>
            <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="budgetBtn" style="display:none;">
                🎯 تعریف بودجه
            </button>
            <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addEntryBtn" style="display:none;">
                ➕ ثبت تراکنش
            </button>
            <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
        </div>
        <div data-ref="body"></div>`,e.querySelectorAll("[data-ref]").forEach(s=>{this.refs[s.dataset.ref]=s}),this.on(this.ref("projSel"),"change",()=>{this._projectId=this.ref("projSel").value,this._load()}),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addEntryBtn"),"click",()=>this._openEntryModal()),this.on(this.ref("budgetBtn"),"click",()=>this._openBudgetModal()),this._projectId?await this._load():this.ref("body").innerHTML='<div class="treasury-empty">📊 یک پروژه انتخاب کنید تا داشبورد مالی آن نمایش داده شود.</div>'}async _load(){if(this._projectId){this.ref("body").innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>',this.ref("budgetBtn").style.display="",this.ref("addEntryBtn").style.display="";try{const e=await this.api.get(`/treasury/project/${this._projectId}/dashboard`);this._data=e,this._renderDash(e)}catch{this.ref("body").innerHTML='<div class="acc-error">خطا در بارگذاری</div>'}}}_renderDash(e){const t=this.ref("body"),s=y=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(y||0))),a=e.summary||{},i=e.units||{},n=a.net_profit>=0?"#10b981":"#ef4444",r=a.net_profit>=0?"✅ سود":"❌ زیان",o=`
        <div class="treasury-kpi-grid">
            <div class="treasury-kpi treasury-kpi--expense">
                <div class="treasury-kpi-icon">💸</div>
                <div class="treasury-kpi-label">مجموع هزینه</div>
                <div class="treasury-kpi-value">${s(a.total_expense)}</div>
                <div class="treasury-kpi-sub">ریال</div>
            </div>
            <div class="treasury-kpi treasury-kpi--income">
                <div class="treasury-kpi-icon">💰</div>
                <div class="treasury-kpi-label">مجموع درآمد</div>
                <div class="treasury-kpi-value">${s(a.total_income)}</div>
                <div class="treasury-kpi-sub">ریال</div>
            </div>
            <div class="treasury-kpi" style="border-top:3px solid ${n};">
                <div class="treasury-kpi-icon">${a.net_profit>=0?"📈":"📉"}</div>
                <div class="treasury-kpi-label">${r}</div>
                <div class="treasury-kpi-value" style="color:${n};">${s(Math.abs(a.net_profit))}</div>
                <div class="treasury-kpi-sub">${a.net_pct}٪ از درآمد — ریال</div>
            </div>
            <div class="treasury-kpi" style="border-top:3px solid #8b5cf6;">
                <div class="treasury-kpi-icon">🎯</div>
                <div class="treasury-kpi-label">پیش‌بینی درآمد</div>
                <div class="treasury-kpi-value" style="color:#8b5cf6;">${s(a.sales_forecast)}</div>
                <div class="treasury-kpi-sub">${s(a.sales_revenue)} دریافتی — ریال</div>
            </div>
        </div>`,l=a.budget>0?`
        <div class="treasury-card" style="margin-bottom:16px;">
            <div class="treasury-card-title">🎯 بودجه در مقابل هزینه واقعی</div>
            <div style="display:flex;justify-content:space-between;font-size:12px;color:#64748b;margin-bottom:6px;">
                <span>هزینه: ${s(a.total_expense)} ریال</span>
                <span>بودجه: ${s(a.budget)} ریال</span>
            </div>
            <div class="treasury-bar-track">
                <div class="treasury-bar-fill ${a.budget_used_pct>100?"treasury-bar-fill--over":a.budget_used_pct>80?"treasury-bar-fill--warn":""}"
                     style="width:${Math.min(a.budget_used_pct,100)}%"></div>
            </div>
            <div style="font-size:12px;margin-top:4px;${a.budget_used_pct>100?"color:#ef4444;":"color:#64748b;"}">
                ${a.budget_used_pct}٪ از بودجه مصرف‌شده
                ${a.budget_used_pct>100?"⚠️ از بودجه فراتر رفته":""}
            </div>
        </div>`:"",c=i.total>0?`
        <div class="treasury-card" style="margin-bottom:16px;">
            <div class="treasury-card-title">🏢 وضعیت فروش واحدها</div>
            <div style="display:flex;gap:16px;align-items:center;flex-wrap:wrap;">
                <div style="flex:1;">
                    <div style="display:flex;justify-content:space-between;font-size:12px;color:#64748b;margin-bottom:4px;">
                        <span>فروش: ${i.sold} واحد از ${i.total}</span>
                        <span>${i.sell_pct}٪</span>
                    </div>
                    <div class="treasury-bar-track">
                        <div class="treasury-bar-fill" style="width:${i.sell_pct}%;background:#10b981;"></div>
                    </div>
                </div>
                <div style="display:flex;gap:12px;font-size:11px;">
                    <span style="color:#10b981;">🟢 آزاد: ${i.available}</span>
                    <span style="color:#f59e0b;">🟡 رزرو: ${i.reserved}</span>
                    <span style="color:#3b82f6;">🔵 فروش: ${i.sold}</span>
                </div>
            </div>
            <div style="font-size:12px;color:#64748b;margin-top:8px;">
                ارزش فروخته‌شده: <b style="color:#10b981;">${s(i.sold_value)} ریال</b>
                از کل <b>${s(i.total_value)} ریال</b>
            </div>
        </div>`:"",d=e.expense_by_cat||{},h=a.total_expense||1,u=Object.entries(d).sort((y,$)=>$[1]-y[1]).map(([y,$])=>{const w=Math.round($/h*100),_=(e.budget_by_cat||{})[y];return`
                <div style="margin-bottom:10px;">
                    <div style="display:flex;justify-content:space-between;font-size:12px;margin-bottom:3px;">
                        <span>${yt[y]||"📌"} ${fe[y]||y}</span>
                        <span style="color:#64748b;">${s($)} ریال (${w}٪)</span>
                    </div>
                    <div class="treasury-bar-track">
                        <div style="height:100%;border-radius:4px;background:${Er[y]||"#94a3b8"};width:${w}%;transition:width .4s;"></div>
                    </div>
                    ${_?`<div style="font-size:10px;color:#94a3b8;margin-top:2px;">
                        بودجه: ${s(_)} ریال ${$>_?'<span style="color:#ef4444;">⚠️ فراتر از بودجه</span>':""}
                    </div>`:""}
                </div>`}).join("")||'<div class="gis-empty-tab">هنوز هزینه‌ای ثبت نشده.</div>',f=(e.recent||[]).length?`
        <div class="treasury-card">
            <div class="treasury-card-title">🕒 آخرین تراکنش‌ها</div>
            ${(e.recent||[]).map(y=>{const $=y.direction==="in";return`
                <div class="treasury-entry-row">
                    <div style="font-size:11px;color:#94a3b8;">${y.entry_date}</div>
                    <div style="flex:1;font-size:13px;">${this.escape(y.description)}</div>
                    <div style="font-size:11px;color:#64748b;">${fe[y.category]||y.category}</div>
                    <div style="font-weight:700;font-size:13px;color:${$?"#10b981":"#ef4444"};">
                        ${$?"▲":"▼"} ${s(y.amount)}
                    </div>
                </div>`}).join("")}
        </div>`:"",m={};(e.monthly||[]).forEach(y=>{m[y.month]||(m[y.month]={in:0,out:0}),m[y.month][y.direction]+=parseFloat(y.total)});const b=Math.max(...Object.values(m).map(y=>Math.max(y.in,y.out)),1),v=Object.keys(m).length>0?`
        <div class="treasury-card" style="margin-bottom:16px;">
            <div class="treasury-card-title">📅 جریان نقدی ۶ ماه اخیر</div>
            <div class="treasury-monthly-chart">
                ${Object.entries(m).map(([y,$])=>`
                <div class="treasury-month-col">
                    <div style="display:flex;gap:3px;align-items:flex-end;height:80px;">
                        <div style="width:16px;background:#10b981;border-radius:3px 3px 0 0;
                             height:${Math.round($.in/b*80)}px;" title="درآمد: ${s($.in)}"></div>
                        <div style="width:16px;background:#ef4444;border-radius:3px 3px 0 0;
                             height:${Math.round($.out/b*80)}px;" title="هزینه: ${s($.out)}"></div>
                    </div>
                    <div style="font-size:9px;color:#94a3b8;margin-top:4px;text-align:center;">${y.slice(5)}</div>
                </div>`).join("")}
            </div>
            <div style="display:flex;gap:12px;font-size:11px;margin-top:6px;">
                <span><span style="color:#10b981;">■</span> درآمد</span>
                <span><span style="color:#ef4444;">■</span> هزینه</span>
            </div>
        </div>`:"";t.innerHTML=`
        ${o}
        <div class="treasury-two-col">
            <div>
                ${l}
                ${c}
                ${v}
            </div>
            <div>
                <div class="treasury-card">
                    <div class="treasury-card-title">💸 تفکیک هزینه</div>
                    ${u}
                </div>
            </div>
        </div>
        ${f}`}_openEntryModal(e=null){const t=!!e,s=e||{},a=["sales_income","investor","loan","other"],i=["land","construction","permits","design","marketing","finance_cost","tax","other"],n=[...new Set([...a,...i])],r=document.createElement("div");r.className="acc-modal-overlay",r.innerHTML=`
        <div class="acc-modal" style="max-width:440px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">💰 ${t?"ویرایش":"ثبت"} تراکنش</div>
            <form>
                <div style="display:flex;gap:12px;margin-bottom:14px;">
                    <label class="treasury-dir-opt treasury-dir-opt--out ${s.direction!=="in"?"treasury-dir-opt--active":""}">
                        <input type="radio" name="direction" value="out" ${s.direction!=="in"?"checked":""}> 💸 هزینه
                    </label>
                    <label class="treasury-dir-opt treasury-dir-opt--in ${s.direction==="in"?"treasury-dir-opt--active":""}">
                        <input type="radio" name="direction" value="in" ${s.direction==="in"?"checked":""}> 💰 درآمد
                    </label>
                </div>
                <div class="acc-form-group"><label>دسته‌بندی</label>
                    <select name="category">
                        ${n.map(l=>`<option value="${l}" ${s.category===l?"selected":""}>${yt[l]||""} ${fe[l]||l}</option>`).join("")}
                    </select>
                </div>
                <div class="acc-form-group"><label>شرح *</label>
                    <input name="description" required value="${this.escape(s.description||"")}">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>مبلغ (ریال) *</label>
                        <input name="amount" type="number" min="0" required value="${s.amount||""}">
                    </div>
                    <div class="acc-form-group"><label>تاریخ</label>
                        <input name="entry_date" type="date" value="${s.entry_date||new Date().toISOString().split("T")[0]}">
                    </div>
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="2">${this.escape(s.notes||"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"ثبت"}</button>
                </div>
            </form>
        </div>`,document.body.appendChild(r),r.querySelectorAll('input[name="direction"]').forEach(l=>{l.addEventListener("change",()=>{r.querySelectorAll(".treasury-dir-opt").forEach(c=>c.classList.remove("treasury-dir-opt--active")),l.closest(".treasury-dir-opt").classList.add("treasury-dir-opt--active")})});const o=()=>r.remove();r.querySelector(".acc-modal__close").addEventListener("click",o),r.querySelector('[data-action="cancel"]').addEventListener("click",o),r.addEventListener("click",l=>{l.target===r&&o()}),r.querySelector("form").addEventListener("submit",async l=>{l.preventDefault();const c=Object.fromEntries(new FormData(l.target).entries());c.project_id=this._projectId;const d=l.target.querySelector('[type="submit"]');d.disabled=!0;try{t?await this.api.put(`/treasury/entries/${s.id}`,c):await this.api.post("/treasury/entries",c),o(),this._toast("✅ ثبت شد"),this._load()}catch(h){alert("خطا: "+((h==null?void 0:h.message)||"")),d.disabled=!1}})}_openBudgetModal(){var i;const e=["land","construction","permits","design","marketing","finance_cost","tax","other"],t=((i=this._data)==null?void 0:i.budget_by_cat)||{},s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
        <div class="acc-modal" style="max-width:480px;max-height:90vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🎯 بودجه تفصیلی</div>
            <form>
                ${e.map(n=>`
                <div class="doc-form-row" style="align-items:center;">
                    <label style="flex:1;font-size:13px;">${yt[n]||""} ${fe[n]||n}</label>
                    <div class="acc-form-group" style="flex:2;margin-bottom:8px;">
                        <input name="cat_${n}" type="number" min="0"
                            value="${t[n]||""}" placeholder="ریال (اختیاری)">
                    </div>
                </div>`).join("")}
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره بودجه</button>
                </div>
            </form>
        </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector('[data-action="cancel"]').addEventListener("click",a),s.addEventListener("click",n=>{n.target===s&&a()}),s.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=new FormData(n.target),o=e.filter(c=>r.get("cat_"+c)).map(c=>({category:c,label:fe[c],planned_amount:parseFloat(r.get("cat_"+c))||0})),l=n.target.querySelector('[type="submit"]');l.disabled=!0;try{await this.api.post(`/treasury/budget/${this._projectId}`,{items:o}),a(),this._toast("✅ بودجه ذخیره شد"),this._load()}catch(c){alert("خطا: "+((c==null?void 0:c.message)||"")),l.disabled=!1}})}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e||0)))}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;direction:rtl;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const zs={land:"خرید زمین",construction:"ساخت و ساز",permits:"مجوزها",design:"طراحی",marketing:"بازاریابی",finance_cost:"هزینه مالی",tax:"مالیات",sales_income:"درآمد فروش",investor:"سرمایه‌گذار",loan:"تسهیلات",other:"سایر"};class Sr extends x{constructor(e={}){super(e),this._entries=[],this._projects=[],this._filter={project_id:"",direction:"",from:"",to:""}}async template(){return'<div data-ref="root"></div>'}async afterRender(){try{const e=await this.api.get("/pc/projects",{per_page:200});this._projects=(e==null?void 0:e.data)??[]}catch{}await this._render()}async _render(){const e=this.ref("root"),t='<option value="">همه پروژه‌ها</option>'+this._projects.map(s=>`<option value="${s.id}">${this.escape(s.name)}</option>`).join("");e.innerHTML=`
        <div style="display:flex;gap:8px;align-items:center;margin-bottom:14px;flex-wrap:wrap;">
            <select class="event-type-filter" data-ref="projSel">${t}</select>
            <select class="event-type-filter" data-ref="dirSel">
                <option value="">هر دو</option>
                <option value="in">💰 درآمد</option>
                <option value="out">💸 هزینه</option>
            </select>
            <input type="date" class="acc-input" data-ref="fromInp" style="width:130px;" title="از تاریخ">
            <input type="date" class="acc-input" data-ref="toInp"   style="width:130px;" title="تا تاریخ">
            <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">➕ ثبت تراکنش</button>
            <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
            <span data-ref="totalLbl" style="font-size:12px;color:#94a3b8;"></span>
        </div>
        <div data-ref="tableWrap"></div>`,e.querySelectorAll("[data-ref]").forEach(s=>{this.refs[s.dataset.ref]=s}),this.on(this.ref("projSel"),"change",()=>{this._filter.project_id=this.ref("projSel").value,this._load()}),this.on(this.ref("dirSel"),"change",()=>{this._filter.direction=this.ref("dirSel").value,this._load()}),this.on(this.ref("fromInp"),"change",()=>{this._filter.from=this.ref("fromInp").value,this._load()}),this.on(this.ref("toInp"),"change",()=>{this._filter.to=this.ref("toInp").value,this._load()}),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openEntryModal()),await this._load()}async _load(){this.ref("tableWrap").innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';const e={};this._filter.project_id&&(e.project_id=this._filter.project_id),this._filter.direction&&(e.direction=this._filter.direction),this._filter.from&&(e.from=this._filter.from),this._filter.to&&(e.to=this._filter.to);try{const t=await this.api.get("/treasury/entries",e);this._entries=(t==null?void 0:t.data)??[],this._renderTable()}catch{this.ref("tableWrap").innerHTML='<div class="acc-error">خطا</div>'}}_renderTable(){const e=this.ref("tableWrap"),t=i=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(i||0)));if(!this._entries.length){e.innerHTML='<div class="acc-empty">تراکنشی ثبت نشده.</div>',this.ref("totalLbl").textContent="";return}const s=this._entries.filter(i=>i.direction==="in").reduce((i,n)=>i+parseFloat(n.amount),0),a=this._entries.filter(i=>i.direction==="out").reduce((i,n)=>i+parseFloat(n.amount),0);this.ref("totalLbl").innerHTML=`<span style="color:#10b981;">▲${t(s)}</span> &nbsp;
             <span style="color:#ef4444;">▼${t(a)}</span> &nbsp;
             <b>${s-a>=0?"سود":"زیان"}: ${t(Math.abs(s-a))}</b>`,e.innerHTML=`
        <div class="treasury-ledger">
            <div class="treasury-ledger-header">
                <span>تاریخ</span>
                <span>شرح</span>
                <span>دسته</span>
                <span>پروژه</span>
                <span>درآمد</span>
                <span>هزینه</span>
                <span>موجودی</span>
                <span></span>
            </div>
            ${this._entries.map(i=>{const n=i.direction==="in",r=parseFloat(i.running_balance||0);return`
                <div class="treasury-ledger-row ${n?"treasury-ledger-row--in":"treasury-ledger-row--out"}"
                     data-id="${i.id}">
                    <span class="treasury-cell-date">${i.entry_date}</span>
                    <span class="treasury-cell-desc">${this.escape(i.description)}</span>
                    <span class="treasury-cell-cat">${zs[i.category]||i.category}</span>
                    <span class="treasury-cell-proj">${this.escape(i.project_name||"—")}</span>
                    <span class="treasury-cell-in">${n?'<b style="color:#10b981;">'+t(i.amount)+"</b>":"—"}</span>
                    <span class="treasury-cell-out">${n?"—":'<b style="color:#ef4444;">'+t(i.amount)+"</b>"}</span>
                    <span class="treasury-cell-bal" style="color:${r>=0?"#10b981":"#ef4444"};font-weight:700;">
                        ${t(r)}
                    </span>
                    <span style="display:flex;gap:4px;">
                        ${i.source==="manual"?`
                        <button class="gis-btn gis-btn--xs" data-edit="${i.id}">✏️</button>
                        <button class="gis-btn gis-btn--xs gis-btn--danger" data-del="${i.id}">🗑️</button>
                        `:" "}
                    </span>
                </div>`}).join("")}
        </div>`,e.querySelectorAll("[data-edit]").forEach(i=>{const n=this._entries.find(r=>String(r.id)===i.dataset.edit);n&&i.addEventListener("click",()=>this._openEntryModal(n))}),e.querySelectorAll("[data-del]").forEach(i=>{i.addEventListener("click",async()=>{if(confirm("حذف این تراکنش؟"))try{await this.api.delete(`/treasury/entries/${i.dataset.del}`),this._toast("🗑️ حذف شد"),this._load()}catch(n){alert("خطا: "+((n==null?void 0:n.message)||""))}})})}_openEntryModal(e=null){const t=!!e,s=e||{},a='<option value="">— انتخاب پروژه —</option>'+this._projects.map(o=>`<option value="${o.id}" ${s.project_id==o.id||this._filter.project_id==o.id?"selected":""}>${this.escape(o.name)}</option>`).join(""),i=["land","construction","permits","design","marketing","finance_cost","tax","sales_income","investor","loan","other"],n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
        <div class="acc-modal" style="max-width:440px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"ویرایش":"ثبت"} تراکنش</div>
            <form>
                <div class="acc-form-group"><label>پروژه *</label>
                    <select name="project_id" required>${a}</select>
                </div>
                <div style="display:flex;gap:10px;margin-bottom:12px;">
                    <label style="font-size:13px;display:flex;gap:6px;align-items:center;background:#fef2f2;padding:8px 14px;border-radius:8px;cursor:pointer;flex:1;justify-content:center;border:2px solid ${s.direction!=="in"?"#ef4444":"#e2e8f0"}">
                        <input type="radio" name="direction" value="out" ${s.direction!=="in"?"checked":""}> 💸 هزینه
                    </label>
                    <label style="font-size:13px;display:flex;gap:6px;align-items:center;background:#f0fdf4;padding:8px 14px;border-radius:8px;cursor:pointer;flex:1;justify-content:center;border:2px solid ${s.direction==="in"?"#10b981":"#e2e8f0"}">
                        <input type="radio" name="direction" value="in" ${s.direction==="in"?"checked":""}> 💰 درآمد
                    </label>
                </div>
                <div class="acc-form-group"><label>دسته‌بندی</label>
                    <select name="category">
                        ${i.map(o=>`<option value="${o}" ${s.category===o?"selected":""}>${zs[o]||o}</option>`).join("")}
                    </select>
                </div>
                <div class="acc-form-group"><label>شرح *</label>
                    <input name="description" required value="${this.escape(s.description||"")}">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>مبلغ (ریال) *</label>
                        <input name="amount" type="number" min="0" required value="${s.amount||""}">
                    </div>
                    <div class="acc-form-group"><label>تاریخ</label>
                        <input name="entry_date" type="date" value="${s.entry_date||new Date().toISOString().split("T")[0]}">
                    </div>
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="2">${this.escape(s.notes||"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"ثبت"}</button>
                </div>
            </form>
        </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector('[data-action="cancel"]').addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()}),n.querySelector("form").addEventListener("submit",async o=>{o.preventDefault();const l=Object.fromEntries(new FormData(o.target).entries()),c=o.target.querySelector('[type="submit"]');c.disabled=!0;try{t?await this.api.put(`/treasury/entries/${s.id}`,l):await this.api.post("/treasury/entries",l),r(),this._toast("✅ ذخیره شد"),this._load()}catch(d){alert("خطا: "+((d==null?void 0:d.message)||"")),c.disabled=!1}})}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;direction:rtl;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}class Cr extends x{async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._load()}async _load(){const e=this.ref("root");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t=await this.api.get("/treasury/overview");this._render((t==null?void 0:t.data)??[])}catch{e.innerHTML='<div class="acc-error">خطا</div>'}}_render(e){const t=this.ref("root"),s=o=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(o||0)));if(!e.length){t.innerHTML='<div class="acc-empty">پروژه‌ای یافت نشد.</div>';return}const a=e.reduce((o,l)=>o+parseFloat(l.total_income||0),0),i=e.reduce((o,l)=>o+parseFloat(l.total_expense||0),0),n=a-i,r=n>=0?"#10b981":"#ef4444";t.innerHTML=`
        <!-- KPI کلی شرکت -->
        <div class="treasury-kpi-grid" style="margin-bottom:24px;">
            <div class="treasury-kpi treasury-kpi--expense">
                <div class="treasury-kpi-icon">💸</div>
                <div class="treasury-kpi-label">کل هزینه‌ها</div>
                <div class="treasury-kpi-value">${s(i)}</div>
                <div class="treasury-kpi-sub">ریال — همه پروژه‌ها</div>
            </div>
            <div class="treasury-kpi treasury-kpi--income">
                <div class="treasury-kpi-icon">💰</div>
                <div class="treasury-kpi-label">کل درآمدها</div>
                <div class="treasury-kpi-value">${s(a)}</div>
                <div class="treasury-kpi-sub">ریال — همه پروژه‌ها</div>
            </div>
            <div class="treasury-kpi" style="border-top:3px solid ${r};">
                <div class="treasury-kpi-icon">${n>=0?"📈":"📉"}</div>
                <div class="treasury-kpi-label">سود/زیان کل</div>
                <div class="treasury-kpi-value" style="color:${r};">${s(Math.abs(n))}</div>
                <div class="treasury-kpi-sub">ریال</div>
            </div>
            <div class="treasury-kpi" style="border-top:3px solid #8b5cf6;">
                <div class="treasury-kpi-icon">🏢</div>
                <div class="treasury-kpi-label">پروژه فعال</div>
                <div class="treasury-kpi-value" style="color:#8b5cf6;">
                    ${e.filter(o=>o.status==="active").length}
                </div>
                <div class="treasury-kpi-sub">از ${e.length} پروژه</div>
            </div>
        </div>

        <!-- جدول پروژه‌ها -->
        <div class="treasury-overview-table">
            <div class="treasury-overview-header">
                <span>پروژه</span>
                <span>هزینه</span>
                <span>درآمد</span>
                <span>سود/زیان</span>
                <span>واحدها</span>
                <span>وضعیت</span>
            </div>
            ${e.map(o=>{const l=parseFloat(o.total_income||0)-parseFloat(o.total_expense||0),c=l>=0?"#10b981":"#ef4444",d=o.unit_count>0?Math.round(o.sold_count/o.unit_count*100):0,h={active:"#10b981",completed:"#3b82f6",planned:"#f59e0b",archived:"#94a3b8"}[o.status]||"#94a3b8",u={active:"فعال",completed:"تکمیل",planned:"برنامه‌ریزی",archived:"بایگانی"}[o.status]||o.status;return`
                <div class="treasury-overview-row">
                    <span style="font-weight:700;color:#1e293b;">${this.escape(o.name)}</span>
                    <span style="color:#ef4444;">${s(o.total_expense)}</span>
                    <span style="color:#10b981;">${s(o.total_income)}</span>
                    <span style="color:${c};font-weight:700;">${l>=0?"+":""}${s(l)}</span>
                    <span>
                        ${o.unit_count>0?`
                        <div style="font-size:11px;">${o.sold_count}/${o.unit_count} (${d}٪)</div>
                        <div class="treasury-bar-track" style="height:4px;margin-top:2px;">
                            <div style="height:100%;background:#3b82f6;border-radius:2px;width:${d}%"></div>
                        </div>`:"-"}
                    </span>
                    <span>
                        <span style="background:${h};color:#fff;padding:2px 8px;border-radius:6px;font-size:11px;">
                            ${u}
                        </span>
                    </span>
                </div>`}).join("")}
        </div>`}}const _t=[{key:"dash",icon:"📊",title:"داشبورد پروژه",Class:Lr},{key:"ledger",icon:"📒",title:"دفتر نقدی",Class:Sr},{key:"overview",icon:"🗂️",title:"نمای کلی",Class:Cr}];class js extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._active="dash",this._sections={}}async template(){const t=_t.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
            </div>`).join(""),s=_t.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>`).join("");return`<div class="sp-section-nav" data-ref="navBar">${t}</div><div>${s}</div>`}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>this.on(t,"click",()=>this._switch(t.dataset.section))),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=_t.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(js,"title","💰 خزانه پروژه"),E.register("treasury",js);const xt={build:"پروانه ساخت",renovation:"بازسازی",demolish:"تخریب",use_change:"تغییر کاربری",completion:"پایان کار"},As={build:"#3b82f6",renovation:"#8b5cf6",demolish:"#ef4444",use_change:"#f59e0b",completion:"#10b981"},Fs={build:"🏗️",renovation:"🔨",demolish:"💥",use_change:"🔄",completion:"✅"},wt={draft:"پیش‌نویس",submitted:"ارسال‌شده",under_review:"در بررسی",approved:"تأیید شده",active:"فعال",completed:"پایان کار",rejected:"رد شده",expired:"منقضی"},Is={draft:"#94a3b8",submitted:"#3b82f6",under_review:"#f59e0b",approved:"#8b5cf6",active:"#10b981",completed:"#059669",rejected:"#ef4444",expired:"#dc2626"},Ds={permit_fee:"عوارض پروانه",levy:"عوارض نوسازی",fine:"جریمه",inspection:"هزینه بازدید",notary:"دفترخانه",other:"سایر"};class Tr extends x{constructor(e={}){super(e),this._permits=[],this._selected=null,this._panelOpen=!1,this._filter={status:"",type:""},this._projects=[],this._parcels=[],this._activeTab="details"}async template(){return'<div data-ref="root"></div>'}async afterRender(){try{const[e,t]=await Promise.all([this.api.get("/gis/districts").catch(()=>null),this.api.get("/pc/projects",{per_page:200}).catch(()=>null)]);this._parcels=(e==null?void 0:e.data)??[],this._projects=(t==null?void 0:t.data)??[]}catch{}await this._render()}async _render(){const e=this.ref("root");e.innerHTML=`
        <div class="permit-wrap" data-ref="wrap">
            <!-- لیست -->
            <div class="permit-list-pane" data-ref="listPane">
                <div class="permit-toolbar">
                    <select class="event-type-filter" data-ref="typeSel">
                        <option value="">همه انواع</option>
                        ${Object.entries(xt).map(([t,s])=>`<option value="${t}">${s}</option>`).join("")}
                    </select>
                    <select class="event-type-filter" data-ref="statusSel">
                        <option value="">همه وضعیت‌ها</option>
                        ${Object.entries(wt).map(([t,s])=>`<option value="${t}">${s}</option>`).join("")}
                    </select>
                    <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">➕ پروانه جدید</button>
                </div>
                <div data-ref="listBody" class="permit-list"></div>
            </div>
            <!-- پانل جزئیات -->
            <div class="permit-detail-pane" data-ref="detailPane">
                <div class="permit-detail-inner" data-ref="detailInner"></div>
            </div>
        </div>`,e.querySelectorAll("[data-ref]").forEach(t=>{this.refs[t.dataset.ref]=t}),this.on(this.ref("typeSel"),"change",()=>{this._filter.type=this.ref("typeSel").value,this._load()}),this.on(this.ref("statusSel"),"change",()=>{this._filter.status=this.ref("statusSel").value,this._load()}),this.on(this.ref("addBtn"),"click",()=>this._openPermitModal()),await this._load()}async _load(){const e=this.ref("listBody");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';const t={};this._filter.type&&(t.type=this._filter.type),this._filter.status&&(t.status=this._filter.status);try{const s=await this.api.get("/permits",t);this._permits=(s==null?void 0:s.data)??[],this._renderList()}catch{e.innerHTML='<div class="acc-error">خطا</div>'}}_renderList(){const e=this.ref("listBody");if(!this._permits.length){e.innerHTML='<div class="acc-empty">پروانه‌ای ثبت نشده.</div>';return}e.innerHTML="",this._permits.forEach(t=>{var l;const s=Is[t.status]||"#94a3b8",a=As[t.type]||"#94a3b8",i=parseInt(t.days_to_expiry),n=t.expiry_date&&i<30&&i>=0,r=t.expiry_date&&i<0,o=document.createElement("div");o.className=`permit-card${((l=this._selected)==null?void 0:l.id)==t.id?" permit-card--active":""}`,o.innerHTML=`
            <div style="display:flex;justify-content:space-between;align-items:start;margin-bottom:8px;">
                <span class="permit-type-badge" style="background:${a};">
                    ${Fs[t.type]||""} ${xt[t.type]||t.type}
                </span>
                <span class="permit-status-badge" style="background:${s};">
                    ${wt[t.status]||t.status}
                </span>
            </div>
            <div class="permit-card-title">
                ${t.permit_number?`📋 ${this.escape(t.permit_number)}`:"(شماره پروانه ثبت نشده)"}
            </div>
            ${t.project_name?`<div class="permit-card-meta">🏗️ ${this.escape(t.project_name)}</div>`:""}
            ${t.parcel_code?`<div class="permit-card-meta">📍 پلاک ${this.escape(t.parcel_code)}</div>`:""}
            ${t.allowed_floors?`<div class="permit-card-meta">🏢 ${t.allowed_floors} طبقه | ${t.allowed_area_sqm||"—"} م²</div>`:""}
            <!-- پیشرفت -->
            <div class="permit-progress-wrap">
                <div class="treasury-bar-track" style="height:4px;">
                    <div class="treasury-bar-fill" style="width:${Math.round(t.done_steps/11*100)}%;background:${s};"></div>
                </div>
                <span style="font-size:10px;color:#94a3b8;">${t.done_steps||0}/11 مرحله</span>
            </div>
            ${n?`<div style="font-size:11px;color:#f59e0b;margin-top:4px;">⚠️ ${i} روز تا انقضا</div>`:""}
            ${r?'<div style="font-size:11px;color:#ef4444;margin-top:4px;">❌ پروانه منقضی شده</div>':""}
            ${t.pending_fees>0?`<div style="font-size:11px;color:#ef4444;">💳 ${t.pending_fees} عوارض معوق</div>`:""}`,o.addEventListener("click",()=>this._openDetail(t)),e.appendChild(o)})}async _openDetail(e){this._selected=e,this._renderList();const t=this.ref("detailPane"),s=this.ref("detailInner");this._panelOpen||(t.classList.add("permit-detail-pane--open"),this._panelOpen=!0),s.innerHTML='<div class="acc-loading" style="padding:40px;text-align:center;"><div class="acc-spinner"></div></div>';try{const a=await this.api.get(`/permits/${e.id}`),i=a==null?void 0:a.data;if(!i)return;this._selected=i,this._renderDetail(i)}catch{s.innerHTML='<div class="acc-error">خطا</div>'}}_renderDetail(e){const t=this.ref("detailInner"),s=n=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(n||0)));As[e.type];const a=Is[e.status]||"#94a3b8",i=e.fee_summary||{};t.innerHTML=`
        <!-- هدر -->
        <div class="permit-detail-header">
            <div style="flex:1;">
                <div style="font-size:16px;font-weight:800;color:#1e293b;margin-bottom:6px;">
                    ${Fs[e.type]||""} ${xt[e.type]||e.type}
                    ${e.permit_number?`<span style="font-size:12px;color:#64748b;margin-right:8px;">№ ${this.escape(e.permit_number)}</span>`:""}
                </div>
                <div style="display:flex;gap:6px;flex-wrap:wrap;">
                    <span style="background:${a};color:#fff;padding:3px 10px;border-radius:8px;font-size:11px;font-weight:700;">${wt[e.status]||e.status}</span>
                    ${e.project_name?`<span style="font-size:11px;color:#64748b;">🏗️ ${this.escape(e.project_name)}</span>`:""}
                    ${e.days_to_expiry!==null&&e.days_to_expiry<30?`<span style="font-size:11px;color:#f59e0b;">⚠️ ${e.days_to_expiry} روز تا انقضا</span>`:""}
                </div>
            </div>
            <button class="gis-panel-close" data-ref="closeBtn">✕</button>
        </div>

        <!-- نوار پیشرفت مراحل -->
        <div class="permit-stepper" data-ref="stepperEl">
            ${this._renderStepper(e.steps)}
        </div>
        <div style="text-align:center;font-size:11px;color:#94a3b8;margin-bottom:12px;">
            ${e.done_steps} از ${e.total_steps} مرحله تکمیل‌شده — ${e.progress_pct}٪
        </div>

        <!-- خلاصه عوارض -->
        ${i.total>0?`
        <div style="background:#f8fafc;border-radius:8px;padding:10px 14px;margin-bottom:12px;font-size:12px;">
            <div style="display:flex;justify-content:space-between;">
                <span>کل عوارض: <b>${s(i.total)} ریال</b></span>
                <span>پرداخت‌شده: <b style="color:#10b981;">${s(i.paid)} ریال</b></span>
                <span>مانده: <b style="color:#ef4444;">${s(i.remaining)} ریال</b></span>
            </div>
            <div class="treasury-bar-track" style="margin-top:6px;">
                <div class="treasury-bar-fill" style="width:${i.total>0?Math.round(i.paid/i.total*100):0}%;background:#10b981;"></div>
            </div>
        </div>`:""}

        <!-- تب‌ها -->
        <div class="gis-panel-tabs" data-ref="detailTabs">
            <button class="gis-panel-tab ${this._activeTab==="details"?"gis-panel-tab--active":""}" data-tab="details">📋 جزئیات</button>
            <button class="gis-panel-tab ${this._activeTab==="steps"?"gis-panel-tab--active":""}" data-tab="steps">🔢 مراحل (${e.done_steps}/${e.total_steps})</button>
            <button class="gis-panel-tab ${this._activeTab==="fees"?"gis-panel-tab--active":""}" data-tab="fees">💳 عوارض (${(e.fees||[]).length})</button>
        </div>
        <div class="permit-tab-body" data-ref="detailTabBody">
            ${this._renderTabContent(this._activeTab,e)}
        </div>

        <!-- اکشن‌ها -->
        <div class="gis-panel-actions">
            <button class="gis-btn gis-btn--primary" data-ref="editBtn">✏️ ویرایش</button>
            <button class="gis-btn gis-btn--danger"  data-ref="delBtn">🗑️ حذف</button>
        </div>`,t.querySelectorAll("[data-ref]").forEach(n=>{this.refs[n.dataset.ref]=n}),this.on(this.ref("closeBtn"),"click",()=>{this.ref("detailPane").classList.remove("permit-detail-pane--open"),this._panelOpen=!1,this._selected=null,this._renderList()}),t.querySelectorAll(".gis-panel-tab").forEach(n=>{n.addEventListener("click",()=>{t.querySelectorAll(".gis-panel-tab").forEach(r=>r.classList.remove("gis-panel-tab--active")),n.classList.add("gis-panel-tab--active"),this._activeTab=n.dataset.tab,this.ref("detailTabBody").innerHTML=this._renderTabContent(n.dataset.tab,e),this._bindTabActions(n.dataset.tab,e)})}),this.on(this.ref("editBtn"),"click",()=>this._openPermitModal(e)),this.on(this.ref("delBtn"),"click",async()=>{confirm("حذف این پروانه؟")&&(await this.api.delete(`/permits/${e.id}`),this._toast("🗑️ حذف شد"),this.ref("detailPane").classList.remove("permit-detail-pane--open"),this._panelOpen=!1,this._selected=null,this._load())}),this._bindTabActions(this._activeTab,e)}_renderStepper(e=[]){return'<div class="permit-stepper-track">'+e.map((t,s)=>{const a=t.status==="done",i=t.status==="failed",n=a?"#10b981":i?"#ef4444":"#e2e8f0",r=a||i?"#fff":"#94a3b8";return`
                <div class="permit-step-item" data-step="${t.key}" title="${t.label}${t.done_date?" — "+t.done_date:""}">
                    <div class="permit-step-circle" style="background:${n};color:${r};">
                        ${a?"✓":i?"✗":t.icon}
                    </div>
                    <div class="permit-step-label" style="color:${a?"#10b981":i?"#ef4444":"#94a3b8"};">${t.label}</div>
                    ${s<e.length-1?'<div class="permit-step-line" style="background:'+(a?"#10b981":"#e2e8f0")+'"></div>':""}
                </div>`}).join("")+"</div>"}_renderTabContent(e,t){switch(e){case"details":return this._renderTabDetails(t);case"steps":return this._renderTabSteps(t.steps||[]);case"fees":return this._renderTabFees(t.fees||[]);default:return""}}_renderTabDetails(e){const t=(s,a)=>a?`<div class="gis-info-row"><span class="gis-info-label">${s}</span><span class="gis-info-value">${a}</span></div>`:"";return`<div class="gis-tab-content">
            <div class="gis-info-divider">مشخصات</div>
            ${t("شماره پروانه",e.permit_number?this.escape(e.permit_number):null)}
            ${t("شماره درخواست",e.application_ref?this.escape(e.application_ref):null)}
            ${t("شهرداری",e.municipality?this.escape(e.municipality):null)}
            ${t("مهندس ناظر",e.engineer_name?this.escape(e.engineer_name):null)}
            <div class="gis-info-divider">تاریخ‌ها</div>
            ${t("درخواست",e.application_date)}
            ${t("تأیید",e.approval_date)}
            ${t("انقضا",e.expiry_date)}
            ${t("پایان کار",e.completion_date)}
            <div class="gis-info-divider">مشخصات ساختمانی مجاز</div>
            ${t("طبقات مجاز",e.allowed_floors)}
            ${t("زیربنای مجاز",e.allowed_area_sqm?e.allowed_area_sqm+" م²":null)}
            ${t("کاربری مجاز",e.allowed_use?this.escape(e.allowed_use):null)}
            ${t("تراکم",e.density_pct?e.density_pct+"%":null)}
            ${e.notes?`<div class="gis-info-divider">یادداشت</div><div style="font-size:12px;color:#475569;">${this.escape(e.notes)}</div>`:""}
        </div>`}_renderTabSteps(e){const t={pending:"در انتظار",done:"انجام شد",failed:"ناموفق",skipped:"رد شد"},s={pending:"#94a3b8",done:"#10b981",failed:"#ef4444",skipped:"#f59e0b"};return`<div class="gis-tab-content">
            <div class="gis-section-title">مراحل فرآیند</div>
            ${e.map(a=>`
            <div class="permit-step-row" style="border-right:3px solid ${s[a.status]||"#e2e8f0"};">
                <div style="display:flex;justify-content:space-between;align-items:start;">
                    <div>
                        <div style="font-weight:700;font-size:13px;">${a.icon} ${a.label}</div>
                        ${a.done_date?`<div style="font-size:11px;color:#64748b;">📅 ${a.done_date}</div>`:""}
                        ${a.reference?`<div style="font-size:11px;color:#64748b;">📎 ${this.escape(a.reference)}</div>`:""}
                        ${a.notes?`<div style="font-size:11px;color:#94a3b8;">${this.escape(a.notes)}</div>`:""}
                    </div>
                    <div style="display:flex;flex-direction:column;align-items:flex-end;gap:4px;">
                        <span style="font-size:10px;color:${s[a.status]};font-weight:700;">${t[a.status]||a.status}</span>
                        ${a.status!=="done"?`<button class="gis-btn gis-btn--xs" style="background:#dcfce7;color:#166534;border:1px solid #86efac;" data-mark-step="${a.key}">✅ انجام شد</button>`:""}
                        ${a.status==="done"?`<button class="gis-btn gis-btn--xs" data-undo-step="${a.key}">↩️ لغو</button>`:""}
                    </div>
                </div>
            </div>`).join("")}
        </div>`}_renderTabFees(e){const t=i=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(i||0))),s={pending:"#f59e0b",paid:"#10b981",overdue:"#ef4444",cancelled:"#94a3b8"},a={pending:"در انتظار",paid:"پرداخت شد",overdue:"سررسید گذشت",cancelled:"لغو"};return`<div class="gis-tab-content">
            <div class="gis-section-title">عوارض و هزینه‌ها
                <button class="gis-btn gis-btn--xs" data-action="add-fee">+ افزودن</button>
            </div>
            ${e.length?e.map(i=>`
            <div class="permit-fee-row" style="border-right:3px solid ${s[i.status]||"#94a3b8"};">
                <div style="flex:1;">
                    <div style="font-weight:700;font-size:13px;">${this.escape(i.description)}</div>
                    <div style="font-size:11px;color:#64748b;">
                        ${Ds[i.category]||i.category}
                        ${i.due_date?" | 📅 سررسید: "+i.due_date:""}
                        ${i.receipt_number?" | رسید: "+i.receipt_number:""}
                    </div>
                </div>
                <div style="text-align:left;">
                    <div style="font-weight:700;font-size:14px;">${t(i.amount)} ریال</div>
                    <div style="font-size:10px;color:${s[i.status]};font-weight:700;">${a[i.status]||i.status}</div>
                    ${i.status!=="paid"&&i.status!=="cancelled"?`
                    <button class="gis-btn gis-btn--xs" style="background:#dcfce7;color:#166534;margin-top:4px;"
                        data-pay-fee="${i.id}">💳 پرداخت</button>`:""}
                    <button class="gis-btn gis-btn--xs gis-btn--danger" data-del-fee="${i.id}" style="margin-top:4px;">🗑️</button>
                </div>
            </div>`).join(""):'<div class="gis-empty-tab">عوارضی ثبت نشده.</div>'}
        </div>`}_bindTabActions(e,t){var a;const s=this.ref("detailTabBody");s&&(e==="steps"&&(s.querySelectorAll("[data-mark-step]").forEach(i=>{i.addEventListener("click",async()=>{try{await this.api.post(`/permits/${t.id}/steps`,{step_key:i.dataset.markStep,status:"done",done_date:new Date().toISOString().split("T")[0]}),this._toast("✅ مرحله تکمیل شد","#10b981"),this._openDetail({id:t.id})}catch{alert("خطا")}})}),s.querySelectorAll("[data-undo-step]").forEach(i=>{i.addEventListener("click",async()=>{try{await this.api.post(`/permits/${t.id}/steps`,{step_key:i.dataset.undoStep,status:"pending"}),this._toast("↩️ مرحله لغو شد","#f59e0b"),this._openDetail({id:t.id})}catch{alert("خطا")}})})),e==="fees"&&((a=s.querySelector('[data-action="add-fee"]'))==null||a.addEventListener("click",()=>this._openFeeModal(t.id)),s.querySelectorAll("[data-pay-fee]").forEach(i=>{i.addEventListener("click",()=>this._openPayFeeModal(t.id,i.dataset.payFee,t.fees||[]))}),s.querySelectorAll("[data-del-fee]").forEach(i=>{i.addEventListener("click",async()=>{if(confirm("حذف این عارضه؟"))try{await this.api.delete(`/permits/${t.id}/fees/${i.dataset.delFee}`),this._toast("🗑️ حذف شد"),this._openDetail({id:t.id})}catch{alert("خطا")}})})))}_openPermitModal(e=null){const t=!!e,s=e||{},a='<option value="">—</option>'+this._projects.map(l=>`<option value="${l.id}" ${s.project_id==l.id?"selected":""}>${this.escape(l.name)}</option>`).join(""),i=l=>s.type===l?"selected":"",n=l=>s.status===l?"selected":"",r=document.createElement("div");r.className="acc-modal-overlay",r.innerHTML=`
        <div class="acc-modal" style="max-width:560px;max-height:90vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">📋 ${t?"ویرایش":"پروانه جدید"}</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>نوع پروانه</label>
                        <select name="type">
                            <option value="build"       ${i("build")}>🏗️ پروانه ساخت</option>
                            <option value="renovation"  ${i("renovation")}>🔨 بازسازی</option>
                            <option value="demolish"    ${i("demolish")}>💥 تخریب</option>
                            <option value="use_change"  ${i("use_change")}>🔄 تغییر کاربری</option>
                            <option value="completion"  ${i("completion")}>✅ پایان کار</option>
                        </select>
                    </div>
                    <div class="acc-form-group"><label>وضعیت</label>
                        <select name="status">
                            <option value="draft"        ${n("draft")}>پیش‌نویس</option>
                            <option value="submitted"    ${n("submitted")}>ارسال‌شده</option>
                            <option value="under_review" ${n("under_review")}>در بررسی</option>
                            <option value="approved"     ${n("approved")}>تأیید شده</option>
                            <option value="active"       ${n("active")}>فعال</option>
                            <option value="completed"    ${n("completed")}>پایان کار</option>
                            <option value="rejected"     ${n("rejected")}>رد شده</option>
                            <option value="expired"      ${n("expired")}>منقضی</option>
                        </select>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>شماره پروانه</label>
                        <input name="permit_number" value="${this.escape(s.permit_number||"")}">
                    </div>
                    <div class="acc-form-group"><label>شماره درخواست</label>
                        <input name="application_ref" value="${this.escape(s.application_ref||"")}">
                    </div>
                </div>
                <div class="acc-form-group"><label>پروژه</label>
                    <select name="project_id">${a}</select>
                </div>
                <div class="gis-info-divider">تاریخ‌ها</div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تاریخ درخواست</label>
                        <input name="application_date" type="date" value="${s.application_date||""}">
                    </div>
                    <div class="acc-form-group"><label>تاریخ تأیید</label>
                        <input name="approval_date" type="date" value="${s.approval_date||""}">
                    </div>
                </div>
                <div class="acc-form-group"><label>تاریخ انقضا</label>
                    <input name="expiry_date" type="date" value="${s.expiry_date||""}">
                </div>
                <div class="gis-info-divider">مشخصات ساختمانی مجاز</div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>طبقات مجاز</label>
                        <input name="allowed_floors" type="number" min="0" value="${s.allowed_floors||""}">
                    </div>
                    <div class="acc-form-group"><label>زیربنای مجاز (م²)</label>
                        <input name="allowed_area_sqm" type="number" step="0.1" value="${s.allowed_area_sqm||""}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کاربری مجاز</label>
                        <input name="allowed_use" value="${this.escape(s.allowed_use||"")}">
                    </div>
                    <div class="acc-form-group"><label>تراکم %</label>
                        <input name="density_pct" type="number" step="5" value="${s.density_pct||""}">
                    </div>
                </div>
                <div class="acc-form-group"><label>شهرداری / منطقه</label>
                    <input name="municipality" value="${this.escape(s.municipality||"")}">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>مهندس ناظر</label>
                        <input name="engineer_name" value="${this.escape(s.engineer_name||"")}">
                    </div>
                    <div class="acc-form-group"><label>کد نظام مهندسی</label>
                        <input name="engineer_code" value="${this.escape(s.engineer_code||"")}">
                    </div>
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="2">${this.escape(s.notes||"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"ثبت پروانه"}</button>
                </div>
            </form>
        </div>`,document.body.appendChild(r);const o=()=>r.remove();r.querySelector(".acc-modal__close").addEventListener("click",o),r.querySelector('[data-action="cancel"]').addEventListener("click",o),r.addEventListener("click",l=>{l.target===r&&o()}),r.querySelector("form").addEventListener("submit",async l=>{l.preventDefault();const c=Object.fromEntries(new FormData(l.target).entries());["application_date","approval_date","expiry_date","allowed_floors","allowed_area_sqm","density_pct","project_id"].forEach(h=>{c[h]||delete c[h]});const d=l.target.querySelector('[type="submit"]');d.disabled=!0;try{t?await this.api.put(`/permits/${e.id}`,c):await this.api.post("/permits",c),o(),this._toast(t?"✅ ویرایش شد":"✅ پروانه ثبت شد"),await this._load(),t&&this._openDetail({id:e.id})}catch(h){alert("خطا: "+((h==null?void 0:h.message)||"")),d.disabled=!1}})}_openFeeModal(e){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:400px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">💳 افزودن عارضه</div>
            <form>
                <div class="acc-form-group"><label>دسته‌بندی</label>
                    <select name="category">
                        ${Object.entries(Ds).map(([a,i])=>`<option value="${a}">${i}</option>`).join("")}
                    </select>
                </div>
                <div class="acc-form-group"><label>شرح *</label>
                    <input name="description" required placeholder="مثلاً: عوارض صدور پروانه">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>مبلغ (ریال) *</label>
                        <input name="amount" type="number" min="0" required>
                    </div>
                    <div class="acc-form-group"><label>سررسید</label>
                        <input name="due_date" type="date">
                    </div>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">افزودن</button>
                </div>
            </form>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector('[data-action="cancel"]').addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries());i.due_date||delete i.due_date;const n=a.target.querySelector('[type="submit"]');n.disabled=!0;try{await this.api.post(`/permits/${e}/fees`,i),s(),this._toast("✅ عارضه افزوده شد"),this._openDetail({id:e})}catch{alert("خطا"),n.disabled=!1}})}_openPayFeeModal(e,t,s){const a=s.find(o=>String(o.id)===String(t));if(!a)return;const i=o=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(o||0))),n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
        <div class="acc-modal" style="max-width:360px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">💳 ثبت پرداخت</div>
            <div style="background:#f0fdf4;border-radius:8px;padding:10px;font-size:13px;margin-bottom:14px;">
                ${this.escape(a.description)}: <b>${i(a.amount)} ریال</b>
            </div>
            <form>
                <div class="acc-form-group"><label>تاریخ پرداخت</label>
                    <input name="paid_date" type="date" value="${new Date().toISOString().split("T")[0]}">
                </div>
                <div class="acc-form-group"><label>شماره رسید</label>
                    <input name="receipt_number" placeholder="اختیاری">
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--success">✅ ثبت پرداخت</button>
                </div>
            </form>
        </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector('[data-action="cancel"]').addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()}),n.querySelector("form").addEventListener("submit",async o=>{o.preventDefault();const l=Object.fromEntries(new FormData(o.target).entries()),c=o.target.querySelector('[type="submit"]');c.disabled=!0;try{await this.api.post(`/permits/${e}/fees/${t}/pay`,l),r(),this._toast("✅ پرداخت ثبت شد","#10b981"),this._openDetail({id:e})}catch{alert("خطا"),c.disabled=!1}})}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;direction:rtl;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e||0)))}}const Mr={draft:"پیش‌نویس",submitted:"ارسال‌شده",under_review:"در بررسی",approved:"تأیید",active:"فعال",completed:"پایان کار",rejected:"رد",expired:"منقضی"},Ps={draft:"#94a3b8",submitted:"#3b82f6",under_review:"#f59e0b",approved:"#8b5cf6",active:"#10b981",completed:"#059669",rejected:"#ef4444",expired:"#dc2626"},Os={build:"پروانه ساخت",renovation:"بازسازی",demolish:"تخریب",use_change:"تغییر کاربری",completion:"پایان کار"};class Rr extends x{async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._load()}async _load(){const e=this.ref("root");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t=await this.api.get("/permits/dashboard");this._render(e,t)}catch{e.innerHTML='<div class="acc-error">خطا</div>'}}_render(e,t){const s=l=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(l||0))),a={};(t.by_status||[]).forEach(l=>{a[l.status]=parseInt(l.cnt)||0});const i=Object.values(a).reduce((l,c)=>l+c,0),n=`
        <div class="permit-kpi-grid">
            ${Object.entries(Mr).map(([l,c])=>a[l]>0?`
            <div class="permit-kpi-card" style="border-top:3px solid ${Ps[l]};">
                <div style="font-size:22px;font-weight:800;color:${Ps[l]};">${a[l]||0}</div>
                <div style="font-size:11px;color:#64748b;">${c}</div>
            </div>`:"").join("")}
            <div class="permit-kpi-card" style="border-top:3px solid #1e293b;">
                <div style="font-size:22px;font-weight:800;color:#1e293b;">${i}</div>
                <div style="font-size:11px;color:#64748b;">کل پروانه‌ها</div>
            </div>
        </div>`,r=(t.expiring||[]).length?`
        <div class="permit-alert-card permit-alert-card--warning">
            <div class="permit-alert-title">⏰ پروانه‌های رو به انقضا (۶۰ روز آینده)</div>
            ${t.expiring.map(l=>`
            <div class="permit-alert-row">
                <div>
                    <b>${l.permit_number||"—"}</b>
                    <span style="font-size:11px;color:#64748b;margin-right:6px;">${Os[l.type]||l.type}</span>
                </div>
                <span style="color:${l.days_left<=14?"#ef4444":"#f59e0b"};font-weight:700;font-size:12px;">
                    ${l.days_left} روز — ${l.expiry_date}
                </span>
            </div>`).join("")}
        </div>`:'<div class="permit-alert-card permit-alert-card--ok">✅ هیچ پروانه‌ای در ۶۰ روز آینده منقضی نمی‌شود</div>',o=(t.pending_fees||[]).length?`
        <div class="permit-alert-card permit-alert-card--danger">
            <div class="permit-alert-title">💳 عوارض معوق</div>
            ${t.pending_fees.map(l=>`
            <div class="permit-alert-row">
                <div>
                    <div style="font-size:12px;font-weight:700;">${this.escape(l.description)}</div>
                    <div style="font-size:11px;color:#64748b;">${l.permit_number||"—"} | ${Os[l.permit_type]||l.permit_type}</div>
                </div>
                <div style="text-align:left;">
                    <div style="font-weight:700;color:#ef4444;">${s(l.amount)} ریال</div>
                    ${l.due_date?`<div style="font-size:10px;color:#94a3b8;">${l.due_date}</div>`:""}
                </div>
            </div>`).join("")}
        </div>`:'<div class="permit-alert-card permit-alert-card--ok">✅ هیچ عارضه معوقی وجود ندارد</div>';e.innerHTML=`
        ${n}
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;margin-top:16px;">
            <div>${r}</div>
            <div>${o}</div>
        </div>`}}const $t=[{key:"list",icon:"📋",title:"پروانه‌ها",Class:Tr},{key:"dash",icon:"📊",title:"داشبورد",Class:Rr}];class Ns extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._active="list",this._sections={}}async template(){const t=$t.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
            </div>`).join(""),s=$t.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>`).join("");return`<div class="sp-section-nav" data-ref="navBar">${t}</div><div>${s}</div>`}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>this.on(t,"click",()=>this._switch(t.dataset.section))),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=$t.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(Ns,"title","📋 مجوزها"),E.register("permits",Ns);const Pe=[{key:"new_lead",label:"سرنخ جدید",icon:"🌱",color:"#94a3b8"},{key:"interested",label:"علاقه‌مند",icon:"💡",color:"#3b82f6"},{key:"visited",label:"بازدید کرده",icon:"👀",color:"#8b5cf6"},{key:"negotiating",label:"مذاکره",icon:"🤝",color:"#f59e0b"},{key:"proposed",label:"پیشنهاد",icon:"📄",color:"#f97316"},{key:"reserved",label:"رزرو",icon:"⭐",color:"#10b981"}],Vs=[{key:"converted",label:"تبدیل شد",icon:"✅",color:"#059669"},{key:"lost",label:"از دست رفت",icon:"❌",color:"#ef4444"}],kt={referral:"معرفی",website:"سایت",social:"شبکه اجتماعی",advertisement:"تبلیغات",exhibition:"نمایشگاه",cold_call:"تماس سرد",other:"سایر"},qr={call:"📞",meeting:"👥",visit:"🏠",message:"💬",email:"📧",note:"📝"},Hr={call:"تماس",meeting:"جلسه",visit:"بازدید",message:"پیام",email:"ایمیل",note:"یادداشت"},Br={positive:"#10b981",neutral:"#64748b",negative:"#ef4444",no_answer:"#f59e0b"},zr={positive:"مثبت",neutral:"خنثی",negative:"منفی",no_answer:"پاسخ ندادند"};class jr extends x{constructor(e={}){super(e),this._leads=[],this._selected=null,this._panelOpen=!1,this._activeTab="activity",this._projects=[],this._filter={search:"",project_id:""}}async template(){return'<div data-ref="root" style="direction:rtl;"></div>'}async afterRender(){try{const e=await this.api.get("/pc/projects",{per_page:200});this._projects=(e==null?void 0:e.data)??[]}catch{}await this._render()}async _render(){const e=this.ref("root"),t='<option value="">همه پروژه‌ها</option>'+this._projects.map(s=>`<option value="${s.id}">${this.escape(s.name)}</option>`).join("");e.innerHTML=`
        <div class="crm-wrap" data-ref="wrap">
            <!-- تولبار -->
            <div class="crm-toolbar">
                <input type="text" class="acc-input" data-ref="searchInp" placeholder="🔍 نام یا تلفن..." style="flex:1;max-width:220px;">
                <select class="event-type-filter" data-ref="projSel">${t}</select>
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="addBtn">➕ لید جدید</button>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="refreshBtn">🔄</button>
            </div>
            <!-- Kanban -->
            <div class="crm-board-wrap">
                <div class="crm-board" data-ref="board"></div>
                <!-- پانل راست -->
                <div class="crm-detail-pane" data-ref="detailPane">
                    <div class="crm-detail-inner" data-ref="detailInner"></div>
                </div>
            </div>
        </div>`,e.querySelectorAll("[data-ref]").forEach(s=>{this.refs[s.dataset.ref]=s}),this.on(this.ref("searchInp"),"input",()=>{this._filter.search=this.ref("searchInp").value,this._load()}),this.on(this.ref("projSel"),"change",()=>{this._filter.project_id=this.ref("projSel").value,this._load()}),this.on(this.ref("addBtn"),"click",()=>this._openLeadModal()),this.on(this.ref("refreshBtn"),"click",()=>this._load()),await this._load()}async _load(){const e=this.ref("board");e.innerHTML='<div class="acc-loading" style="padding:40px;"><div class="acc-spinner"></div></div>';const t={include_all:1};this._filter.project_id&&(t.project_id=this._filter.project_id),this._filter.search&&(t.search=this._filter.search);try{const s=await this.api.get("/crm/leads",t);this._leads=(s==null?void 0:s.data)??[],this._renderBoard()}catch{e.innerHTML='<div class="acc-error">خطا</div>'}}_renderBoard(){const e=this.ref("board");e.innerHTML="",[...Pe,...Vs].forEach(t=>{const s=this._leads.filter(i=>i.status===t.key),a=document.createElement("div");a.className="crm-col",a.innerHTML=`
            <div class="crm-col-header" style="border-top:3px solid ${t.color};">
                <span>${t.icon} ${t.label}</span>
                <span class="crm-col-count" style="background:${t.color};">${s.length}</span>
            </div>
            <div class="crm-col-body" data-stage="${t.key}">
                ${s.map(i=>this._leadCard(i,t)).join("")}
            </div>`,a.querySelectorAll("[data-lead-id]").forEach(i=>{const n=this._leads.find(r=>String(r.id)===i.dataset.leadId);n&&i.addEventListener("click",()=>this._openDetail(n))}),e.appendChild(a)})}_leadCard(e,t){var r;const s=o=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(o||0))),a=parseInt(e.days_since_contact)||0,i=e.last_contact_date&&a>7;return`
        <div class="crm-lead-card ${((r=this._selected)==null?void 0:r.id)==e.id?"crm-lead-card--active":""} ${i?"crm-lead-card--cold":""}"
             data-lead-id="${e.id}">
            <div class="crm-lead-name">${this.escape(e.name)}</div>
            ${e.phone?`<div class="crm-lead-phone">📞 ${e.phone}</div>`:""}
            ${e.budget_max?`<div class="crm-lead-budget">💰 تا ${s(e.budget_max)} ریال</div>`:""}
            ${e.project_name?`<div class="crm-lead-project">🏗️ ${this.escape(e.project_name)}</div>`:""}
            <div class="crm-lead-meta">
                <span title="${kt[e.source]||e.source}" style="color:#94a3b8;font-size:10px;">📌 ${kt[e.source]||e.source}</span>
                ${e.score>0?`<span class="crm-score-badge" style="background:${e.score>=70?"#10b981":e.score>=40?"#f59e0b":"#94a3b8"};">${e.score}</span>`:""}
            </div>
            ${i?`<div style="font-size:10px;color:#f59e0b;">⚠️ ${a} روز بدون تماس</div>`:""}
            ${e.pending_reminders>0?`<div style="font-size:10px;color:#ef4444;">🔔 ${e.pending_reminders} یادآور</div>`:""}
        </div>`}async _openDetail(e){this._selected=e,this._renderBoard();const t=this.ref("detailPane"),s=this.ref("detailInner");this._panelOpen||(t.classList.add("crm-detail-pane--open"),this._panelOpen=!0),s.innerHTML='<div class="acc-loading" style="padding:40px;"><div class="acc-spinner"></div></div>';try{const a=await this.api.get(`/crm/leads/${e.id}`),i=a==null?void 0:a.data;if(!i)return;this._selected=i,this._renderDetail(i)}catch{s.innerHTML='<div class="acc-error">خطا</div>'}}_renderDetail(e){const t=this.ref("detailInner"),s=i=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(i||0))),a=[...Pe,...Vs].find(i=>i.key===e.status)||Pe[0];t.innerHTML=`
        <!-- هدر -->
        <div class="crm-detail-header">
            <div style="flex:1;">
                <div class="crm-detail-name">${this.escape(e.name)}</div>
                <div style="display:flex;gap:6px;margin-top:4px;flex-wrap:wrap;">
                    <span style="background:${a.color};color:#fff;padding:2px 8px;border-radius:6px;font-size:11px;">
                        ${a.icon} ${a.label}
                    </span>
                    <span style="font-size:11px;color:#64748b;">${kt[e.source]||e.source}</span>
                    ${e.score>0?`<span class="crm-score-badge" style="background:${e.score>=70?"#10b981":e.score>=40?"#f59e0b":"#94a3b8"};">${e.score}/۱۰۰</span>`:""}
                </div>
            </div>
            <button class="gis-panel-close" data-ref="closeBtn">✕</button>
        </div>

        <!-- اطلاعات سریع -->
        <div class="crm-quick-info">
            ${e.phone?`<div>📞 <a href="tel:${e.phone}">${e.phone}</a></div>`:""}
            ${e.phone2?`<div>📞 ${e.phone2}</div>`:""}
            ${e.email?`<div>📧 ${e.email}</div>`:""}
            ${e.budget_max?`<div>💰 بودجه: تا ${s(e.budget_max)} ریال</div>`:""}
            ${e.preferred_type&&e.preferred_type!=="any"?`<div>🏢 نوع: ${e.preferred_type}</div>`:""}
            ${e.project_name?`<div>🏗️ پروژه: ${this.escape(e.project_name)}</div>`:""}
            ${e.next_followup?`<div>📅 پیگیری: ${e.next_followup}</div>`:""}
        </div>

        <!-- حرکت در پایپ‌لاین -->
        <div class="crm-stage-selector" data-ref="stageSel">
            ${Pe.map(i=>`
            <button class="crm-stage-btn ${e.status===i.key?"crm-stage-btn--active":""}"
                    style="border-color:${e.status===i.key?i.color:"#e2e8f0"};${e.status===i.key?"background:"+i.color+";color:#fff;":""}"
                    data-move="${i.key}">${i.icon} ${i.label}</button>`).join("")}
            <button class="crm-stage-btn" style="border-color:#ef4444;color:#ef4444;" data-move="lost">❌ از دست رفت</button>
        </div>

        <!-- تب‌ها -->
        <div class="gis-panel-tabs" data-ref="detailTabs">
            <button class="gis-panel-tab ${this._activeTab==="activity"?"gis-panel-tab--active":""}" data-tab="activity">
                📞 فعالیت‌ها (${(e.activities||[]).length})
            </button>
            <button class="gis-panel-tab ${this._activeTab==="reminder"?"gis-panel-tab--active":""}" data-tab="reminder">
                🔔 یادآور (${(e.reminders||[]).filter(i=>i.status==="pending").length})
            </button>
            <button class="gis-panel-tab ${this._activeTab==="units"?"gis-panel-tab--active":""}" data-tab="units">
                🏢 واحدها
            </button>
        </div>
        <div class="crm-tab-body" data-ref="tabBody">
            ${this._renderTabContent(this._activeTab,e)}
        </div>

        <!-- اکشن‌ها -->
        <div class="gis-panel-actions">
            <button class="gis-btn gis-btn--primary" data-ref="editBtn">✏️ ویرایش</button>
            <button class="gis-btn" data-ref="locBtn" style="background:#dbeafe;color:#1e40af;">📍 موقعیت‌ها</button>
            <button class="gis-btn gis-btn--success" data-ref="convertBtn">✅ تبدیل به مشتری</button>
            <button class="gis-btn gis-btn--danger"  data-ref="delBtn">🗑️</button>
        </div>`,t.querySelectorAll("[data-ref]").forEach(i=>{this.refs[i.dataset.ref]=i}),this.on(this.ref("closeBtn"),"click",()=>{this.ref("detailPane").classList.remove("crm-detail-pane--open"),this._panelOpen=!1,this._selected=null,this._renderBoard()}),t.querySelectorAll("[data-move]").forEach(i=>{i.addEventListener("click",async()=>{try{await this.api.post(`/crm/leads/${e.id}/move`,{status:i.dataset.move}),this._toast("✅ مرحله تغییر کرد"),await this._load(),this._openDetail({id:e.id})}catch{}})}),t.querySelectorAll(".gis-panel-tab").forEach(i=>{i.addEventListener("click",()=>{t.querySelectorAll(".gis-panel-tab").forEach(n=>n.classList.remove("gis-panel-tab--active")),i.classList.add("gis-panel-tab--active"),this._activeTab=i.dataset.tab,this.ref("tabBody").innerHTML=this._renderTabContent(i.dataset.tab,e),this._bindTabActions(i.dataset.tab,e)})}),this.on(this.ref("editBtn"),"click",()=>this._openLeadModal(e)),this.on(this.ref("locBtn"),"click",()=>z.openModal({api:this.api,entityType:"lead",entityId:e.id,entityName:e.full_name||e.name||`#${e.id}`})),this.on(this.ref("convertBtn"),"click",()=>this._openConvertModal(e)),this.on(this.ref("delBtn"),"click",async()=>{confirm("حذف این لید؟")&&(await this.api.delete(`/crm/leads/${e.id}`),this._toast("🗑️ حذف شد"),this.ref("detailPane").classList.remove("crm-detail-pane--open"),this._panelOpen=!1,this._selected=null,this._load())}),this._bindTabActions(this._activeTab,e)}_renderTabContent(e,t){switch(e){case"activity":return this._renderActivities(t.activities||[]);case"reminder":return this._renderReminders(t.reminders||[]);case"units":return this._renderUnitsTab(t);default:return""}}_renderActivities(e){return`<div class="gis-tab-content">
            <div class="gis-section-title">فعالیت‌ها
                <button class="gis-btn gis-btn--xs" data-action="add-act">+ ثبت فعالیت</button>
            </div>
            ${e.length?'<div class="crm-timeline">'+e.map(t=>{var s;return`
                <div class="crm-tl-item">
                    <div class="crm-tl-icon">${qr[t.type]||"📝"}</div>
                    <div class="crm-tl-body">
                        <div style="display:flex;justify-content:space-between;">
                            <b style="font-size:13px;">${this.escape(t.subject)}</b>
                            <span style="font-size:10px;color:${Br[t.result]||"#64748b"};">${zr[t.result]||""}</span>
                        </div>
                        <div style="font-size:11px;color:#64748b;">
                            ${Hr[t.type]||t.type} | ${((s=t.activity_date)==null?void 0:s.slice(0,16))||""}
                            ${t.duration_min?" | "+t.duration_min+" دقیقه":""}
                        </div>
                        ${t.body?`<div style="font-size:12px;color:#475569;margin-top:3px;">${this.escape(t.body)}</div>`:""}
                        ${t.next_action?`<div style="font-size:11px;color:#8b5cf6;margin-top:2px;">➡️ ${this.escape(t.next_action)}</div>`:""}
                        <button class="gis-btn gis-btn--xs gis-btn--danger" data-del-act="${t.id}" style="margin-top:4px;">🗑️</button>
                    </div>
                </div>`}).join("")+"</div>":'<div class="gis-empty-tab">فعالیتی ثبت نشده.</div>'}
        </div>`}_renderReminders(e){const t={pending:"#f59e0b",done:"#10b981",cancelled:"#94a3b8"},s={pending:"⏳ در انتظار",done:"✅ انجام شد",cancelled:"❌ لغو"};return`<div class="gis-tab-content">
            <div class="gis-section-title">یادآورها
                <button class="gis-btn gis-btn--xs" data-action="add-rem">+ افزودن</button>
            </div>
            ${e.length?e.map(a=>`
            <div class="crm-reminder-card" style="border-right:3px solid ${t[a.status]||"#94a3b8"};">
                <div style="display:flex;justify-content:space-between;">
                    <b>${this.escape(a.title)}</b>
                    <span style="font-size:10px;color:${t[a.status]};">${s[a.status]||a.status}</span>
                </div>
                <div style="font-size:11px;color:#64748b;">📅 ${a.due_date}${a.due_time?" ⏰ "+a.due_time:""}</div>
                <div style="display:flex;gap:4px;margin-top:6px;">
                    ${a.status==="pending"?`<button class="gis-btn gis-btn--xs" style="background:#dcfce7;color:#166534;" data-done-rem="${a.id}">✅ انجام شد</button>`:""}
                    <button class="gis-btn gis-btn--xs gis-btn--danger" data-del-rem="${a.id}">🗑️</button>
                </div>
            </div>`).join(""):'<div class="gis-empty-tab">یادآوری ثبت نشده.</div>'}
        </div>`}_renderUnitsTab(e){return`<div class="gis-tab-content">
            <div class="gis-section-title">واحدهای پیشنهادی بر اساس بودجه</div>
            <div data-ref="unitsResult">
                <div class="acc-loading"><div class="acc-spinner"></div></div>
            </div>
        </div>`}_bindTabActions(e,t){var a,i;const s=this.ref("tabBody");s&&(e==="activity"&&((a=s.querySelector('[data-action="add-act"]'))==null||a.addEventListener("click",()=>this._openActModal(t.id)),s.querySelectorAll("[data-del-act]").forEach(n=>{n.addEventListener("click",async()=>{confirm("حذف؟")&&(await this.api.delete(`/crm/activities/${n.dataset.delAct}`),this._toast("🗑️ حذف شد"),this._openDetail({id:t.id}))})})),e==="reminder"&&((i=s.querySelector('[data-action="add-rem"]'))==null||i.addEventListener("click",()=>this._openRemModal(t.id)),s.querySelectorAll("[data-done-rem]").forEach(n=>{n.addEventListener("click",async()=>{await this.api.put(`/crm/reminders/${n.dataset.doneRem}`,{status:"done"}),this._toast("✅ انجام شد","#10b981"),this._openDetail({id:t.id})})}),s.querySelectorAll("[data-del-rem]").forEach(n=>{n.addEventListener("click",async()=>{await this.api.delete(`/crm/reminders/${n.dataset.delRem}`),this._toast("🗑️"),this._openDetail({id:t.id})})})),e==="units"&&this.api.get(`/crm/leads/${t.id}/units`).then(n=>{const r=(n==null?void 0:n.data)??[],o=c=>new Intl.NumberFormat("fa-IR").format(Math.round(Number(c||0))),l=s.querySelector('[data-ref="unitsResult"]');if(l){if(!r.length){l.innerHTML='<div class="gis-empty-tab">واحد مطابق بودجه یافت نشد.</div>';return}l.innerHTML=r.map(c=>`
                <div class="crm-unit-card">
                    <div style="font-weight:700;">واحد ${this.escape(c.unit_number)} — طبقه ${c.floor}</div>
                    <div style="font-size:11px;color:#64748b;">${this.escape(c.project_name||"—")} | ${c.area_sqm||"—"} م²</div>
                    <div style="font-weight:700;color:#10b981;margin-top:4px;">${o(c.base_price)} ریال</div>
                </div>`).join("")}}).catch(()=>{}))}_openLeadModal(e=null){const t=!!e,s=e||{},a='<option value="">—</option>'+this._projects.map(o=>`<option value="${o.id}" ${s.project_id==o.id?"selected":""}>${this.escape(o.name)}</option>`).join(""),i=o=>s.source===o?"selected":"",n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
        <div class="acc-modal" style="max-width:500px;max-height:90vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🎯 ${t?"ویرایش":"لید جدید"}</div>
            <form>
                <div class="acc-form-group"><label>نام *</label>
                    <input name="name" required value="${this.escape(s.name||"")}">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تلفن</label>
                        <input name="phone" type="tel" value="${this.escape(s.phone||"")}">
                    </div>
                    <div class="acc-form-group"><label>تلفن دوم</label>
                        <input name="phone2" type="tel" value="${this.escape(s.phone2||"")}">
                    </div>
                </div>
                <div class="acc-form-group"><label>ایمیل</label>
                    <input name="email" type="email" value="${this.escape(s.email||"")}">
                </div>
                <div class="acc-form-group"><label>منبع آشنایی</label>
                    <select name="source">
                        <option value="referral"    ${i("referral")}>معرفی</option>
                        <option value="website"     ${i("website")}>سایت</option>
                        <option value="social"      ${i("social")}>شبکه اجتماعی</option>
                        <option value="advertisement" ${i("advertisement")}>تبلیغات</option>
                        <option value="exhibition"  ${i("exhibition")}>نمایشگاه</option>
                        <option value="cold_call"   ${i("cold_call")}>تماس سرد</option>
                        <option value="other"       ${i("other")}>سایر</option>
                    </select>
                </div>
                <div class="acc-form-group"><label>پروژه مورد علاقه</label>
                    <select name="project_id">${a}</select>
                </div>
                <div class="gis-info-divider">بودجه و ترجیحات</div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>حداقل بودجه (ریال)</label>
                        <input name="budget_min" type="number" value="${s.budget_min||""}">
                    </div>
                    <div class="acc-form-group"><label>حداکثر بودجه (ریال)</label>
                        <input name="budget_max" type="number" value="${s.budget_max||""}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>نوع واحد</label>
                        <select name="preferred_type">
                            <option value="any" ${s.preferred_type==="any"||!s.preferred_type?"selected":""}>هر نوع</option>
                            <option value="residential" ${s.preferred_type==="residential"?"selected":""}>مسکونی</option>
                            <option value="commercial"  ${s.preferred_type==="commercial"?"selected":""}>تجاری</option>
                            <option value="office"      ${s.preferred_type==="office"?"selected":""}>اداری</option>
                        </select>
                    </div>
                    <div class="acc-form-group"><label>متراژ (م²)</label>
                        <input name="preferred_area_sqm" type="number" value="${s.preferred_area_sqm||""}">
                    </div>
                </div>
                <div class="acc-form-group"><label>تاریخ پیگیری بعدی</label>
                    <input name="next_followup" type="date" value="${s.next_followup||""}">
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="2">${this.escape(s.notes||"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">${t?"ذخیره":"افزودن لید"}</button>
                </div>
            </form>
        </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector('[data-action="cancel"]').addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()}),n.querySelector("form").addEventListener("submit",async o=>{o.preventDefault();const l=Object.fromEntries(new FormData(o.target).entries());["budget_min","budget_max","preferred_area_sqm","project_id","next_followup"].forEach(d=>{l[d]||delete l[d]});const c=o.target.querySelector('[type="submit"]');c.disabled=!0;try{t?await this.api.put(`/crm/leads/${e.id}`,l):await this.api.post("/crm/leads",l),r(),this._toast(t?"✅ ویرایش شد":"✅ لید افزوده شد"),await this._load(),t&&this._openDetail({id:e.id})}catch(d){alert("خطا: "+((d==null?void 0:d.message)||"")),c.disabled=!1}})}_openActModal(e){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:420px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">📞 ثبت فعالیت</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>نوع</label>
                        <select name="type">
                            <option value="call">📞 تماس</option>
                            <option value="meeting">👥 جلسه</option>
                            <option value="visit">🏠 بازدید</option>
                            <option value="message">💬 پیام</option>
                            <option value="email">📧 ایمیل</option>
                            <option value="note">📝 یادداشت</option>
                        </select>
                    </div>
                    <div class="acc-form-group"><label>نتیجه</label>
                        <select name="result">
                            <option value="positive">✅ مثبت</option>
                            <option value="neutral" selected>➡️ خنثی</option>
                            <option value="negative">❌ منفی</option>
                            <option value="no_answer">📵 پاسخ ندادند</option>
                        </select>
                    </div>
                </div>
                <div class="acc-form-group"><label>موضوع *</label>
                    <input name="subject" required placeholder="خلاصه مکالمه/جلسه...">
                </div>
                <div class="acc-form-group"><label>توضیحات</label>
                    <textarea name="body" rows="3" placeholder="جزئیات..."></textarea>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تاریخ و ساعت</label>
                        <input name="activity_date" type="datetime-local" value="${new Date().toISOString().slice(0,16)}">
                    </div>
                    <div class="acc-form-group"><label>مدت (دقیقه)</label>
                        <input name="duration_min" type="number" min="0" placeholder="اختیاری">
                    </div>
                </div>
                <div class="acc-form-group"><label>اقدام بعدی</label>
                    <input name="next_action" placeholder="مثلاً: پیگیری در ۳ روز آینده">
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ثبت</button>
                </div>
            </form>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector('[data-action="cancel"]').addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries());["duration_min","next_action"].forEach(r=>{i[r]||delete i[r]});const n=a.target.querySelector('[type="submit"]');n.disabled=!0;try{await this.api.post(`/crm/leads/${e}/activities`,i),s(),this._toast("✅ فعالیت ثبت شد"),this._openDetail({id:e})}catch{alert("خطا"),n.disabled=!1}})}_openRemModal(e){const t=new Date;t.setDate(t.getDate()+1);const s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
        <div class="acc-modal" style="max-width:380px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🔔 یادآور جدید</div>
            <form>
                <div class="acc-form-group"><label>عنوان *</label>
                    <input name="title" required placeholder="مثلاً: پیگیری تلفنی">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تاریخ</label>
                        <input name="due_date" type="date" value="${t.toISOString().split("T")[0]}">
                    </div>
                    <div class="acc-form-group"><label>ساعت</label>
                        <input name="due_time" type="time" value="10:00">
                    </div>
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="2"></textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">افزودن</button>
                </div>
            </form>
        </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector('[data-action="cancel"]').addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries());n.notes||delete n.notes;const r=i.target.querySelector('[type="submit"]');r.disabled=!0;try{await this.api.post(`/crm/leads/${e}/reminders`,n),a(),this._toast("🔔 یادآور ثبت شد","#f59e0b"),this._openDetail({id:e})}catch{alert("خطا"),r.disabled=!1}})}_openConvertModal(e){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:360px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">✅ تبدیل به مشتری</div>
            <div style="background:#f0fdf4;border-radius:8px;padding:12px;margin-bottom:14px;font-size:13px;">
                لید «${this.escape(e.name)}» به عنوان مشتری واقعی ثبت خواهد شد.
            </div>
            <div class="acc-form-group"><label>شماره فروش (اختیاری)</label>
                <input id="sale-id-inp" type="number" placeholder="اگر واحدی فروخته شده">
            </div>
            <div class="acc-modal__actions">
                <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                <button class="acc-btn acc-btn--success" id="confirm-convert">✅ تأیید تبدیل</button>
            </div>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector('[data-action="cancel"]').addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("#confirm-convert").addEventListener("click",async()=>{const a=t.querySelector("#sale-id-inp").value;try{await this.api.post(`/crm/leads/${e.id}/convert`,{sale_id:a||void 0}),s(),this._toast("✅ لید به مشتری تبدیل شد","#10b981"),await this._load(),this.ref("detailPane").classList.remove("crm-detail-pane--open"),this._panelOpen=!1,this._selected=null}catch{alert("خطا")}})}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;direction:rtl;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const Ar={new_lead:"سرنخ",interested:"علاقه‌مند",visited:"بازدید",negotiating:"مذاکره",proposed:"پیشنهاد",reserved:"رزرو",converted:"تبدیل شد",lost:"از دست رفت"},Ws={new_lead:"#94a3b8",interested:"#3b82f6",visited:"#8b5cf6",negotiating:"#f59e0b",proposed:"#f97316",reserved:"#10b981",converted:"#059669",lost:"#ef4444"},Fr={referral:"معرفی",website:"سایت",social:"شبکه اجتماعی",advertisement:"تبلیغات",exhibition:"نمایشگاه",cold_call:"تماس سرد",other:"سایر"};class Ir extends x{async template(){return'<div data-ref="root"></div>'}async afterRender(){await this._load()}async _load(){const e=this.ref("root");e.innerHTML='<div class="acc-loading"><div class="acc-spinner"></div></div>';try{const t=await this.api.get("/crm/dashboard");this._render(e,t)}catch{e.innerHTML='<div class="acc-error">خطا</div>'}}_render(e,t){const s={};(t.by_status||[]).forEach(f=>{s[f.status]=parseInt(f.cnt)||0});const a=["new_lead","interested","visited","negotiating","proposed","reserved"],i=a.reduce((f,m)=>f+(s[m]||0),0),n=s.converted||0,r=s.lost||0,o=n+r>0?Math.round(n/(n+r)*100):0,l=`
        <div style="display:grid;grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:20px;">
            <div class="permit-kpi-card" style="border-top:3px solid #3b82f6;">
                <div style="font-size:22px;font-weight:800;color:#3b82f6;">${i}</div>
                <div style="font-size:11px;color:#64748b;">لید فعال</div>
            </div>
            <div class="permit-kpi-card" style="border-top:3px solid #10b981;">
                <div style="font-size:22px;font-weight:800;color:#10b981;">${n}</div>
                <div style="font-size:11px;color:#64748b;">تبدیل شده</div>
            </div>
            <div class="permit-kpi-card" style="border-top:3px solid #ef4444;">
                <div style="font-size:22px;font-weight:800;color:#ef4444;">${r}</div>
                <div style="font-size:11px;color:#64748b;">از دست رفته</div>
            </div>
            <div class="permit-kpi-card" style="border-top:3px solid #8b5cf6;">
                <div style="font-size:22px;font-weight:800;color:#8b5cf6;">${o}٪</div>
                <div style="font-size:11px;color:#64748b;">نرخ تبدیل</div>
            </div>
        </div>`,c=(t.overdue_reminders||[]).length?`
        <div style="background:#fef2f2;border:1px solid #fca5a5;border-radius:10px;padding:14px;margin-bottom:16px;">
            <div style="font-weight:700;font-size:13px;margin-bottom:10px;">🔔 یادآورهای معوق (${t.overdue_reminders.length})</div>
            ${t.overdue_reminders.map(f=>`
            <div style="display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid rgba(0,0,0,.05);font-size:12px;">
                <div>
                    <b>${this.escape(f.title)}</b>
                    <div style="color:#64748b;">${this.escape(f.lead_name)} ${f.lead_phone?"— "+f.lead_phone:""}</div>
                </div>
                <span style="color:#ef4444;font-size:11px;">📅 ${f.due_date}</span>
            </div>`).join("")}
        </div>`:'<div style="background:#f0fdf4;border:1px solid #86efac;border-radius:10px;padding:14px;margin-bottom:16px;color:#166534;">✅ هیچ یادآور معوقی وجود ندارد</div>',d=(t.cold_leads||[]).length?`
        <div style="background:#fffbeb;border:1px solid #fcd34d;border-radius:10px;padding:14px;margin-bottom:16px;">
            <div style="font-weight:700;font-size:13px;margin-bottom:10px;">🧊 لیدهای سرد (بدون تماس +۷ روز)</div>
            ${t.cold_leads.map(f=>`
            <div style="display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid rgba(0,0,0,.05);font-size:12px;">
                <div>
                    <b>${this.escape(f.name)}</b>
                    ${f.phone?`<span style="color:#64748b;"> — ${f.phone}</span>`:""}
                </div>
                <span style="color:#f59e0b;font-weight:700;">${f.days} روز</span>
            </div>`).join("")}
        </div>`:"",h=(t.by_source||[]).length?`
        <div style="background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:14px;margin-bottom:16px;">
            <div style="font-weight:700;font-size:13px;margin-bottom:10px;">📌 منبع آشنایی لیدها</div>
            ${t.by_source.map(f=>`
            <div style="display:flex;justify-content:space-between;align-items:center;padding:5px 0;font-size:12px;">
                <span>${Fr[f.source]||f.source}</span>
                <div style="display:flex;align-items:center;gap:8px;">
                    <div style="background:#e2e8f0;border-radius:4px;height:8px;width:80px;overflow:hidden;">
                        <div style="height:100%;background:#3b82f6;border-radius:4px;width:${i>0?Math.round(f.cnt/i*100):0}%"></div>
                    </div>
                    <b>${f.cnt}</b>
                </div>
            </div>`).join("")}
        </div>`:"",u=`
        <div style="background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:14px;margin-bottom:16px;">
            <div style="font-weight:700;font-size:13px;margin-bottom:10px;">📊 توزیع بر اساس مرحله</div>
            ${a.map(f=>s[f]>0?`
            <div style="display:flex;justify-content:space-between;align-items:center;padding:4px 0;font-size:12px;">
                <span style="color:${Ws[f]};">${Ar[f]}</span>
                <div style="display:flex;align-items:center;gap:8px;">
                    <div style="background:#e2e8f0;border-radius:4px;height:8px;width:80px;overflow:hidden;">
                        <div style="height:100%;background:${Ws[f]};border-radius:4px;width:${i>0?Math.round((s[f]||0)/i*100):0}%"></div>
                    </div>
                    <b>${s[f]||0}</b>
                </div>
            </div>`:"").join("")}
        </div>`;e.innerHTML=`
        ${l}
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:16px;">
            <div>${c}${d}</div>
            <div>${u}${h}</div>
        </div>`}}const Et=[{key:"pipeline",icon:"🎯",title:"پایپ‌لاین",Class:jr},{key:"dash",icon:"📊",title:"داشبورد",Class:Ir}];class Us extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._active="pipeline",this._sections={}}async template(){const t=Et.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
            </div>`).join(""),s=Et.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>`).join("");return`<div class="sp-section-nav" data-ref="navBar">${t}</div><div>${s}</div>`}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>this.on(t,"click",()=>this._switch(t.dataset.section))),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=Et.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(Us,"title","🎯 CRM"),E.register("crm",Us);class Dr extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📊 موجودی انبار</h2>
                <div style="display:flex;gap:8px;align-items:center;">
                    <input type="text" data-ref="search" placeholder="جستجو محصول..."
                           class="acc-input" style="width:200px;">
                    <select data-ref="whFilter" class="acc-input">
                        <option value="">همه انبارها</option>
                    </select>
                    <button class="acc-btn acc-btn--warning" data-ref="lowBtn">
                        ⚠️ کم‌موجودی
                    </button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>

            <!-- آمار سریع -->
            <div class="inv-stats-row" data-ref="statsRow" style="display:flex;gap:12px;margin:12px 0;flex-wrap:wrap;"></div>

            <div data-ref="tableWrap">
                <div class="acc-loading">⏳ در حال بارگذاری...</div>
            </div>
        </div>`}async afterRender(){await this._loadWarehouses(),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("lowBtn"),"click",()=>this._loadLow()),this.on(this.ref("search"),"input",()=>this._filter()),this.on(this.ref("whFilter"),"change",()=>this._load())}async _loadWarehouses(){try{const e=await this.api.get("/inv/warehouses"),t=this.ref("whFilter");((e==null?void 0:e.data)??[]).forEach(s=>{const a=document.createElement("option");a.value=s.id,a.textContent=s.name,t.appendChild(a)})}catch{}}async _load(){var t;const e=(t=this.ref("whFilter"))==null?void 0:t.value;this.ref("tableWrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{let s=e?`/inv/stock/warehouse/${e}`:"/inv/stock";const a=await this.api.get(s);this._rows=(a==null?void 0:a.data)??[],this._renderStats(),this._renderTable(this._rows)}catch{this.ref("tableWrap").innerHTML='<div class="acc-error">❌ خطا در بارگذاری</div>'}}async _loadLow(){this.ref("tableWrap").innerHTML='<div class="acc-loading">⏳ بارگذاری کم‌موجودی‌ها...</div>';try{const e=await this.api.get("/inv/stock/low"),t=(e==null?void 0:e.data)??[];if(!t.length){this.ref("tableWrap").innerHTML='<div class="acc-empty">✅ همه محصولات موجودی کافی دارند</div>';return}this._renderTable(t,!0)}catch{}}_renderStats(){const e=this._rows??[],t=e.reduce((i,n)=>i+parseFloat(n.stock_value??n.qty*(n.avg_cost??0)),0),s=e.length,a=new Set(e.map(i=>i.warehouse_id)).size;this.ref("statsRow").innerHTML=`
            <div class="inv-stat-card">📦 <b>${s}</b> قلم</div>
            <div class="inv-stat-card">🏭 <b>${a}</b> انبار</div>
            <div class="inv-stat-card">💰 ارزش: <b>${this._fmt(t)}</b> ﷼</div>
        `}_renderTable(e,t=!1){if(!e.length){this.ref("tableWrap").innerHTML='<div class="acc-empty">موجودی یافت نشد</div>';return}const s=`
        <table class="acc-table">
            <thead><tr>
                <th>کد</th><th>نام محصول</th><th>انبار</th>
                <th>موجودی</th><th>واحد</th><th>بهای میانگین</th><th>ارزش کل</th>
                ${t?"<th>حداقل</th>":""}
            </tr></thead>
            <tbody>
            ${e.map(a=>{const i=parseFloat(a.qty??a.total_qty??0),n=parseFloat(a.avg_cost??0),r=i*n;return`<tr ${t&&i<=parseFloat(a.min_stock??0)?'style="background:#fef2f2;"':""}>
                    <td>${this.escape(a.product_code??a.code??"")}</td>
                    <td>${this.escape(a.product_name??a.name??"")}</td>
                    <td>${this.escape(a.warehouse_name??"")}</td>
                    <td style="font-weight:700;color:${i<=0?"#ef4444":"#1d4ed8"};">${this._fmt(i)}</td>
                    <td>${this.escape(a.unit??"")}</td>
                    <td>${n>0?this._fmt(n):"—"}</td>
                    <td>${r>0?this._fmt(r):"—"}</td>
                    ${t?`<td style="color:#ef4444;">${this._fmt(a.min_stock)}</td>`:""}
                </tr>`}).join("")}
            </tbody>
        </table>`;this.ref("tableWrap").innerHTML=s}_filter(){var s;const e=(((s=this.ref("search"))==null?void 0:s.value)??"").toLowerCase();if(!e){this._renderTable(this._rows??[]);return}const t=(this._rows??[]).filter(a=>(a.product_name??"").toLowerCase().includes(e)||(a.product_code??"").toLowerCase().includes(e));this._renderTable(t)}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const Oe={purchase_receipt:{label:"ورود از خرید",icon:"📥",color:"#10b981"},sale_issue:{label:"خروج برای فروش",icon:"📤",color:"#3b82f6"},return_in:{label:"مرجوعی ورودی",icon:"↩️",color:"#8b5cf6"},return_out:{label:"مرجوعی خروجی",icon:"↪️",color:"#f97316"},waste:{label:"ضایعات",icon:"🗑️",color:"#ef4444"},consignment_out:{label:"صدور امانی",icon:"📦",color:"#f59e0b"},consignment_return:{label:"برگشت امانت",icon:"🔄",color:"#06b6d4"},transfer:{label:"انتقال بین انبار",icon:"🔃",color:"#6366f1"},adjustment:{label:"تعدیل موجودی",icon:"⚖️",color:"#64748b"},project_issue:{label:"خروج پروژه",icon:"🏗️",color:"#84cc16"}},Gs={draft:{label:"پیش‌نویس",color:"#94a3b8"},confirmed:{label:"تأیید شده",color:"#10b981"},cancelled:{label:"لغو شده",color:"#ef4444"}};class Pr extends x{constructor(e){super(e),this._warehouses=[],this._products=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📄 اسناد حرکت انبار</h2>
                <div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
                    <select data-ref="typeFilter" class="acc-input">
                        <option value="">همه انواع</option>${Object.entries(Oe).map(([t,s])=>`<option value="${t}">${s.icon} ${s.label}</option>`).join("")}
                    </select>
                    <select data-ref="statusFilter" class="acc-input">
                        <option value="">همه وضعیت‌ها</option>
                        <option value="draft">پیش‌نویس</option>
                        <option value="confirmed">تأیید شده</option>
                        <option value="cancelled">لغو شده</option>
                    </select>
                    <input type="date" data-ref="fromDate" class="acc-input" title="از تاریخ">
                    <input type="date" data-ref="toDate"   class="acc-input" title="تا تاریخ">
                    <button class="acc-btn acc-btn--primary" data-ref="newBtn" data-perm="inv.vouchers.create">➕ سند جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="tableWrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await Promise.all([this._loadWarehouses(),this._loadProducts()]),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("newBtn"),"click",()=>this._openModal()),this.on(this.ref("typeFilter"),"change",()=>this._load()),this.on(this.ref("statusFilter"),"change",()=>this._load()),this.on(this.ref("fromDate"),"change",()=>this._load()),this.on(this.ref("toDate"),"change",()=>this._load())}async _loadWarehouses(){try{const e=await this.api.get("/inv/warehouses");this._warehouses=(e==null?void 0:e.data)??[]}catch{}}async _loadProducts(){try{const e=await this.api.get("/inv/products");this._products=(e==null?void 0:e.data)??[]}catch{}}async _load(){var n,r,o,l;const e={},t=(n=this.ref("typeFilter"))==null?void 0:n.value,s=(r=this.ref("statusFilter"))==null?void 0:r.value,a=(o=this.ref("fromDate"))==null?void 0:o.value,i=(l=this.ref("toDate"))==null?void 0:l.value;t&&(e.type=t),s&&(e.status=s),a&&(e.from=a),i&&(e.to=i),this.ref("tableWrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const c=await this.api.get("/inv/vouchers",e);this._renderTable((c==null?void 0:c.data)??[])}catch{this.ref("tableWrap").innerHTML='<div class="acc-error">❌ خطا در بارگذاری</div>'}}_renderTable(e){if(!e.length){this.ref("tableWrap").innerHTML='<div class="acc-empty">سندی یافت نشد</div>';return}this.ref("tableWrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>شماره سند</th><th>نوع</th><th>تاریخ</th><th>وضعیت</th>
                <th>ردیف</th><th>توضیح</th><th>اقدام</th>
            </tr></thead>
            <tbody>
            ${e.map(t=>{const s=Oe[t.type]??{label:t.type,icon:"📄",color:"#64748b"},a=Gs[t.status]??{label:t.status,color:"#64748b"};return`<tr>
                    <td style="font-weight:700;">${this.escape(t.voucher_no)}</td>
                    <td><span style="color:${s.color};font-weight:600;">${s.icon} ${s.label}</span></td>
                    <td>${t.date??""}</td>
                    <td><span style="color:${a.color};font-weight:600;">${a.label}</span></td>
                    <td>${t.item_count??0} ردیف</td>
                    <td style="max-width:180px;overflow:hidden;text-overflow:ellipsis;">${this.escape(t.description??"")}</td>
                    <td style="display:flex;gap:4px;">
                        <button class="acc-btn acc-btn--xs" data-action="view" data-id="${t.id}">👁️</button>
                        ${t.status==="draft"?`
                        <button class="acc-btn acc-btn--xs" data-action="confirm" data-id="${t.id}" data-perm="inv.vouchers.confirm" style="background:#d1fae5;color:#065f46;">✅ تأیید</button>
                        <button class="acc-btn acc-btn--xs" data-action="edit"    data-id="${t.id}" data-perm="inv.vouchers.create">✏️</button>
                        <button class="acc-btn acc-btn--xs gis-btn--danger" data-action="cancel" data-id="${t.id}" data-perm="inv.vouchers.cancel">🗑️</button>
                        `:""}
                    </td>
                </tr>`}).join("")}
            </tbody>
        </table>`,this.ref("tableWrap").querySelectorAll("[data-action]").forEach(t=>{t.addEventListener("click",()=>{const s=parseInt(t.dataset.id);t.dataset.action==="view"&&this._viewVoucher(s),t.dataset.action==="edit"&&this._openModal(s),t.dataset.action==="confirm"&&this._confirm(s),t.dataset.action==="cancel"&&this._cancel(s)})}),this.applyAclToDom(this.ref("tableWrap"))}async _viewVoucher(e){try{const t=await this.api.get(`/inv/vouchers/${e}`),s=t==null?void 0:t.data;if(!s)return;const a=Oe[s.type]??{label:s.type,icon:"📄"},i=Gs[s.status]??{label:s.status},n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
            <div class="acc-modal" style="max-width:700px;max-height:90vh;overflow-y:auto;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">${a.icon} سند ${this.escape(s.voucher_no)}</div>
                <div style="display:flex;gap:12px;margin-bottom:12px;font-size:13px;flex-wrap:wrap;">
                    <span>📅 ${s.date}</span>
                    <span>وضعیت: <b>${i.label}</b></span>
                    ${s.ref_no?`<span>مرجع: ${this.escape(s.ref_no)}</span>`:""}
                    ${s.created_by?`<span>ثبت‌کننده: ${this.escape(s.created_by)}</span>`:""}
                </div>
                ${s.description?`<div style="background:#f8fafc;padding:8px;border-radius:6px;margin-bottom:12px;font-size:12px;">${this.escape(s.description)}</div>`:""}
                <table class="acc-table">
                    <thead><tr><th>محصول</th><th>از انبار</th><th>به انبار</th><th>تعداد</th><th>قیمت واحد</th><th>مبلغ کل</th></tr></thead>
                    <tbody>
                    ${(s.items??[]).map(r=>`<tr>
                        <td>${this.escape(r.product_name??"")} <small style="color:#94a3b8;">${this.escape(r.product_code??"")}</small></td>
                        <td>${this.escape(r.from_warehouse_name??"—")}</td>
                        <td>${this.escape(r.to_warehouse_name??"—")}</td>
                        <td>${this._fmt(r.qty)} ${this.escape(r.unit??"")}</td>
                        <td>${r.unit_price>0?this._fmt(r.unit_price):"—"}</td>
                        <td>${r.total_price>0?this._fmt(r.total_price):"—"}</td>
                    </tr>`).join("")}
                    </tbody>
                </table>
                <div style="margin-top:12px;text-align:left;">
                    <b>جمع کل: ${this._fmt((s.items??[]).reduce((r,o)=>r+parseFloat(o.total_price??0),0))} ﷼</b>
                </div>
            </div>`,document.body.appendChild(n),n.querySelector(".acc-modal__close").addEventListener("click",()=>n.remove()),n.addEventListener("click",r=>{r.target===n&&n.remove()})}catch{alert("خطا در بارگذاری سند")}}async _confirm(e){if(confirm("آیا از تأیید این سند مطمئن هستید؟"))try{await this.api.post(`/inv/vouchers/${e}/confirm`,{}),this._toast("✅ سند تأیید شد","#10b981"),this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}async _cancel(e){if(confirm("آیا از لغو این سند مطمئن هستید؟"))try{await this.api.delete(`/inv/vouchers/${e}`),this._toast("🗑️ سند لغو شد"),this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}_openModal(e=null){const t=Object.entries(Oe).map(([c,d])=>`<option value="${c}">${d.icon} ${d.label}</option>`).join(""),s=this._warehouses.map(c=>`<option value="${c.id}">${c.name} (${c.type})</option>`).join(""),a=this._products.map(c=>`<option value="${c.id}" data-unit="${c.unit}">${c.name} [${c.code}]</option>`).join(""),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
        <div class="acc-modal" style="max-width:700px;max-height:90vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">📄 سند جدید حرکت انبار</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group">
                        <label>نوع سند *</label>
                        <select name="type" required>${t}</select>
                    </div>
                    <div class="acc-form-group">
                        <label>تاریخ *</label>
                        <input name="date" type="date" value="${new Date().toISOString().split("T")[0]}" required>
                    </div>
                </div>
                <div class="acc-form-group">
                    <label>توضیح</label>
                    <input name="description" type="text" placeholder="اختیاری">
                </div>
                <div class="acc-form-group">
                    <label>ثبت‌کننده</label>
                    <input name="created_by" type="text" placeholder="نام">
                </div>

                <div class="gis-info-divider">ردیف‌های سند</div>
                <div data-ref-inner="items" id="inv-items-container"></div>
                <button type="button" id="inv-add-row" class="acc-btn acc-btn--secondary acc-btn--sm" style="margin-bottom:12px;">
                    ➕ افزودن ردیف
                </button>

                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">💾 ذخیره پیش‌نویس</button>
                </div>
            </form>
        </div>`,document.body.appendChild(i);const n=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",n),i.querySelector("[data-action=cancel]").addEventListener("click",n),i.addEventListener("click",c=>{c.target===i&&n()});const r=i.querySelector("#inv-items-container");let o=0;const l=()=>{const c=o++,d=document.createElement("div");d.className="inv-item-row",d.style.cssText="display:grid;grid-template-columns:2fr 1fr 1fr 1fr 1fr auto;gap:6px;margin-bottom:6px;align-items:end;",d.innerHTML=`
                <div><label style="font-size:11px;">محصول</label>
                    <select name="items[${c}][product_id]" class="acc-input" required><option value="">انتخاب...</option>${a}</select>
                </div>
                <div><label style="font-size:11px;">از انبار</label>
                    <select name="items[${c}][from_warehouse_id]" class="acc-input"><option value="">—</option>${s}</select>
                </div>
                <div><label style="font-size:11px;">به انبار</label>
                    <select name="items[${c}][to_warehouse_id]" class="acc-input"><option value="">—</option>${s}</select>
                </div>
                <div><label style="font-size:11px;">تعداد</label>
                    <input name="items[${c}][qty]" type="number" min="0.001" step="any" class="acc-input" required>
                </div>
                <div><label style="font-size:11px;">قیمت واحد</label>
                    <input name="items[${c}][unit_price]" type="number" min="0" step="any" class="acc-input" placeholder="0">
                </div>
                <button type="button" class="acc-btn acc-btn--xs gis-btn--danger" style="margin-top:18px;" onclick="this.closest('.inv-item-row').remove()">✕</button>
            `,r.appendChild(d)};l(),i.querySelector("#inv-add-row").addEventListener("click",l),i.querySelector("form").addEventListener("submit",async c=>{c.preventDefault();const d=new FormData(c.target),h={type:d.get("type"),date:d.get("date"),description:d.get("description")??"",created_by:d.get("created_by")??"",items:[]};if(r.querySelectorAll(".inv-item-row").forEach(m=>{var y,$,w,_,k;const b=(y=m.querySelector("[name$='[product_id]']"))==null?void 0:y.value,v=parseFloat((($=m.querySelector("[name$='[qty]']"))==null?void 0:$.value)??0);!b||v<=0||h.items.push({product_id:parseInt(b),from_warehouse_id:((w=m.querySelector("[name$='[from_warehouse_id]']"))==null?void 0:w.value)||null,to_warehouse_id:((_=m.querySelector("[name$='[to_warehouse_id]']"))==null?void 0:_.value)||null,qty:v,unit_price:parseFloat(((k=m.querySelector("[name$='[unit_price]']"))==null?void 0:k.value)??0)})}),!h.items.length){alert("حداقل یک ردیف وارد کنید");return}const f=c.target.querySelector("[type=submit]");f.disabled=!0,f.textContent="در حال ذخیره...";try{await this.api.post("/inv/vouchers",h),n(),this._toast("✅ سند ذخیره شد"),this._load()}catch(m){alert("خطا: "+((m==null?void 0:m.message)??"")),f.disabled=!1,f.textContent="💾 ذخیره پیش‌نویس"}})}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const Or={avg:"میانگین موزون",fifo:"FIFO"},Nr={none:"—",batch:"بچ/لات",serial:"سریال",both:"بچ + سریال"};class Vr extends x{constructor(e){super(e),this._categories=[]}async template(){return`
        <div class="acc-section-wrap" style="display:grid;grid-template-columns:220px 1fr;gap:16px;height:100%;">
            <!-- درخت دسته‌بندی -->
            <div style="border-left:1px solid #e2e8f0;padding-left:12px;">
                <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
                    <b style="font-size:13px;">دسته‌بندی‌ها</b>
                    <button class="acc-btn acc-btn--xs" data-ref="addCatBtn">➕</button>
                </div>
                <div data-ref="catTree" style="font-size:12px;"></div>
            </div>

            <!-- لیست محصولات -->
            <div>
                <div class="acc-toolbar" style="margin-bottom:12px;">
                    <h3 data-ref="catTitle" style="margin:0;font-size:14px;">همه محصولات</h3>
                    <div style="display:flex;gap:8px;">
                        <input type="text" data-ref="search" placeholder="جستجو..." class="acc-input" style="width:180px;">
                        <button class="acc-btn acc-btn--primary" data-ref="addProdBtn">➕ محصول جدید</button>
                        <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                    </div>
                </div>
                <div data-ref="prodWrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
            </div>
        </div>`}async afterRender(){await this._loadCategories(),await this._loadProducts(),this.on(this.ref("refreshBtn"),"click",()=>this._loadProducts()),this.on(this.ref("addProdBtn"),"click",()=>this._openProductModal()),this.on(this.ref("addCatBtn"),"click",()=>this._openCategoryModal()),this.on(this.ref("search"),"input",()=>this._filterProducts()),this._activeCat=null}async _loadCategories(){try{const e=await this.api.get("/inv/categories");this._categories=(e==null?void 0:e.data)??[],this._renderCatTree()}catch{}}_renderCatTree(){const e=this.ref("catTree"),t=this._categories,s=(a,i)=>t.filter(n=>parseInt(n.parent_id)===a).map(n=>`
                <div style="padding:4px 0 4px ${i*12}px;cursor:pointer;border-radius:4px;"
                     class="inv-cat-item ${this._activeCat===n.id?"inv-cat-item--active":""}"
                     data-cat-id="${n.id}" data-cat-name="${this.escape(n.name)}">
                    ${i>0?"└ ":""}${this.escape(n.name)}
                    <small style="color:#94a3b8;">(${n.product_count??0})</small>
                </div>
                ${s(n.id,i+1)}
            `).join("");e.innerHTML=`
            <div style="padding:4px 0;cursor:pointer;font-weight:600;" data-cat-id="" data-cat-name="همه محصولات" class="inv-cat-item ${this._activeCat?"":"inv-cat-item--active"}">
                📁 همه محصولات
            </div>
            ${s(0,0)}
        `,e.querySelectorAll(".inv-cat-item").forEach(a=>{a.addEventListener("click",()=>{this._activeCat=a.dataset.catId?parseInt(a.dataset.catId):null,this.ref("catTitle").textContent=a.dataset.catName,e.querySelectorAll(".inv-cat-item").forEach(i=>i.classList.remove("inv-cat-item--active")),a.classList.add("inv-cat-item--active"),this._loadProducts()})})}async _loadProducts(){const e={};this._activeCat&&(e.category_id=this._activeCat),this.ref("prodWrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const t=await this.api.get("/inv/products",e);this._rows=(t==null?void 0:t.data)??[],this._renderProducts(this._rows)}catch{this.ref("prodWrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_renderProducts(e){if(!e.length){this.ref("prodWrap").innerHTML='<div class="acc-empty">محصولی یافت نشد</div>';return}this.ref("prodWrap").innerHTML=`
        <table class="acc-table">
            <thead><tr><th>کد</th><th>نام</th><th>دسته</th><th>واحد</th><th>موجودی</th><th>قیمت‌گذاری</th><th>ردیابی</th><th>اقدام</th></tr></thead>
            <tbody>
            ${e.map(t=>`<tr>
                <td style="font-weight:600;">${this.escape(t.code)}</td>
                <td>${this.escape(t.name)}</td>
                <td><small>${this.escape(t.category_name??"—")}</small></td>
                <td>${this.escape(t.unit)}</td>
                <td style="color:${parseFloat(t.total_stock)>0?"#1d4ed8":"#94a3b8"};">${this._fmt(t.total_stock)}</td>
                <td><small>${Or[t.costing_method]??t.costing_method}</small></td>
                <td><small>${Nr[t.tracking]??t.tracking}</small></td>
                <td style="display:flex;gap:4px;">
                    <button class="acc-btn acc-btn--xs" data-edit="${t.id}">✏️</button>
                    <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${t.id}" ${parseFloat(t.total_stock)>0?"disabled title='موجودی دارد'":""}>🗑️</button>
                </td>
            </tr>`).join("")}
            </tbody>
        </table>`,this.ref("prodWrap").querySelectorAll("[data-edit]").forEach(t=>t.addEventListener("click",()=>{const s=this._rows.find(a=>a.id==t.dataset.edit);s&&this._openProductModal(s)})),this.ref("prodWrap").querySelectorAll("[data-del]").forEach(t=>t.addEventListener("click",async()=>{if(confirm("حذف این محصول؟"))try{await this.api.delete(`/inv/products/${t.dataset.del}`),this._toast("✅ حذف شد"),this._loadProducts()}catch(s){alert("خطا: "+((s==null?void 0:s.message)??""))}}))}_filterProducts(){var t;const e=(((t=this.ref("search"))==null?void 0:t.value)??"").toLowerCase();if(!e){this._renderProducts(this._rows??[]);return}this._renderProducts((this._rows??[]).filter(s=>s.name.toLowerCase().includes(e)||(s.code??"").toLowerCase().includes(e)))}_openProductModal(e=null){const t=!!e,s=this._categories.map(n=>`<option value="${n.id}" ${(e==null?void 0:e.category_id)==n.id?"selected":""}>${"—".repeat(n.level)} ${this.escape(n.name)}</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
        <div class="acc-modal" style="max-width:520px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش":"➕ محصول جدید"}</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد *</label>
                        <input name="code" required value="${this.escape((e==null?void 0:e.code)??"")}">
                    </div>
                    <div class="acc-form-group"><label>نام *</label>
                        <input name="name" required value="${this.escape((e==null?void 0:e.name)??"")}">
                    </div>
                </div>
                <div class="acc-form-group"><label>دسته‌بندی</label>
                    <select name="category_id"><option value="">— بدون دسته —</option>${s}</select>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>واحد اصلی</label>
                        <input name="unit" value="${this.escape((e==null?void 0:e.unit)??"عدد")}">
                    </div>
                    <div class="acc-form-group"><label>واحد دوم</label>
                        <input name="unit2" value="${this.escape((e==null?void 0:e.unit2)??"")}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>روش قیمت‌گذاری</label>
                        <select name="costing_method">
                            <option value="avg"  ${(e==null?void 0:e.costing_method)==="avg"?"selected":""}>میانگین موزون</option>
                            <option value="fifo" ${(e==null?void 0:e.costing_method)==="fifo"?"selected":""}>FIFO</option>
                        </select>
                    </div>
                    <div class="acc-form-group"><label>ردیابی</label>
                        <select name="tracking">
                            <option value="none"   ${(e==null?void 0:e.tracking)==="none"?"selected":""}>بدون ردیابی</option>
                            <option value="batch"  ${(e==null?void 0:e.tracking)==="batch"?"selected":""}>بچ / لات</option>
                            <option value="serial" ${(e==null?void 0:e.tracking)==="serial"?"selected":""}>سریال نامبر</option>
                            <option value="both"   ${(e==null?void 0:e.tracking)==="both"?"selected":""}>هر دو</option>
                        </select>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>حداقل موجودی</label>
                        <input name="min_stock" type="number" min="0" step="any" value="${(e==null?void 0:e.min_stock)??0}">
                    </div>
                    <div class="acc-form-group"><label>مقدار سفارش مجدد</label>
                        <input name="reorder_qty" type="number" min="0" step="any" value="${(e==null?void 0:e.reorder_qty)??0}">
                    </div>
                </div>
                <div class="acc-form-group"><label>توضیحات</label>
                    <textarea name="description" rows="2">${this.escape((e==null?void 0:e.description)??"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action=cancel]").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());r.category_id||delete r.category_id;const o=n.target.querySelector("[type=submit]");o.disabled=!0;try{t?(await this.api.put(`/inv/products/${e.id}`,r),this._toast("✅ ویرایش شد")):(await this.api.post("/inv/products",r),this._toast("✅ محصول ثبت شد")),i(),this._loadProducts()}catch(l){alert("خطا: "+((l==null?void 0:l.message)??"")),o.disabled=!1}})}_openCategoryModal(){const e=this._categories.map(a=>`<option value="${a.id}">${"—".repeat(a.level)} ${this.escape(a.name)}</option>`).join(""),t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:380px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">➕ دسته‌بندی جدید</div>
            <form>
                <div class="acc-form-group"><label>دسته والد</label>
                    <select name="parent_id"><option value="0">— سطح اول —</option>${e}</select>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد</label><input name="code"></div>
                    <div class="acc-form-group"><label>نام *</label><input name="name" required></div>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector("[data-action=cancel]").addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries()),n=a.target.querySelector("[type=submit]");n.disabled=!0;try{await this.api.post("/inv/categories",i),this._toast("✅ دسته ثبت شد"),s(),await this._loadCategories()}catch(r){alert("خطا: "+((r==null?void 0:r.message)??"")),n.disabled=!1}})}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const Ks={main:"انبار اصلی",scrap:"ضایعات",consignment:"امانت",project:"پروژه"};class Wr extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🏭 انبارها</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ انبار جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/inv/warehouses"),t=(e==null?void 0:e.data)??[];if(!t.length){this.ref("wrap").innerHTML='<div class="acc-empty">انباری ثبت نشده</div>';return}this.ref("wrap").innerHTML=`
            <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:16px;padding:4px;">
                ${t.map(s=>`
                <div class="inv-wh-card" style="border:1px solid #e2e8f0;border-radius:10px;padding:16px;">
                    <div style="display:flex;justify-content:space-between;align-items:start;">
                        <div>
                            <div style="font-weight:700;font-size:15px;">🏭 ${this.escape(s.name)}</div>
                            <div style="font-size:11px;color:#64748b;margin-top:2px;">${Ks[s.type]??s.type} | کد: ${this.escape(s.code)}</div>
                        </div>
                        <div style="display:flex;gap:4px;">
                            <button class="acc-btn acc-btn--xs" data-edit="${s.id}">✏️</button>
                            <button class="acc-btn acc-btn--xs" data-loc="${s.id}" data-name="${this.escape(s.name)}" style="background:#dbeafe;color:#1e40af;">📍</button>
                        </div>
                    </div>
                    ${s.location?`<div style="font-size:12px;color:#475569;margin-top:8px;">📍 ${this.escape(s.location)}</div>`:""}
                    ${s.manager_name?`<div style="font-size:12px;color:#475569;margin-top:4px;">👤 ${this.escape(s.manager_name)}</div>`:""}
                    <div style="display:flex;gap:12px;margin-top:12px;font-size:13px;">
                        <div><b style="color:#3b82f6;">${this.escape(String(s.product_count??0))}</b> قلم</div>
                        <div><b style="color:#10b981;">${this._fmt(s.total_value??0)}</b> ﷼</div>
                    </div>
                </div>`).join("")}
            </div>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(s=>s.addEventListener("click",async()=>{const a=await this.api.get("/inv/warehouses"),i=((a==null?void 0:a.data)??[]).find(n=>n.id==s.dataset.edit);i&&this._openModal(i)})),this.ref("wrap").querySelectorAll("[data-loc]").forEach(s=>s.addEventListener("click",()=>z.openModal({api:this.api,entityType:"warehouse",entityId:parseInt(s.dataset.loc),entityName:s.dataset.name})))}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_openModal(e=null){const t=!!e,s=Object.entries(Ks).map(([n,r])=>`<option value="${n}" ${(e==null?void 0:e.type)===n?"selected":""}>${r}</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
        <div class="acc-modal" style="max-width:420px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش انبار":"🏭 انبار جدید"}</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد *</label>
                        <input name="code" required value="${this.escape((e==null?void 0:e.code)??"")}">
                    </div>
                    <div class="acc-form-group"><label>نام *</label>
                        <input name="name" required value="${this.escape((e==null?void 0:e.name)??"")}">
                    </div>
                </div>
                <div class="acc-form-group"><label>نوع انبار</label>
                    <select name="type">${s}</select>
                </div>
                <div class="acc-form-group"><label>مکان / آدرس</label>
                    <input name="location" value="${this.escape((e==null?void 0:e.location)??"")}">
                </div>
                <div class="acc-form-group"><label>مسئول انبار</label>
                    <input name="manager_name" value="${this.escape((e==null?void 0:e.manager_name)??"")}">
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action=cancel]").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries()),o=n.target.querySelector("[type=submit]");o.disabled=!0;try{t?await this.api.put(`/inv/warehouses/${e.id}`,r):await this.api.post("/inv/warehouses",r),i(),this._toast("✅ انبار ذخیره شد"),this._load()}catch(l){alert("خطا: "+((l==null?void 0:l.message)??"")),o.disabled=!1}})}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}class Ur extends x{constructor(e){super(e),this._products=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📦 بچ / لات</h2>
                <div style="display:flex;gap:8px;align-items:center;">
                    <select data-ref="prodFilter" class="acc-input" style="width:200px;">
                        <option value="">همه محصولات</option>
                    </select>
                    <button class="acc-btn acc-btn--warning" data-ref="expiringBtn">⏰ در حال انقضا</button>
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ بچ جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._loadProducts(),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal()),this.on(this.ref("prodFilter"),"change",()=>this._load()),this.on(this.ref("expiringBtn"),"click",()=>this._loadExpiring())}async _loadProducts(){try{const e=await this.api.get("/inv/products");this._products=(e==null?void 0:e.data)??[];const t=this.ref("prodFilter");this._products.forEach(s=>{const a=document.createElement("option");a.value=s.id,a.textContent=s.name,t.appendChild(a)})}catch{}}async _load(){var s;const e=(s=this.ref("prodFilter"))==null?void 0:s.value,t=e?{product_id:e}:{};this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const a=await this.api.get("/inv/batches",t);this._renderTable((a==null?void 0:a.data)??[])}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}async _loadExpiring(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/inv/reports/expiring",{days:30}),t=(e==null?void 0:e.data)??[];if(!t.length){this.ref("wrap").innerHTML='<div class="acc-empty">✅ بچ منقضی‌شونده‌ای در ۳۰ روز آینده وجود ندارد</div>';return}this._renderTable(t,!0)}catch{}}_renderTable(e,t=!1){if(!e.length){this.ref("wrap").innerHTML='<div class="acc-empty">بچی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>شماره بچ</th><th>محصول</th><th>تاریخ تولید</th><th>تاریخ انقضا</th>
                ${t?"<th>روز باقیمانده</th>":""}
                <th>موجودی</th><th>بهای تمام شده</th><th>اقدام</th>
            </tr></thead>
            <tbody>
            ${e.map(s=>{const a=s.days_left!==void 0?parseInt(s.days_left):null;return`<tr ${a!==null&&a<=7?'style="background:#fef2f2;"':""}>
                    <td style="font-weight:600;">${this.escape(s.batch_no)}</td>
                    <td>${this.escape(s.product_name??"")}</td>
                    <td>${s.mfg_date??"—"}</td>
                    <td style="color:${a!==null&&a<=30?"#ef4444":"inherit"};">${s.exp_date??"—"}</td>
                    ${t?`<td style="color:${a<=7?"#ef4444":"#f59e0b"};font-weight:700;">${a} روز</td>`:""}
                    <td>${this._fmt(s.total_qty)} ${this.escape(s.unit??"")}</td>
                    <td>${s.cost_price>0?this._fmt(s.cost_price)+" ﷼":"—"}</td>
                    <td style="display:flex;gap:4px;">
                        <button class="acc-btn acc-btn--xs" data-edit="${s.id}">✏️</button>
                        <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${s.id}" ${parseFloat(s.total_qty)>0?"disabled":""}>🗑️</button>
                    </td>
                </tr>`}).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(s=>s.addEventListener("click",async()=>{await this.api.get("/inv/batches",{product_id:s.dataset.pid??0});const a=await this.api.get("/inv/batches"),i=((a==null?void 0:a.data)??[]).find(n=>n.id==s.dataset.edit);i&&this._openModal(i)})),this.ref("wrap").querySelectorAll("[data-del]").forEach(s=>s.addEventListener("click",async()=>{if(confirm("حذف این بچ؟"))try{await this.api.delete(`/inv/batches/${s.dataset.del}`),this._toast("✅ حذف شد"),this._load()}catch(a){alert("خطا: "+((a==null?void 0:a.message)??""))}}))}_openModal(e=null){const t=!!e,s=this._products.map(n=>`<option value="${n.id}" ${(e==null?void 0:e.product_id)==n.id?"selected":""}>${this.escape(n.name)}</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
        <div class="acc-modal" style="max-width:420px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش بچ":"📦 بچ جدید"}</div>
            <form>
                <div class="acc-form-group"><label>محصول *</label>
                    <select name="product_id" required><option value="">انتخاب...</option>${s}</select>
                </div>
                <div class="acc-form-group"><label>شماره بچ / لات *</label>
                    <input name="batch_no" required value="${this.escape((e==null?void 0:e.batch_no)??"")}">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تاریخ تولید</label>
                        <input name="mfg_date" type="date" value="${(e==null?void 0:e.mfg_date)??""}">
                    </div>
                    <div class="acc-form-group"><label>تاریخ انقضا</label>
                        <input name="exp_date" type="date" value="${(e==null?void 0:e.exp_date)??""}">
                    </div>
                </div>
                <div class="acc-form-group"><label>بهای تمام شده (ریال)</label>
                    <input name="cost_price" type="number" min="0" step="any" value="${(e==null?void 0:e.cost_price)??0}">
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <input name="notes" value="${this.escape((e==null?void 0:e.notes)??"")}">
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action=cancel]").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());r.mfg_date||(r.mfg_date=null),r.exp_date||(r.exp_date=null);const o=n.target.querySelector("[type=submit]");o.disabled=!0;try{t?await this.api.put(`/inv/batches/${e.id}`,r):await this.api.post("/inv/batches",r),i(),this._toast("✅ بچ ذخیره شد"),this._load()}catch(l){alert("خطا: "+((l==null?void 0:l.message)??"")),o.disabled=!1}})}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const Ne={in_stock:{label:"در انبار",color:"#10b981"},issued:{label:"صادر شده",color:"#3b82f6"},returned:{label:"مرجوع شده",color:"#8b5cf6"},scrapped:{label:"اسقاط",color:"#ef4444"},lost:{label:"مفقود",color:"#f59e0b"}};class Gr extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🔢 سریال نامبر</h2>
                <div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
                    <input type="text" data-ref="search" placeholder="جستجو سریال..."
                           class="acc-input" style="width:200px;">
                    <select data-ref="statusFilter" class="acc-input">
                        <option value="">همه وضعیت‌ها</option>
                        ${Object.entries(Ne).map(([e,t])=>`<option value="${e}">${t.label}</option>`).join("")}
                    </select>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("statusFilter"),"change",()=>this._load());let e;this.on(this.ref("search"),"input",()=>{clearTimeout(e),e=setTimeout(()=>this._load(),400)})}async _load(){var a,i,n;const e={},t=(a=this.ref("statusFilter"))==null?void 0:a.value,s=(n=(i=this.ref("search"))==null?void 0:i.value)==null?void 0:n.trim();t&&(e.status=t),s&&(e.search=s),this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const r=await this.api.get("/inv/serials",e);this._rows=(r==null?void 0:r.data)??[],this._renderTable(this._rows)}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_renderTable(e){if(!e.length){this.ref("wrap").innerHTML='<div class="acc-empty">سریالی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>سریال نامبر</th><th>محصول</th><th>وضعیت</th>
                <th>انبار</th><th>بچ</th><th>صادر به</th><th>اقدام</th>
            </tr></thead>
            <tbody>
            ${e.map(t=>{const s=Ne[t.status]??{label:t.status,color:"#64748b"};return`<tr>
                    <td style="font-weight:700;font-family:monospace;">${this.escape(t.serial_no)}</td>
                    <td>${this.escape(t.product_name??"")} <small style="color:#94a3b8;">${this.escape(t.product_code??"")}</small></td>
                    <td><span style="color:${s.color};font-weight:600;">${s.label}</span></td>
                    <td>${this.escape(t.warehouse_name??"—")}</td>
                    <td><small>${this.escape(t.batch_no??"—")}</small></td>
                    <td><small>${this.escape(t.issued_to??"—")}</small></td>
                    <td><button class="acc-btn acc-btn--xs" data-id="${t.id}" data-status="${t.status}">✏️</button></td>
                </tr>`}).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-id]").forEach(t=>t.addEventListener("click",()=>{const s=e.find(a=>a.id==t.dataset.id);s&&this._openEditModal(s)}))}_openEditModal(e){Ne[e.status]??e.status;const t=Object.entries(Ne).map(([i,n])=>`<option value="${i}" ${e.status===i?"selected":""}>${n.label}</option>`).join(""),s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
        <div class="acc-modal" style="max-width:380px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🔢 ویرایش سریال</div>
            <div style="background:#f8fafc;padding:10px;border-radius:8px;margin-bottom:12px;font-size:13px;">
                <b>${this.escape(e.serial_no)}</b><br>
                <small>${this.escape(e.product_name??"")}</small>
            </div>
            <form>
                <div class="acc-form-group"><label>وضعیت</label>
                    <select name="status">${t}</select>
                </div>
                <div class="acc-form-group"><label>صادر به</label>
                    <input name="issued_to" value="${this.escape(e.issued_to??"")}">
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <input name="notes" value="${this.escape(e.notes??"")}">
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action=cancel]").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries()),r=i.target.querySelector("[type=submit]");r.disabled=!0;try{await this.api.put(`/inv/serials/${e.id}`,n),a(),this._toast("✅ سریال به‌روز شد"),this._load()}catch(o){alert("خطا: "+((o==null?void 0:o.message)??"")),r.disabled=!1}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}class Kr extends x{constructor(e){super(e),this._products=[],this._warehouses=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📈 گزارش‌های انبار</h2>
            </div>

            <!-- انتخاب گزارش -->
            <div style="display:flex;gap:12px;margin-bottom:20px;flex-wrap:wrap;">
                <button class="acc-btn acc-btn--primary" data-report="card">📋 کاردکس محصول</button>
                <button class="acc-btn acc-btn--secondary" data-report="valuation">💰 ارزش‌گذاری انبار</button>
                <button class="acc-btn acc-btn--warning" data-report="low">⚠️ کم‌موجودی</button>
                <button class="acc-btn" data-report="expiring" style="background:#fef9c3;color:#854d0e;border:1px solid #fde68a;">⏰ در حال انقضا</button>
            </div>

            <!-- فیلترهای کاردکس -->
            <div data-ref="cardFilters" style="display:none;background:#f8fafc;padding:12px;border-radius:8px;margin-bottom:16px;display:none;">
                <div style="display:flex;gap:8px;align-items:end;flex-wrap:wrap;">
                    <div class="acc-form-group" style="margin:0;">
                        <label style="font-size:11px;">محصول *</label>
                        <select data-ref="cardProd" class="acc-input" style="width:200px;">
                            <option value="">انتخاب...</option>
                        </select>
                    </div>
                    <div class="acc-form-group" style="margin:0;">
                        <label style="font-size:11px;">انبار (اختیاری)</label>
                        <select data-ref="cardWh" class="acc-input">
                            <option value="">همه انبارها</option>
                        </select>
                    </div>
                    <button class="acc-btn acc-btn--primary" data-ref="cardRunBtn">📋 نمایش کاردکس</button>
                </div>
            </div>

            <div data-ref="reportWrap"></div>
        </div>`}async afterRender(){await Promise.all([this._loadProducts(),this._loadWarehouses()]),this.container.querySelectorAll("[data-report]").forEach(e=>e.addEventListener("click",()=>this._selectReport(e.dataset.report))),this.on(this.ref("cardRunBtn"),"click",()=>this._runCard())}async _loadProducts(){try{const e=await this.api.get("/inv/products");this._products=(e==null?void 0:e.data)??[];const t=this.ref("cardProd");this._products.forEach(s=>{const a=document.createElement("option");a.value=s.id,a.textContent=`${s.name} [${s.code}]`,t.appendChild(a)})}catch{}}async _loadWarehouses(){try{const e=await this.api.get("/inv/warehouses");this._warehouses=(e==null?void 0:e.data)??[];const t=this.ref("cardWh");this._warehouses.forEach(s=>{const a=document.createElement("option");a.value=s.id,a.textContent=s.name,t.appendChild(a)})}catch{}}_selectReport(e){const t=this.ref("cardFilters");t.style.display=e==="card"?"block":"none",this.ref("reportWrap").innerHTML="",e==="valuation"&&this._runValuation(),e==="low"&&this._runLow(),e==="expiring"&&this._runExpiring()}async _runCard(){var s,a;const e=(s=this.ref("cardProd"))==null?void 0:s.value,t=(a=this.ref("cardWh"))==null?void 0:a.value;if(!e){alert("محصول را انتخاب کنید");return}this.ref("reportWrap").innerHTML='<div class="acc-loading">⏳ بارگذاری کاردکس...</div>';try{const i={product_id:e};t&&(i.warehouse_id=t);const n=await this.api.get("/inv/reports/card",i),r=(n==null?void 0:n.data)??[],o=this._products.find(l=>l.id==e);if(!r.length){this.ref("reportWrap").innerHTML='<div class="acc-empty">تراکنشی یافت نشد</div>';return}this.ref("reportWrap").innerHTML=`
            <div style="margin-bottom:8px;font-weight:700;font-size:14px;">
                📋 کاردکس: ${this.escape((o==null?void 0:o.name)??"")}
                <small style="color:#94a3b8;">موجودی نهایی: ${this._fmt(n.final_balance)} ${this.escape((o==null?void 0:o.unit)??"")}</small>
            </div>
            <table class="acc-table" style="font-size:12px;">
                <thead><tr>
                    <th>شماره سند</th><th>نوع</th><th>تاریخ</th>
                    <th>از انبار</th><th>به انبار</th>
                    <th>ورودی</th><th>خروجی</th><th>مانده</th>
                    <th>قیمت واحد</th>
                </tr></thead>
                <tbody>
                ${r.map(l=>`<tr>
                    <td>${this.escape(l.voucher_no)}</td>
                    <td style="font-size:11px;">${this.escape(l.type)}</td>
                    <td>${l.date}</td>
                    <td style="font-size:11px;">${this.escape(l.from_wh??"—")}</td>
                    <td style="font-size:11px;">${this.escape(l.to_wh??"—")}</td>
                    <td style="color:#10b981;font-weight:${l.in_qty>0?"700":"400"};">${l.in_qty>0?this._fmt(l.in_qty):"—"}</td>
                    <td style="color:#ef4444;font-weight:${l.out_qty>0?"700":"400"};">${l.out_qty>0?this._fmt(l.out_qty):"—"}</td>
                    <td style="font-weight:700;color:#1d4ed8;">${this._fmt(l.balance)}</td>
                    <td>${l.unit_price>0?this._fmt(l.unit_price):"—"}</td>
                </tr>`).join("")}
                </tbody>
            </table>`}catch{this.ref("reportWrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}async _runValuation(){this.ref("reportWrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/inv/reports/valuation"),t=(e==null?void 0:e.data)??[],s=(e==null?void 0:e.total_value)??0;if(!t.length){this.ref("reportWrap").innerHTML='<div class="acc-empty">موجودی‌ای یافت نشد</div>';return}this.ref("reportWrap").innerHTML=`
            <div style="background:#f0fdf4;padding:10px 16px;border-radius:8px;margin-bottom:12px;font-size:14px;">
                💰 ارزش کل انبار: <b style="color:#166534;font-size:16px;">${this._fmt(s)} ﷼</b>
            </div>
            <table class="acc-table">
                <thead><tr><th>محصول</th><th>انبار</th><th>موجودی</th><th>بهای میانگین</th><th>ارزش</th><th>روش</th></tr></thead>
                <tbody>
                ${t.map(a=>`<tr>
                    <td>${this.escape(a.name)}</td>
                    <td>${this.escape(a.warehouse_name)}</td>
                    <td>${this._fmt(a.qty)} ${this.escape(a.unit)}</td>
                    <td>${this._fmt(a.avg_cost)}</td>
                    <td style="font-weight:700;color:#166534;">${this._fmt(a.value)} ﷼</td>
                    <td><small>${a.costing_method==="fifo"?"FIFO":"میانگین"}</small></td>
                </tr>`).join("")}
                </tbody>
            </table>`}catch{this.ref("reportWrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}async _runLow(){this.ref("reportWrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/inv/stock/low"),t=(e==null?void 0:e.data)??[];if(!t.length){this.ref("reportWrap").innerHTML='<div class="acc-empty">✅ همه محصولات موجودی کافی دارند</div>';return}this.ref("reportWrap").innerHTML=`
            <div style="background:#fef2f2;padding:10px 16px;border-radius:8px;margin-bottom:12px;color:#991b1b;">
                ⚠️ <b>${t.length}</b> محصول زیر حداقل موجودی
            </div>
            <table class="acc-table">
                <thead><tr><th>کد</th><th>نام</th><th>موجودی فعلی</th><th>حداقل</th><th>سفارش پیشنهادی</th></tr></thead>
                <tbody>
                ${t.map(s=>`<tr style="background:#fef2f2;">
                    <td>${this.escape(s.code)}</td>
                    <td>${this.escape(s.name)}</td>
                    <td style="color:#ef4444;font-weight:700;">${this._fmt(s.total_qty)} ${this.escape(s.unit)}</td>
                    <td>${this._fmt(s.min_stock)}</td>
                    <td style="color:#166534;font-weight:700;">${this._fmt(s.reorder_qty||s.min_stock-s.total_qty)}</td>
                </tr>`).join("")}
                </tbody>
            </table>`}catch{this.ref("reportWrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}async _runExpiring(){this.ref("reportWrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/inv/reports/expiring",{days:30}),t=(e==null?void 0:e.data)??[];if(!t.length){this.ref("reportWrap").innerHTML='<div class="acc-empty">✅ بچ منقضی‌شونده‌ای در ۳۰ روز آینده وجود ندارد</div>';return}this.ref("reportWrap").innerHTML=`
            <table class="acc-table">
                <thead><tr><th>بچ</th><th>محصول</th><th>تاریخ انقضا</th><th>روز باقیمانده</th><th>موجودی</th></tr></thead>
                <tbody>
                ${t.map(s=>{const a=parseInt(s.days_left);return`<tr style="background:${a<=7?"#fef2f2":"#fefce8"};">
                        <td>${this.escape(s.batch_no)}</td>
                        <td>${this.escape(s.product_name)}</td>
                        <td style="color:${a<=7?"#ef4444":"#ca8a04"};font-weight:700;">${s.exp_date}</td>
                        <td style="color:${a<=7?"#ef4444":"#ca8a04"};font-weight:700;">${a} روز</td>
                        <td>${this._fmt(s.total_qty)} ${this.escape(s.unit)}</td>
                    </tr>`}).join("")}
                </tbody>
            </table>`}catch{this.ref("reportWrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const Lt=[{key:"stock",icon:"📊",title:"موجودی انبار",desc:"وضعیت فعلی",Class:Dr},{key:"vouchers",icon:"📄",title:"اسناد حرکت",desc:"ورود و خروج",Class:Pr},{key:"products",icon:"🗂️",title:"محصولات",desc:"کالاها و دسته‌ها",Class:Vr},{key:"warehouses",icon:"🏭",title:"انبارها",desc:"مکان‌های نگهداری",Class:Wr},{key:"batches",icon:"📦",title:"بچ / لات",desc:"دسته‌های تولیدی",Class:Ur},{key:"serials",icon:"🔢",title:"سریال نامبر",desc:"ردیابی تک‌واحدی",Class:Gr},{key:"reports",icon:"📈",title:"گزارش‌ها",desc:"کاردکس و ارزش‌گذاری",Class:Kr}];class Js extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="stock",this._sections={}}async template(){const t=Lt.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
                <div class="sp-nav-card__desc">${a.desc}</div>
            </div>
        `).join(""),s=Lt.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=Lt.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(Js,"title","انبار"),E.register("inventory",Js);class Jr extends x{constructor(e){super(e),this._users=[],this._selectedId=null,this._profile=null,this._menus=[],this._roles=[],this._registry={},this._profiles=[],this._scopeCache={},this._state={menu_keys:[],role_ids:[],scopes:{}}}async template(){return`
        <div class="acc-section-wrap acl-user-profile">
            <div class="acc-toolbar" style="flex-wrap:wrap;gap:10px;">
                <h2 class="acc-section-title">👤 پروفایل دسترسی کاربر</h2>
                <div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin-right:auto;">
                    <select data-ref="userSelect" class="acc-input" style="min-width:240px;">
                        <option value="">— انتخاب کاربر —</option>
                    </select>
                    <select data-ref="profileSelect" class="acc-input" style="min-width:200px;">
                        <option value="">📋 پروفایل آماده...</option>
                    </select>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>

            <div data-ref="empty" class="acc-empty" style="padding:40px;">
                یک کاربر را انتخاب کنید تا منو، نقش و محدوده دسترسی را تنظیم کنید.
            </div>

            <div data-ref="editor" style="display:none;">
                <div data-ref="warnings" style="display:none;margin-bottom:12px;"></div>

                <div class="acl-profile-card">
                    <h3>۱. منوهای قابل مشاهده</h3>
                    <p class="acl-profile-hint">کاربر فقط این منوها را در sidebar می‌بیند.</p>
                    <div data-ref="menuGrid" class="acl-check-grid"></div>
                </div>

                <div class="acl-profile-card">
                    <h3>۲. نقش‌ها (عملیات مجاز)</h3>
                    <p class="acl-profile-hint">نقش تعیین می‌کند کاربر چه کارهایی انجام دهد (ثبت، ویرایش، حذف).</p>
                    <div data-ref="roleGrid" class="acl-check-grid"></div>
                    <div data-ref="roleSuggest" class="acl-profile-suggest"></div>
                </div>

                <div class="acl-profile-card">
                    <h3>۳. محدوده دسترسی (Scope)</h3>
                    <p class="acl-profile-hint">برای ماژول‌های انتخاب‌شده، مشخص کنید روی کدام انبار/پروژه/منطقه کار کند. خالی = سراسری.</p>
                    <div data-ref="scopeArea"></div>
                </div>

                <div style="display:flex;gap:10px;justify-content:flex-end;margin-top:16px;">
                    <button class="acc-btn acc-btn--primary" data-ref="saveBtn">💾 ذخیره دسترسی‌ها</button>
                </div>
            </div>
        </div>
        <style>
            .acl-user-profile .acl-profile-card {
                background:#fff;border:1px solid #e2e8f0;border-radius:12px;
                padding:16px 18px;margin-bottom:14px;
            }
            .acl-user-profile .acl-profile-card h3 { margin:0 0 6px;font-size:15px; }
            .acl-user-profile .acl-profile-hint { margin:0 0 12px;color:#64748b;font-size:12px; }
            .acl-user-profile .acl-check-grid {
                display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:8px;
            }
            .acl-user-profile .acl-check-item {
                display:flex;align-items:center;gap:8px;padding:8px 10px;
                border:1px solid #e2e8f0;border-radius:8px;cursor:pointer;font-size:13px;
            }
            .acl-user-profile .acl-check-item:hover { background:#f8fafc; }
            .acl-user-profile .acl-check-item input { accent-color:#4f46e5; }
            .acl-user-profile .acl-scope-block {
                border:1px dashed #cbd5e1;border-radius:10px;padding:12px;margin-bottom:10px;
            }
            .acl-user-profile .acl-scope-block h4 { margin:0 0 8px;font-size:13px; }
            .acl-user-profile .acl-warn-box {
                background:#fef9c3;border:1px solid #fde047;color:#854d0e;
                padding:10px 14px;border-radius:8px;font-size:13px;
            }
            .acl-user-profile .acl-profile-suggest {
                margin-top:8px;font-size:12px;color:#6366f1;
            }
        </style>`}async afterRender(){await this._loadUsers(),await this._loadRegistry(),this.on(this.ref("refreshBtn"),"click",()=>this._reload()),this.on(this.ref("userSelect"),"change",()=>this._onUserChange()),this.on(this.ref("profileSelect"),"change",()=>this._applyProfile()),this.on(this.ref("saveBtn"),"click",()=>this._save())}async _loadUsers(){try{const e=await this.api.get("/acl/users");this._users=(e==null?void 0:e.data)??[];const t=this.ref("userSelect");t.innerHTML='<option value="">— انتخاب کاربر —</option>'+this._users.map(s=>`<option value="${s.user_id}">${this.escape(s.display_name||s.user_login)} (${this.escape(s.user_login)})</option>`).join("")}catch{this.ref("userSelect").innerHTML='<option value="">خطا در بارگذاری کاربران</option>'}}async _loadRegistry(){try{const e=await this.api.get("/acl/module-registry");this._registry=(e==null?void 0:e.data)??{},this._profiles=(e==null?void 0:e.profiles)??[];const t=this.ref("profileSelect");t.innerHTML='<option value="">📋 پروفایل آماده...</option>'+this._profiles.map(s=>`<option value="${s.key}">${this.escape(s.label)}</option>`).join("")}catch{}}async _onUserChange(){const e=parseInt(this.ref("userSelect").value,10);if(this._selectedId=e||null,!this._selectedId){this.ref("empty").style.display="",this.ref("editor").style.display="none";return}await this._loadProfile()}async _reload(){await this._loadUsers(),this._selectedId&&await this._loadProfile()}async _loadProfile(){var e,t,s,a;this.ref("empty").style.display="none",this.ref("editor").style.display="",(e=this.ref("editor").querySelector(".acc-loading"))==null||e.remove();try{const i=await this.api.get(`/acl/users/${this._selectedId}/profile`);this._profile=(i==null?void 0:i.profile)??null,this._menus=(i==null?void 0:i.menus)??[],this._roles=(i==null?void 0:i.roles)??[],this._state={menu_keys:[...((t=this._profile)==null?void 0:t.menu_keys)??[]],role_ids:[...((s=this._profile)==null?void 0:s.role_ids)??[]],scopes:{...((a=this._profile)==null?void 0:a.scopes)??{}}},this._renderAll((i==null?void 0:i.suggested_roles)??[])}catch(i){this.ref("editor").innerHTML=`<div class="acc-error">❌ ${this.escape((i==null?void 0:i.message)??"خطا")}</div>`}}_renderAll(e=[]){this._renderMenus(),this._renderRoles(e),this._renderScopes(),this._validateUi()}_renderMenus(){const e=this.ref("menuGrid"),t=["access","users"];e.innerHTML=this._menus.filter(s=>!t.includes(s.menu_key)).map(s=>{const a=this._state.menu_keys.includes(s.menu_key)?"checked":"";return`<label class="acl-check-item">
                    <input type="checkbox" data-menu="${s.menu_key}" ${a}>
                    <span>${this.escape(s.icon||"")} ${this.escape(s.title)}</span>
                </label>`}).join(""),e.querySelectorAll("input[data-menu]").forEach(s=>{s.addEventListener("change",async()=>{const a=s.dataset.menu;s.checked?this._state.menu_keys.includes(a)||this._state.menu_keys.push(a):this._state.menu_keys=this._state.menu_keys.filter(i=>i!==a),await this._refreshScopeAndSuggest(),this._validateUi()})})}_renderRoles(e=[]){var n,r,o;const t=this.ref("roleGrid"),s=typeof window<"u"&&((r=(n=window.acl)==null?void 0:n.isSuperAdmin)==null?void 0:r.call(n)),a=this._roles.filter(l=>l.slug!=="super_admin"||s);t.innerHTML=a.map(l=>{const c=this._state.role_ids.includes(+l.id)?"checked":"";return`<label class="acl-check-item" ${l.slug==="super_admin"?'style="border-color:#f59e0b;background:#fffbeb;"':""}>
                <input type="checkbox" data-role="${l.id}" ${c}>
                <span><b>${this.escape(l.name)}</b><br><small style="color:#94a3b8;">${this.escape(l.slug)}</small></span>
            </label>`}).join(""),t.querySelectorAll("input[data-role]").forEach(l=>{l.addEventListener("change",()=>{const c=+l.dataset.role;l.checked?this._state.role_ids.includes(c)||this._state.role_ids.push(c):this._state.role_ids=this._state.role_ids.filter(d=>d!==c),this._validateUi()})});const i=this.ref("roleSuggest");if(e.length){const l=e.map(c=>c.name).join("، ");i.innerHTML=`💡 پیشنهاد برای منوهای انتخاب‌شده: <b>${this.escape(l)}</b>
                <button type="button" class="acc-btn acc-btn--xs acc-btn--secondary" data-ref="applySuggest" style="margin-right:8px;">اعمال پیشنهاد</button>`,(o=i.querySelector("[data-ref=applySuggest]"))==null||o.addEventListener("click",()=>{e.forEach(c=>{const d=+c.id;this._state.role_ids.includes(d)||this._state.role_ids.push(d)}),this._renderRoles(e),this._validateUi()})}else i.innerHTML=""}async _refreshScopeAndSuggest(){try{const e=await this.api.get(`/acl/users/${this._selectedId}/profile`);this._renderRoles((e==null?void 0:e.suggested_roles)??[])}catch{}await this._renderScopes()}async _renderScopes(){const e=this.ref("scopeArea"),t=this._getScopeTypesForMenus();if(!t.length){e.innerHTML='<div style="color:#94a3b8;font-size:13px;">برای منوهای انتخاب‌شده محدوده‌ای تعریف نشده (سراسری).</div>';return}e.innerHTML='<div class="acc-loading">⏳ بارگذاری محدوده‌ها...</div>';const s=[];for(const a of t){const i=await this._loadScopeOptions(a.scope_type),n=new Set(this._state.scopes[a.scope_type]??[]);s.push(`
                <div class="acl-scope-block" data-scope-type="${a.scope_type}">
                    <h4>${this.escape(a.scope_label||a.scope_type)}</h4>
                    <div class="acl-check-grid">
                        ${i.length?i.map(r=>`
                            <label class="acl-check-item">
                                <input type="checkbox" data-scope-type="${a.scope_type}" data-scope-id="${r.id}"
                                    ${n.has(+r.id)?"checked":""}>
                                <span>${this.escape(r.label||r.name||r.title||"#"+r.id)}</span>
                            </label>
                        `).join(""):'<div style="color:#94a3b8;font-size:12px;">موردی یافت نشد — خالی = سراسری</div>'}
                    </div>
                </div>
            `)}e.innerHTML=s.join(""),e.querySelectorAll("input[data-scope-type]").forEach(a=>{a.addEventListener("change",()=>{const i=a.dataset.scopeType,n=+a.dataset.scopeId;this._state.scopes[i]||(this._state.scopes[i]=[]),a.checked?this._state.scopes[i].includes(n)||this._state.scopes[i].push(n):this._state.scopes[i]=this._state.scopes[i].filter(r=>r!==n)})})}_getScopeTypesForMenus(){const e=new Set,t=[];for(const s of this._state.menu_keys)for(const a of Object.values(this._registry))a.menu_key===s&&a.scope_type&&!e.has(a.scope_type)&&(e.add(a.scope_type),t.push({scope_type:a.scope_type,scope_label:a.scope_label,scope_api:a.scope_api}));return t}async _loadScopeOptions(e){if(this._scopeCache[e])return this._scopeCache[e];try{const t=await this.api.get(`/acl/scope-options/${e}`);this._scopeCache[e]=(t==null?void 0:t.data)??[]}catch{this._scopeCache[e]=[]}return this._scopeCache[e]}_validateUi(){const e=this.ref("warnings"),t=[];this._state.menu_keys.length||t.push("حداقل یک منو انتخاب کنید."),this._state.role_ids.length||t.push("حداقل یک نقش انتخاب کنید.");for(const a of this._state.menu_keys)for(const i of Object.values(this._registry)){if(i.menu_key!==a||!i.view_perm)continue;this._getSelectedRolePerms().has(i.view_perm)||t.push(`منوی «${i.label}» نیاز به مجوز ${i.view_perm} دارد که در نقش‌های انتخاب‌شده نیست.`)}const s=this._roles.find(a=>a.slug==="super_admin");s&&this._state.role_ids.includes(+s.id)&&t.push("نقش «مدیر کل سیستم» دسترسی سراسری دارد — محدوده انبار/پروژه روی این نقش اعمال نمی‌شود. برای محدودیت واقعی، super_admin را بردارید و نقش‌های عملیاتی (مثل انباردار/فروش) بدهید."),t.length?(e.style.display="",e.className="acl-warn-box",e.innerHTML="⚠️ "+t.map(a=>`<div>${this.escape(a)}</div>`).join("")):(e.style.display="none",e.innerHTML="")}_getSelectedRolePerms(){const e=new Set;for(const t of this._roles)this._state.role_ids.includes(+t.id)&&t.permissions&&t.permissions.forEach(s=>e.add(s));return e}async _applyProfile(){const e=this.ref("profileSelect").value;if(!e)return;const t=this._profiles.find(a=>a.key===e);if(!t)return;this._state.menu_keys=[...t.menu_keys??[]],this._state.scopes=JSON.parse(JSON.stringify(t.scopes??{}));const s=t.role_slugs??[];this._state.role_ids=this._roles.filter(a=>s.includes(a.slug)).map(a=>+a.id),this._renderAll(),this.ref("profileSelect").value=""}async _save(){if(!this._selectedId)return;const e=this.ref("saveBtn");e.disabled=!0,e.textContent="⏳ در حال ذخیره...";try{const t=await this.api.put(`/acl/users/${this._selectedId}/profile`,{menu_keys:this._state.menu_keys,role_ids:this._state.role_ids,scopes:this._state.scopes});e.disabled=!1,e.textContent="💾 ذخیره دسترسی‌ها";const s=[...(t==null?void 0:t.warnings)??[]];if((t==null?void 0:t.menus_saved)===!1&&s.push("جدول منوها در دیتابیس نیست — run-acl-migrate.php را اجرا کنید."),s.length){const a=this.ref("warnings");a.style.display="",a.className="acl-warn-box",a.innerHTML="⚠️ ذخیره شد با هشدار:<br>"+s.map(i=>`<div>${this.escape(i)}</div>`).join("")}else{const a=this.ref("warnings");a.style.display="",a.className="acl-warn-box",a.style.background="#dcfce7",a.style.borderColor="#86efac",a.style.color="#166534",a.innerHTML="✅ دسترسی‌ها با موفقیت ذخیره شد",setTimeout(()=>{a.style.display="none"},4e3)}await this._loadProfile()}catch(t){e.disabled=!1,e.textContent="💾 ذخیره دسترسی‌ها";const s=(t==null?void 0:t.message)??"خطا در ذخیره";if(s.includes("هم‌خوان")||s.includes("منو")){if(confirm(s+`

با وجود هشدار ذخیره شود؟`))try{await this.api.put(`/acl/users/${this._selectedId}/profile`,{menu_keys:this._state.menu_keys,role_ids:this._state.role_ids,scopes:this._state.scopes,force:!0}),await this._loadProfile()}catch(a){alert("❌ "+((a==null?void 0:a.message)??""))}}else alert("❌ "+s)}}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}class Yr extends x{constructor(e){super(e),this._roles=[],this._users=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">👥 کاربران و نقش‌ها</h2>
                <div style="display:flex;gap:8px;">
                    <input type="text" data-ref="search" placeholder="جستجو کاربر..."
                           class="acc-input" style="width:220px;">
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._loadRoles(),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("search"),"input",()=>this._filter())}async _loadRoles(){try{const e=await this.api.get("/acl/roles");this._roles=(e==null?void 0:e.data)??[]}catch{}}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/acl/users");this._users=(e==null?void 0:e.data)??[],this._renderTable(this._users)}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_filter(){var t;const e=(((t=this.ref("search"))==null?void 0:t.value)??"").toLowerCase();if(!e){this._renderTable(this._users);return}this._renderTable(this._users.filter(s=>(s.display_name??"").toLowerCase().includes(e)||(s.user_login??"").toLowerCase().includes(e)||(s.user_email??"").toLowerCase().includes(e)))}_renderTable(e){if(!e.length){this.ref("wrap").innerHTML='<div class="acc-empty">کاربری یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>کاربر</th><th>ایمیل</th><th>نقش‌ها</th><th>تعداد</th><th>اقدام</th>
            </tr></thead>
            <tbody>
            ${e.map(t=>`<tr>
                <td>
                    <div style="font-weight:700;">${this.escape(t.display_name??t.user_login)}</div>
                    <small style="color:#94a3b8;">${this.escape(t.user_login)}</small>
                </td>
                <td><small>${this.escape(t.user_email??"—")}</small></td>
                <td style="max-width:300px;">
                    ${t.roles_list?`<small style="color:#475569;">${this.escape(t.roles_list)}</small>`:'<span style="color:#cbd5e1;font-size:11px;">— بدون نقش —</span>'}
                </td>
                <td style="text-align:center;">
                    <span style="background:${t.role_count>0?"#d1fae5":"#fee2e2"};
                                 color:${t.role_count>0?"#065f46":"#991b1b"};
                                 padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">
                        ${t.role_count}
                    </span>
                </td>
                <td>
                    <button class="acc-btn acc-btn--xs acc-btn--primary" data-uid="${t.user_id}">⚙️ مدیریت نقش‌ها</button>
                </td>
            </tr>`).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-uid]").forEach(t=>t.addEventListener("click",()=>this._openRolesModal(parseInt(t.dataset.uid),e.find(s=>s.user_id==t.dataset.uid))))}async _openRolesModal(e,t){let s=[];try{const o=await this.api.get(`/acl/users/${e}/roles`);s=(o==null?void 0:o.data)??[]}catch{}const a=this._roles.map(o=>`<option value="${o.id}">${this.escape(o.name)}</option>`).join(""),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
        <div class="acc-modal" style="max-width:560px;max-height:90vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">⚙️ نقش‌های ${this.escape((t==null?void 0:t.display_name)??"")}</div>

            <!-- نقش‌های فعلی -->
            <div style="margin-bottom:14px;">
                <b style="font-size:13px;">نقش‌های فعلی:</b>
                <div data-ref-inner="assignments" id="acl-assignments-list" style="margin-top:6px;"></div>
            </div>

            <!-- افزودن نقش جدید -->
            <div style="background:#f8fafc;padding:12px;border-radius:8px;">
                <b style="font-size:13px;">➕ افزودن نقش جدید:</b>
                <form id="acl-assign-form" style="display:grid;grid-template-columns:1fr 1fr 1fr auto;gap:6px;margin-top:8px;align-items:end;">
                    <div>
                        <label style="font-size:11px;">نقش *</label>
                        <select name="role_id" required class="acc-input"><option value="">انتخاب...</option>${a}</select>
                    </div>
                    <div>
                        <label style="font-size:11px;">نوع scope</label>
                        <select name="scope_type" class="acc-input">
                            <option value="global">سراسری</option>
                            <option value="project">پروژه</option>
                            <option value="warehouse">انبار</option>
                            <option value="district">منطقه GIS</option>
                        </select>
                    </div>
                    <div>
                        <label style="font-size:11px;">ID شیء</label>
                        <input name="scope_id" type="number" class="acc-input" placeholder="(اختیاری)">
                    </div>
                    <button type="submit" class="acc-btn acc-btn--primary acc-btn--sm">➕</button>
                </form>
            </div>

            <div class="acc-modal__actions" style="margin-top:14px;">
                <button type="button" class="acc-btn acc-btn--secondary" data-action="close">بستن</button>
            </div>
        </div>`,document.body.appendChild(i);const n=()=>{i.remove(),this._load()};i.querySelector(".acc-modal__close").addEventListener("click",n),i.querySelector("[data-action=close]").addEventListener("click",n),i.addEventListener("click",o=>{o.target===i&&n()});const r=()=>{const o=i.querySelector("#acl-assignments-list");if(!s.length){o.innerHTML='<div style="color:#94a3b8;font-size:12px;padding:8px;">— نقشی اختصاص داده نشده —</div>';return}o.innerHTML=s.map(l=>`
                <div style="display:flex;justify-content:space-between;align-items:center;padding:6px 10px;background:#fff;border:1px solid #e2e8f0;border-radius:6px;margin-bottom:4px;">
                    <div>
                        <b style="font-size:13px;">${this.escape(l.role_name)}</b>
                        <small style="color:#64748b;margin-right:8px;">
                            ${l.scope_type==="global"?"🌐 سراسری":`${this.escape(l.scope_type)}: ${l.scope_id??"—"}`}
                        </small>
                    </div>
                    <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${l.assignment_id}">🗑️</button>
                </div>
            `).join(""),o.querySelectorAll("[data-del]").forEach(l=>l.addEventListener("click",async()=>{if(confirm("حذف این نقش از کاربر؟"))try{await this.api.delete(`/acl/users/${e}/roles/${l.dataset.del}`),s=s.filter(c=>c.assignment_id!=l.dataset.del),r()}catch(c){alert("خطا: "+((c==null?void 0:c.message)??""))}}))};r(),i.querySelector("#acl-assign-form").addEventListener("submit",async o=>{o.preventDefault();const l=Object.fromEntries(new FormData(o.target).entries());l.scope_id||delete l.scope_id;try{await this.api.post(`/acl/users/${e}/roles`,l);const c=await this.api.get(`/acl/users/${e}/roles`);s=(c==null?void 0:c.data)??[],r(),o.target.reset()}catch(c){alert("خطا: "+((c==null?void 0:c.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}class Qr extends x{constructor(e){super(e),this._perms=[],this._permsGrouped={}}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🎭 نقش‌ها</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ نقش جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._loadPerms(),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal())}async _loadPerms(){try{const e=await this.api.get("/acl/permissions");this._perms=(e==null?void 0:e.data)??[],this._permsGrouped=(e==null?void 0:e.grouped)??{}}catch{}}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/acl/roles");this._rows=(e==null?void 0:e.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">نقشی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:14px;padding:4px;">
            ${this._rows.map(e=>`
            <div style="border:1px solid #e2e8f0;border-radius:10px;padding:14px;background:#fff;">
                <div style="display:flex;justify-content:space-between;align-items:start;">
                    <div>
                        <div style="font-weight:700;font-size:14px;">🎭 ${this.escape(e.name)}</div>
                        <small style="color:#94a3b8;font-family:monospace;">${this.escape(e.slug)}</small>
                        ${e.is_system==1?'<span style="background:#dbeafe;color:#1e40af;padding:1px 6px;border-radius:4px;font-size:10px;margin-right:6px;">سیستمی</span>':""}
                    </div>
                </div>
                ${e.description?`<div style="font-size:12px;color:#475569;margin-top:6px;">${this.escape(e.description)}</div>`:""}
                <div style="display:flex;gap:8px;margin-top:10px;font-size:12px;">
                    <span><b>${e.perm_count}</b> مجوز</span>
                    <span><b>${e.user_count}</b> کاربر</span>
                </div>
                <div style="display:flex;gap:6px;margin-top:10px;">
                    <button class="acc-btn acc-btn--xs acc-btn--primary" data-perms="${e.id}">🔑 ویرایش مجوزها</button>
                    ${e.is_system!=1?`
                    <button class="acc-btn acc-btn--xs" data-edit="${e.id}">✏️</button>
                    <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${e.id}">🗑️</button>
                    `:""}
                </div>
            </div>`).join("")}
        </div>`,this.ref("wrap").querySelectorAll("[data-perms]").forEach(e=>e.addEventListener("click",()=>this._openPermsModal(parseInt(e.dataset.perms),this._rows.find(t=>t.id==e.dataset.perms)))),this.ref("wrap").querySelectorAll("[data-edit]").forEach(e=>e.addEventListener("click",()=>this._openModal(this._rows.find(t=>t.id==e.dataset.edit)))),this.ref("wrap").querySelectorAll("[data-del]").forEach(e=>e.addEventListener("click",async()=>{if(confirm("حذف این نقش؟"))try{await this.api.delete(`/acl/roles/${e.dataset.del}`),this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}))}_openModal(e=null){const t=!!e,s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
        <div class="acc-modal" style="max-width:420px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش":"➕ نقش جدید"}</div>
            <form>
                ${t?"":`<div class="acc-form-group"><label>شناسه یکتا (slug) *</label>
                    <input name="slug" required placeholder="مثلاً sales_manager">
                </div>`}
                <div class="acc-form-group"><label>نام نمایشی *</label>
                    <input name="name" required value="${this.escape((e==null?void 0:e.name)??"")}">
                </div>
                <div class="acc-form-group"><label>توضیحات</label>
                    <textarea name="description" rows="2">${this.escape((e==null?void 0:e.description)??"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action=cancel]").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries());try{t?await this.api.put(`/acl/roles/${e.id}`,n):await this.api.post("/acl/roles",n),a(),this._load()}catch(r){alert("خطا: "+((r==null?void 0:r.message)??""))}})}async _openPermsModal(e,t){let s=[];try{const o=await this.api.get(`/acl/roles/${e}/permissions`);s=(o==null?void 0:o.data)??[]}catch{}const a=Object.entries(this._permsGrouped),i={gis:"GIS",inv:"انبار",sales:"فروش",purchase:"خرید",cpm:"پروژه",acc:"حسابداری",payroll:"حقوق",treasury:"خزانه",crm:"CRM",system:"سیستم"},n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
        <div class="acc-modal" style="max-width:700px;max-height:90vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🔑 مجوزهای نقش «${this.escape((t==null?void 0:t.name)??"")}»</div>

            <div style="display:flex;gap:6px;margin-bottom:12px;">
                <button class="acc-btn acc-btn--xs" id="acl-select-all">انتخاب همه</button>
                <button class="acc-btn acc-btn--xs" id="acl-deselect-all">حذف همه</button>
            </div>

            <form id="acl-perms-form">
                ${a.map(([o,l])=>`
                <div style="margin-bottom:16px;padding:10px;background:#f8fafc;border-radius:8px;">
                    <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;">
                        <b style="font-size:13px;color:#1e40af;">📦 ${this.escape(i[o]??o)}</b>
                        <button type="button" class="acc-btn acc-btn--xs" data-group="${o}">✅ همه</button>
                    </div>
                    <div style="display:grid;grid-template-columns:1fr 1fr;gap:4px;">
                        ${l.map(c=>`
                        <label style="display:flex;gap:6px;align-items:center;font-size:12px;padding:4px;cursor:pointer;">
                            <input type="checkbox" name="permissions" value="${this.escape(c.permission_key)}"
                                   ${s.includes(c.permission_key)?"checked":""}>
                            ${this.escape(c.label)} <small style="color:#94a3b8;font-family:monospace;">${this.escape(c.permission_key)}</small>
                        </label>`).join("")}
                    </div>
                </div>
                `).join("")}

                <div class="acc-modal__actions" style="position:sticky;bottom:0;background:#fff;padding:10px 0;">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">💾 ذخیره مجوزها</button>
                </div>
            </form>
        </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector("[data-action=cancel]").addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()}),n.querySelector("#acl-select-all").addEventListener("click",()=>n.querySelectorAll("input[type=checkbox]").forEach(o=>o.checked=!0)),n.querySelector("#acl-deselect-all").addEventListener("click",()=>n.querySelectorAll("input[type=checkbox]").forEach(o=>o.checked=!1)),n.querySelectorAll("[data-group]").forEach(o=>o.addEventListener("click",()=>{o.dataset.group;const l=o.closest("[style*='background:#f8fafc']").querySelectorAll("input[type=checkbox]"),c=[...l].every(d=>d.checked);l.forEach(d=>d.checked=!c)})),n.querySelector("#acl-perms-form").addEventListener("submit",async o=>{o.preventDefault();const l=[...o.target.querySelectorAll("input[name=permissions]:checked")].map(c=>c.value);try{await this.api.put(`/acl/roles/${e}/permissions`,{permissions:l}),r(),this._toast(`✅ ${l.length} مجوز ذخیره شد`),this._load()}catch(c){alert("خطا: "+((c==null?void 0:c.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const Zr={gis:"🗺️ GIS",inv:"🏭 انبار",sales:"🧾 فروش",purchase:"🛒 خرید",cpm:"📊 پروژه",acc:"📦 حسابداری",payroll:"👨‍💼 حقوق",treasury:"💰 خزانه",crm:"🎯 CRM",system:"⚙️ سیستم"};class Xr extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🔑 مجوزها</h2>
                <div style="display:flex;gap:8px;">
                    <input type="text" data-ref="search" placeholder="جستجو..." class="acc-input" style="width:220px;">
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div style="background:#eff6ff;padding:10px 14px;border-radius:8px;margin-bottom:12px;font-size:12px;color:#1e40af;">
                💡 مجوزها به‌صورت خودکار از ماژول‌ها ساخته می‌شوند. الگو: <code>ماژول.منبع.عمل</code>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("search"),"input",()=>this._filter())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/acl/permissions");this._rows=(e==null?void 0:e.data)??[],this._grouped=(e==null?void 0:e.grouped)??{},this._render(this._grouped)}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_filter(){var s;const e=(((s=this.ref("search"))==null?void 0:s.value)??"").toLowerCase();if(!e){this._render(this._grouped);return}const t={};for(const[a,i]of Object.entries(this._grouped)){const n=i.filter(r=>r.permission_key.toLowerCase().includes(e)||(r.label??"").toLowerCase().includes(e));n.length&&(t[a]=n)}this._render(t)}_render(e){const t=Object.entries(e);if(!t.length){this.ref("wrap").innerHTML='<div class="acc-empty">مجوزی یافت نشد</div>';return}this.ref("wrap").innerHTML=t.map(([s,a])=>`
        <div style="margin-bottom:16px;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;">
            <div style="background:#f1f5f9;padding:10px 14px;font-weight:700;font-size:13px;">
                ${this.escape(Zr[s]??s)}
                <small style="color:#94a3b8;font-weight:400;">(${a.length} مجوز)</small>
            </div>
            <table class="acc-table" style="margin:0;">
                <thead><tr><th>کلید</th><th>توضیح</th><th>عمل</th></tr></thead>
                <tbody>
                ${a.map(i=>`<tr>
                    <td style="font-family:monospace;font-size:12px;color:#1d4ed8;">${this.escape(i.permission_key)}</td>
                    <td>${this.escape(i.label??"—")}</td>
                    <td><small style="background:#f1f5f9;padding:2px 6px;border-radius:4px;">${this.escape(i.action)}</small></td>
                </tr>`).join("")}
                </tbody>
            </table>
        </div>
        `).join("")}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}class eo extends x{constructor(e){super(e),this._perms=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📋 منوها</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ منوی جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._loadPerms(),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal())}async _loadPerms(){try{const e=await this.api.get("/acl/permissions");this._perms=(e==null?void 0:e.data)??[]}catch{}}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/acl/menus");this._rows=(e==null?void 0:e.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">منویی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>ترتیب</th><th>منو</th><th>کلید</th><th>مسیر</th>
                <th>مجوز لازم</th><th>وضعیت</th><th>اقدام</th>
            </tr></thead>
            <tbody>
            ${this._rows.map(e=>`<tr>
                <td>${e.sort_order}</td>
                <td>${e.icon} ${this.escape(e.title)}</td>
                <td><small style="font-family:monospace;">${this.escape(e.menu_key)}</small></td>
                <td><small>${this.escape(e.route)}</small></td>
                <td>
                    ${e.required_permission?`<small style="font-family:monospace;color:#1d4ed8;">${this.escape(e.required_permission)}</small>`:'<span style="color:#94a3b8;font-size:11px;">بدون محدودیت</span>'}
                </td>
                <td>${e.is_active==1?"✅":"❌"}</td>
                <td style="display:flex;gap:4px;">
                    <button class="acc-btn acc-btn--xs" data-edit="${e.id}">✏️</button>
                    <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${e.id}">🗑️</button>
                </td>
            </tr>`).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(e=>e.addEventListener("click",()=>this._openModal(this._rows.find(t=>t.id==e.dataset.edit)))),this.ref("wrap").querySelectorAll("[data-del]").forEach(e=>e.addEventListener("click",async()=>{if(confirm("حذف این منو؟"))try{await this.api.delete(`/acl/menus/${e.dataset.del}`),this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}))}_openModal(e=null){const t=!!e,s='<option value="">— بدون محدودیت —</option>'+this._perms.map(n=>`<option value="${n.permission_key}" ${(e==null?void 0:e.required_permission)===n.permission_key?"selected":""}>${this.escape(n.label)} [${this.escape(n.permission_key)}]</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
        <div class="acc-modal" style="max-width:480px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش منو":"➕ منوی جدید"}</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کلید *</label>
                        <input name="menu_key" required value="${this.escape((e==null?void 0:e.menu_key)??"")}" ${t?"readonly":""}>
                    </div>
                    <div class="acc-form-group"><label>عنوان *</label>
                        <input name="title" required value="${this.escape((e==null?void 0:e.title)??"")}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>آیکن</label>
                        <input name="icon" value="${this.escape((e==null?void 0:e.icon)??"")}" placeholder="مثلاً 🗺️">
                    </div>
                    <div class="acc-form-group"><label>مسیر / تب</label>
                        <input name="route" value="${this.escape((e==null?void 0:e.route)??"")}" placeholder="مثلاً gis">
                    </div>
                </div>
                <div class="acc-form-group"><label>مجوز لازم برای نمایش</label>
                    <select name="required_permission">${s}</select>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>ترتیب نمایش</label>
                        <input name="sort_order" type="number" value="${(e==null?void 0:e.sort_order)??0}">
                    </div>
                    <div class="acc-form-group"><label>وضعیت</label>
                        <select name="is_active">
                            <option value="1" ${(e==null?void 0:e.is_active)==1?"selected":""}>✅ فعال</option>
                            <option value="0" ${(e==null?void 0:e.is_active)==0?"selected":""}>❌ غیرفعال</option>
                        </select>
                    </div>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action=cancel]").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());try{t?await this.api.put(`/acl/menus/${e.id}`,r):await this.api.post("/acl/menus",r),i(),this._load()}catch(o){alert("خطا: "+((o==null?void 0:o.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const St=[{key:"users",icon:"👤",title:"پروفایل کاربر",desc:"منو + نقش + scope",Class:Jr},{key:"users_adv",icon:"👥",title:"کاربران (پیشرفته)",desc:"اختصاص نقش تکی",Class:Yr},{key:"roles",icon:"🎭",title:"نقش‌ها",desc:"تعریف نقش و مجوز",Class:Qr},{key:"permissions",icon:"🔑",title:"مجوزها",desc:"لیست همه مجوزها",Class:Xr},{key:"menus",icon:"📋",title:"منوها",desc:"منو با مجوز لازم",Class:eo}];class Ct extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="users",this._sections={}}async template(){const t=St.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
                <div class="sp-nav-card__desc">${a.desc}</div>
            </div>
        `).join(""),s=St.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=St.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(Ct,"title","🛡️ مدیریت دسترسی‌ها"),E.register("acl",Ct),E.register("access",Ct);const Ys={active:{label:"فعال",color:"#10b981"},inactive:{label:"غیرفعال",color:"#94a3b8"},on_leave:{label:"در مرخصی",color:"#f59e0b"}};class to extends x{constructor(e){super(e),this._depts=[],this._positions=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">👥 کارمندان</h2>
                <div style="display:flex;gap:8px;">
                    <input type="text" data-ref="search" placeholder="جستجو نام/کد/کدملی..." class="acc-input" style="width:220px;">
                    <select data-ref="deptFilter" class="acc-input"><option value="">همه بخش‌ها</option></select>
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ کارمند جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await Promise.all([this._loadDepts(),this._loadPositions()]),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal()),this.on(this.ref("search"),"input",()=>{clearTimeout(this._t),this._t=setTimeout(()=>this._load(),300)}),this.on(this.ref("deptFilter"),"change",()=>this._load())}async _loadDepts(){try{const e=await this.api.get("/hr/departments");this._depts=(e==null?void 0:e.data)??[];const t=this.ref("deptFilter");this._depts.forEach(s=>{const a=document.createElement("option");a.value=s.id,a.textContent=s.name,t.appendChild(a)})}catch{}}async _loadPositions(){try{const e=await this.api.get("/hr/positions");this._positions=(e==null?void 0:e.data)??[]}catch{}}async _load(){var a,i,n;const e={},t=(i=(a=this.ref("search"))==null?void 0:a.value)==null?void 0:i.trim(),s=(n=this.ref("deptFilter"))==null?void 0:n.value;t&&(e.search=t),s&&(e.department_id=s),this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const r=await this.api.get("/hr/employees",e);this._rows=(r==null?void 0:r.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">کارمندی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(300px,1fr));gap:12px;padding:4px;">
            ${this._rows.map(e=>{const t=Ys[e.status]??{label:e.status,color:"#64748b"};return`
                <div style="border:1px solid #e2e8f0;border-radius:10px;padding:12px;background:#fff;">
                    <div style="display:flex;justify-content:space-between;align-items:start;">
                        <div style="flex:1;">
                            <div style="font-weight:700;font-size:14px;">👤 ${this.escape(e.full_name)}</div>
                            <small style="color:#94a3b8;font-family:monospace;">${this.escape(e.employee_code)}</small>
                        </div>
                        <span style="background:${t.color}1a;color:${t.color};padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${t.label}</span>
                    </div>
                    ${e.position_title?`<div style="font-size:12px;color:#475569;margin-top:6px;">💼 ${this.escape(e.position_title)}</div>`:""}
                    ${e.dept_name?`<div style="font-size:12px;color:#64748b;">🏢 ${this.escape(e.dept_name)}</div>`:""}
                    ${e.mobile?`<div style="font-size:12px;color:#64748b;direction:ltr;text-align:right;">📱 ${this.escape(e.mobile)}</div>`:""}
                    <div style="display:flex;gap:4px;margin-top:10px;">
                        <button class="acc-btn acc-btn--xs" data-edit="${e.id}">✏️ ویرایش</button>
                        <button class="acc-btn acc-btn--xs" data-loc="${e.id}" data-name="${this.escape(e.full_name)}" style="background:#dbeafe;color:#1e40af;">📍 موقعیت‌ها</button>
                    </div>
                </div>`}).join("")}
        </div>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(e=>e.addEventListener("click",()=>this._openModal(this._rows.find(t=>t.id==e.dataset.edit)))),this.ref("wrap").querySelectorAll("[data-loc]").forEach(e=>e.addEventListener("click",()=>z.openModal({api:this.api,entityType:"employee",entityId:parseInt(e.dataset.loc),entityName:e.dataset.name})))}_openModal(e=null){const t=!!e,s='<option value="">—</option>'+this._depts.map(r=>`<option value="${r.id}" ${(e==null?void 0:e.department_id)==r.id?"selected":""}>${this.escape(r.name)}</option>`).join(""),a='<option value="">—</option>'+this._positions.map(r=>`<option value="${r.id}" ${(e==null?void 0:e.position_id)==r.id?"selected":""}>${this.escape(r.title)}</option>`).join(""),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
        <div class="acc-modal" style="max-width:640px;max-height:92vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش":"➕ کارمند جدید"}</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد کارمندی</label>
                        <input name="employee_code" value="${this.escape((e==null?void 0:e.employee_code)??"")}" placeholder="(خودکار)">
                    </div>
                    <div class="acc-form-group"><label>وضعیت</label>
                        <select name="status">
                            ${Object.entries(Ys).map(([r,o])=>`<option value="${r}" ${(e==null?void 0:e.status)===r?"selected":""}>${o.label}</option>`).join("")}
                        </select>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>نام *</label>
                        <input name="first_name" required value="${this.escape((e==null?void 0:e.first_name)??"")}">
                    </div>
                    <div class="acc-form-group"><label>نام خانوادگی *</label>
                        <input name="last_name" required value="${this.escape((e==null?void 0:e.last_name)??"")}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد ملی</label>
                        <input name="national_id" value="${this.escape((e==null?void 0:e.national_id)??"")}">
                    </div>
                    <div class="acc-form-group"><label>نام پدر</label>
                        <input name="father_name" value="${this.escape((e==null?void 0:e.father_name)??"")}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تاریخ تولد</label>
                        <input name="birth_date" type="date" value="${(e==null?void 0:e.birth_date)??""}">
                    </div>
                    <div class="acc-form-group"><label>جنسیت</label>
                        <select name="gender">
                            <option value="">—</option>
                            <option value="male"   ${(e==null?void 0:e.gender)==="male"?"selected":""}>مرد</option>
                            <option value="female" ${(e==null?void 0:e.gender)==="female"?"selected":""}>زن</option>
                        </select>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>موبایل</label>
                        <input name="mobile" value="${this.escape((e==null?void 0:e.mobile)??"")}" dir="ltr">
                    </div>
                    <div class="acc-form-group"><label>ایمیل</label>
                        <input name="email" type="email" value="${this.escape((e==null?void 0:e.email)??"")}" dir="ltr">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>بخش</label>
                        <select name="department_id">${s}</select>
                    </div>
                    <div class="acc-form-group"><label>سمت</label>
                        <select name="position_id">${a}</select>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تاریخ استخدام</label>
                        <input name="hire_date" type="date" value="${(e==null?void 0:e.hire_date)??""}">
                    </div>
                    <div class="acc-form-group"><label>نوع همکاری</label>
                        <select name="employment_type">
                            <option value="full_time"  ${(e==null?void 0:e.employment_type)==="full_time"?"selected":""}>تمام‌وقت</option>
                            <option value="part_time"  ${(e==null?void 0:e.employment_type)==="part_time"?"selected":""}>پاره‌وقت</option>
                            <option value="contract"   ${(e==null?void 0:e.employment_type)==="contract"?"selected":""}>قرارداد موقت</option>
                            <option value="freelance"  ${(e==null?void 0:e.employment_type)==="freelance"?"selected":""}>پروژه‌ای</option>
                        </select>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>حقوق پایه (ریال)</label>
                        <input name="base_salary" type="number" value="${(e==null?void 0:e.base_salary)??0}">
                    </div>
                    <div class="acc-form-group"><label>شماره IBAN</label>
                        <input name="iban" value="${this.escape((e==null?void 0:e.iban)??"")}" dir="ltr">
                    </div>
                </div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" rows="2">${this.escape((e==null?void 0:e.notes)??"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(i);const n=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",n),i.querySelector("[data-action=cancel]").addEventListener("click",n),i.addEventListener("click",r=>{r.target===i&&n()}),i.querySelector("form").addEventListener("submit",async r=>{r.preventDefault();const o=Object.fromEntries(new FormData(r.target).entries()),l=r.target.querySelector("[type=submit]");l.disabled=!0;try{t?await this.api.put(`/hr/employees/${e.id}`,o):await this.api.post("/hr/employees",o),n(),this._load()}catch(c){alert("خطا: "+((c==null?void 0:c.message)??"")),l.disabled=!1}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}class so extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🏢 بخش‌ها</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ بخش جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/hr/departments");this._rows=(e==null?void 0:e.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">بخشی ثبت نشده</div>';return}const e=(t,s=0)=>this._rows.filter(a=>a.parent_id==t).map(a=>`
            <div style="margin-right:${s*20}px;padding:8px 12px;border:1px solid #e2e8f0;border-radius:8px;margin-bottom:6px;background:#fff;">
                <div style="display:flex;justify-content:space-between;align-items:center;">
                    <div>
                        <b>🏢 ${this.escape(a.name)}</b>
                        <small style="color:#94a3b8;margin-right:6px;">${this.escape(a.code||"")}</small>
                        ${a.manager_first?`<small style="color:#3b82f6;margin-right:8px;">👤 ${this.escape(a.manager_first)} ${this.escape(a.manager_last)}</small>`:""}
                    </div>
                    <div style="display:flex;gap:4px;">
                        <span style="background:#dbeafe;color:#1e40af;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${a.emp_count} کارمند</span>
                        <button class="acc-btn acc-btn--xs" data-edit="${a.id}">✏️</button>
                        <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${a.id}">🗑️</button>
                    </div>
                </div>
            </div>
            ${e(a.id,s+1)}
        `).join("");this.ref("wrap").innerHTML=e(0),this.ref("wrap").querySelectorAll("[data-edit]").forEach(t=>t.addEventListener("click",()=>this._openModal(this._rows.find(s=>s.id==t.dataset.edit)))),this.ref("wrap").querySelectorAll("[data-del]").forEach(t=>t.addEventListener("click",async()=>{if(confirm("حذف این بخش؟"))try{await this.api.delete(`/hr/departments/${t.dataset.del}`),this._load()}catch(s){alert("خطا: "+((s==null?void 0:s.message)??""))}}))}_openModal(e=null){const t=!!e,s='<option value="0">سطح اول</option>'+this._rows.map(n=>`<option value="${n.id}" ${(e==null?void 0:e.parent_id)==n.id?"selected":""}>${this.escape(n.name)}</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
        <div class="acc-modal" style="max-width:420px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش":"➕ بخش جدید"}</div>
            <form>
                <div class="acc-form-group"><label>بخش والد</label>
                    <select name="parent_id">${s}</select>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد</label><input name="code" value="${this.escape((e==null?void 0:e.code)??"")}"></div>
                    <div class="acc-form-group"><label>نام *</label><input name="name" required value="${this.escape((e==null?void 0:e.name)??"")}"></div>
                </div>
                <div class="acc-form-group"><label>توضیحات</label>
                    <textarea name="description" rows="2">${this.escape((e==null?void 0:e.description)??"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action=cancel]").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());try{t?await this.api.put(`/hr/departments/${e.id}`,r):await this.api.post("/hr/departments",r),i(),this._load()}catch(o){alert("خطا: "+((o==null?void 0:o.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const Qs={exec:"مدیر اجرایی",manager:"مدیر",supervisor:"سرپرست",senior:"ارشد",staff:"کارمند",intern:"کارآموز"};class ao extends x{constructor(e){super(e),this._depts=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📋 سمت‌ها</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ سمت جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){try{const e=await this.api.get("/hr/departments");this._depts=(e==null?void 0:e.data)??[]}catch{}await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/hr/positions");this._rows=(e==null?void 0:e.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">سمتی ثبت نشده</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr><th>کد</th><th>عنوان</th><th>بخش</th><th>سطح</th><th>کارمندان</th><th>اقدام</th></tr></thead>
            <tbody>
            ${this._rows.map(e=>`<tr>
                <td><small style="font-family:monospace;">${this.escape(e.code)}</small></td>
                <td><b>${this.escape(e.title)}</b></td>
                <td>${this.escape(e.dept_name??"—")}</td>
                <td><span style="background:#f1f5f9;padding:2px 8px;border-radius:6px;font-size:11px;">${Qs[e.level]??e.level}</span></td>
                <td><b style="color:#3b82f6;">${e.emp_count}</b></td>
                <td style="display:flex;gap:4px;">
                    <button class="acc-btn acc-btn--xs" data-edit="${e.id}">✏️</button>
                    <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${e.id}">🗑️</button>
                </td>
            </tr>`).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(e=>e.addEventListener("click",()=>this._openModal(this._rows.find(t=>t.id==e.dataset.edit)))),this.ref("wrap").querySelectorAll("[data-del]").forEach(e=>e.addEventListener("click",async()=>{if(confirm("حذف این سمت؟"))try{await this.api.delete(`/hr/positions/${e.dataset.del}`),this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}))}_openModal(e=null){const t=!!e,s='<option value="">—</option>'+this._depts.map(r=>`<option value="${r.id}" ${(e==null?void 0:e.department_id)==r.id?"selected":""}>${this.escape(r.name)}</option>`).join(""),a=Object.entries(Qs).map(([r,o])=>`<option value="${r}" ${(e==null?void 0:e.level)===r?"selected":""}>${o}</option>`).join(""),i=document.createElement("div");i.className="acc-modal-overlay",i.innerHTML=`
        <div class="acc-modal" style="max-width:440px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش":"➕ سمت جدید"}</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد</label><input name="code" value="${this.escape((e==null?void 0:e.code)??"")}"></div>
                    <div class="acc-form-group"><label>عنوان *</label><input name="title" required value="${this.escape((e==null?void 0:e.title)??"")}"></div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>بخش</label><select name="department_id">${s}</select></div>
                    <div class="acc-form-group"><label>سطح</label><select name="level">${a}</select></div>
                </div>
                <div class="acc-form-group"><label>شرح وظایف</label>
                    <textarea name="description" rows="3">${this.escape((e==null?void 0:e.description)??"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(i);const n=()=>i.remove();i.querySelector(".acc-modal__close").addEventListener("click",n),i.querySelector("[data-action=cancel]").addEventListener("click",n),i.addEventListener("click",r=>{r.target===i&&n()}),i.querySelector("form").addEventListener("submit",async r=>{r.preventDefault();const o=Object.fromEntries(new FormData(r.target).entries());try{t?await this.api.put(`/hr/positions/${e.id}`,o):await this.api.post("/hr/positions",o),n(),this._load()}catch(l){alert("خطا: "+((l==null?void 0:l.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const io={present:"حاضر",absent:"غایب",leave:"مرخصی",late:"تأخیر"};class no extends x{constructor(e){super(e),this._emps=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">⏰ حضور غیاب</h2>
                <div style="display:flex;gap:8px;">
                    <select data-ref="empFilter" class="acc-input" style="width:200px;"><option value="">همه کارمندان</option></select>
                    <input type="date" data-ref="fromDate" class="acc-input">
                    <input type="date" data-ref="toDate" class="acc-input">
                    <button class="acc-btn acc-btn--primary" data-ref="checkBtn">⏱️ ثبت ورود/خروج</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){try{const s=await this.api.get("/hr/employees");this._emps=(s==null?void 0:s.data)??[];const a=this.ref("empFilter");this._emps.forEach(i=>{const n=document.createElement("option");n.value=i.id,n.textContent=i.full_name,a.appendChild(n)})}catch{}const e=new Date().toISOString().split("T")[0],t=new Date(Date.now()-30*864e5).toISOString().split("T")[0];this.ref("fromDate").value=t,this.ref("toDate").value=e,await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("checkBtn"),"click",()=>this._openCheckModal()),this.on(this.ref("empFilter"),"change",()=>this._load()),this.on(this.ref("fromDate"),"change",()=>this._load()),this.on(this.ref("toDate"),"change",()=>this._load())}async _load(){var s,a,i;const e={from:(s=this.ref("fromDate"))==null?void 0:s.value,to:(a=this.ref("toDate"))==null?void 0:a.value},t=(i=this.ref("empFilter"))==null?void 0:i.value;t&&(e.employee_id=t),this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const n=await this.api.get("/hr/attendance",e);this._render((n==null?void 0:n.data)??[])}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(e){if(!e.length){this.ref("wrap").innerHTML='<div class="acc-empty">رکوردی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr><th>کارمند</th><th>تاریخ</th><th>ورود</th><th>خروج</th><th>ساعت</th><th>وضعیت</th><th>GPS</th></tr></thead>
            <tbody>
            ${e.map(t=>`<tr>
                <td><b>${this.escape(t.employee_name)}</b></td>
                <td>${t.date}</td>
                <td style="font-family:monospace;">${t.check_in?t.check_in.substring(11,16):"—"}</td>
                <td style="font-family:monospace;">${t.check_out?t.check_out.substring(11,16):"—"}</td>
                <td><b>${t.hours?t.hours+" ساعت":"—"}</b></td>
                <td>${io[t.status]??t.status}</td>
                <td>${t.check_in_lat?'<span title="ورود ثبت GPS شده">📍</span>':""}</td>
            </tr>`).join("")}
            </tbody>
        </table>`}_openCheckModal(){const e=this._emps.map(i=>`<option value="${i.id}">${this.escape(i.full_name)}</option>`).join(""),t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:380px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">⏱️ ثبت ورود/خروج</div>
            <form>
                <div class="acc-form-group"><label>کارمند *</label>
                    <select name="employee_id" required><option value="">انتخاب...</option>${e}</select>
                </div>
                <div class="acc-form-group"><label>عملیات</label>
                    <select name="action">
                        <option value="check_in">ورود</option>
                        <option value="check_out">خروج</option>
                    </select>
                </div>
                <div data-ref-gps style="background:#f0fdf4;padding:8px;border-radius:6px;font-size:12px;color:#166534;">
                    📍 در حال دریافت GPS...
                </div>
                <input type="hidden" name="lat"><input type="hidden" name="lng">
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ثبت</button>
                </div>
            </form>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector("[data-action=cancel]").addEventListener("click",s),t.addEventListener("click",i=>{i.target===t&&s()});const a=t.querySelector("[data-ref-gps]");navigator.geolocation?navigator.geolocation.getCurrentPosition(i=>{t.querySelector("[name=lat]").value=i.coords.latitude,t.querySelector("[name=lng]").value=i.coords.longitude,a.innerHTML=`📍 ثبت شد: ${i.coords.latitude.toFixed(5)}, ${i.coords.longitude.toFixed(5)}`},i=>{a.innerHTML="⚠️ GPS در دسترس نیست — ثبت بدون موقعیت",a.style.background="#fef9c3",a.style.color="#854d0e"}):a.innerHTML="⚠️ مرورگر از GPS پشتیبانی نمی‌کند",t.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries());try{await this.api.post("/hr/attendance",n),s(),this._load(),this._toast("✅ ثبت شد","#10b981")}catch(r){alert("خطا: "+((r==null?void 0:r.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const Zs={annual:"استحقاقی",sick:"استعلاجی",emergency:"فوریتی",unpaid:"بدون حقوق",maternity:"زایمان",other:"سایر"},Xs={pending:{label:"در انتظار",color:"#f59e0b"},approved:{label:"تأیید شده",color:"#10b981"},rejected:{label:"رد شده",color:"#ef4444"}};class ro extends x{constructor(e){super(e),this._emps=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🌴 مرخصی‌ها</h2>
                <div style="display:flex;gap:8px;">
                    <select data-ref="statusFilter" class="acc-input">
                        <option value="">همه وضعیت‌ها</option>
                        ${Object.entries(Xs).map(([e,t])=>`<option value="${e}">${t.label}</option>`).join("")}
                    </select>
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ درخواست جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){try{const e=await this.api.get("/hr/employees");this._emps=(e==null?void 0:e.data)??[]}catch{}await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal()),this.on(this.ref("statusFilter"),"change",()=>this._load())}async _load(){var s;const e={},t=(s=this.ref("statusFilter"))==null?void 0:s.value;t&&(e.status=t),this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const a=await this.api.get("/hr/leaves",e);this._render((a==null?void 0:a.data)??[])}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(e){if(!e.length){this.ref("wrap").innerHTML='<div class="acc-empty">درخواستی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr><th>کارمند</th><th>نوع</th><th>از</th><th>تا</th><th>روز</th><th>دلیل</th><th>وضعیت</th><th>اقدام</th></tr></thead>
            <tbody>
            ${e.map(t=>{const s=Xs[t.status]??{label:t.status,color:"#64748b"};return`<tr>
                    <td><b>${this.escape(t.employee_name)}</b></td>
                    <td>${Zs[t.leave_type]??t.leave_type}</td>
                    <td>${t.from_date}</td>
                    <td>${t.to_date}</td>
                    <td><b>${t.days}</b></td>
                    <td style="max-width:200px;overflow:hidden;text-overflow:ellipsis;">${this.escape(t.reason??"")}</td>
                    <td><span style="background:${s.color}1a;color:${s.color};padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${s.label}</span></td>
                    <td style="display:flex;gap:3px;">
                        ${t.status==="pending"?`
                        <button class="acc-btn acc-btn--xs" data-approve="${t.id}" style="background:#d1fae5;color:#065f46;">✅</button>
                        <button class="acc-btn acc-btn--xs gis-btn--danger" data-reject="${t.id}">❌</button>
                        `:""}
                        <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${t.id}">🗑️</button>
                    </td>
                </tr>`}).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-approve]").forEach(t=>t.addEventListener("click",()=>this._setStatus(t.dataset.approve,"approved"))),this.ref("wrap").querySelectorAll("[data-reject]").forEach(t=>t.addEventListener("click",()=>this._setStatus(t.dataset.reject,"rejected"))),this.ref("wrap").querySelectorAll("[data-del]").forEach(t=>t.addEventListener("click",async()=>{if(confirm("حذف این درخواست؟"))try{await this.api.delete(`/hr/leaves/${t.dataset.del}`),this._load()}catch(s){alert("خطا: "+((s==null?void 0:s.message)??""))}}))}async _setStatus(e,t){try{await this.api.put(`/hr/leaves/${e}`,{status:t}),this._load()}catch(s){alert("خطا: "+((s==null?void 0:s.message)??""))}}_openModal(){const e=this._emps.map(i=>`<option value="${i.id}">${this.escape(i.full_name)}</option>`).join(""),t=Object.entries(Zs).map(([i,n])=>`<option value="${i}">${n}</option>`).join(""),s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
        <div class="acc-modal" style="max-width:420px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🌴 درخواست مرخصی</div>
            <form>
                <div class="acc-form-group"><label>کارمند *</label>
                    <select name="employee_id" required><option value="">انتخاب...</option>${e}</select>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>نوع</label><select name="leave_type">${t}</select></div>
                    <div class="acc-form-group"><label></label><span></span></div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>از تاریخ *</label><input name="from_date" type="date" required></div>
                    <div class="acc-form-group"><label>تا تاریخ *</label><input name="to_date" type="date" required></div>
                </div>
                <div class="acc-form-group"><label>دلیل</label>
                    <textarea name="reason" rows="3"></textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ثبت درخواست</button>
                </div>
            </form>
        </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action=cancel]").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries());try{await this.api.post("/hr/leaves",n),a(),this._load()}catch(r){alert("خطا: "+((r==null?void 0:r.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const ea={office:"#3b82f6",warehouse:"#f59e0b",home:"#10b981",site:"#ef4444",meeting:"#8b5cf6",branch:"#06b6d4",factory:"#dc2626",other:"#64748b"};class oo extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🗺️ نقشه پرسنل</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="mapEl" style="height:600px;border:1px solid #cbd5e1;border-radius:8px;background:#f8fafc;">
                <div style="padding:40px;text-align:center;color:#64748b;">⏳ بارگذاری نقشه...</div>
            </div>
        </div>`}async afterRender(){await this._loadLeaflet(),this._initMap(),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load())}async _loadLeaflet(){var s;if(window.L)return;const e=(((s=window.ACC_CONFIG)==null?void 0:s.pluginUrl)??"").replace(/\/+$/,""),t=e?`${e}/assets/vendor/leaflet`:"/wp-content/plugins/acc-engine/assets/vendor/leaflet";if(!document.querySelector('link[href*="leaflet"]')){const a=document.createElement("link");a.rel="stylesheet",a.href=`${t}/leaflet.css`,document.head.appendChild(a)}await new Promise((a,i)=>{const n=document.createElement("script");n.src=`${t}/leaflet.js`,n.onload=a,n.onerror=i,document.head.appendChild(n)})}_initMap(){var a;const e=window.L,t=this.ref("mapEl");t.innerHTML="",this._map=e.map(t).setView([29.5926,52.5836],12);const s=(((a=window.ACC_CONFIG)==null?void 0:a.pluginUrl)??"").replace(/\/+$/,"");e.tileLayer(`${s||"/wp-content/plugins/acc-engine"}/assets/vendor/leaflet/tiles_esri/{z}/{x}/{y}.png`,{attribution:"© Esri",minZoom:10,maxZoom:19,maxNativeZoom:16}).addTo(this._map),this._layer=e.layerGroup().addTo(this._map)}async _load(){try{const e=await this.api.get("/gis/locations/map",{entity_type:"employee"});this._renderMarkers((e==null?void 0:e.data)??[])}catch{this._toast("❌ خطا در بارگذاری","#ef4444")}}async _renderMarkers(e){const t=window.L;if(this._layer.clearLayers(),!e.length){this._toast("موقعیتی برای پرسنل ثبت نشده","#f59e0b");return}const s={};try{const i=await this.api.get("/hr/employees");((i==null?void 0:i.data)??[]).forEach(n=>s[n.id]=n)}catch{}const a=[];e.forEach(i=>{const n=parseFloat(i.lat),r=parseFloat(i.lng);if(isNaN(n)||isNaN(r))return;const o=ea[i.location_type]??ea.other,l=s[i.entity_id],c=t.circleMarker([n,r],{radius:8,fillColor:o,color:"#fff",weight:2,fillOpacity:.9}),d=l?`${l.first_name} ${l.last_name}`:`#${i.entity_id}`;c.bindTooltip(`
                <b>👤 ${this.escape(d)}</b>
                ${i.label?`<br>${this.escape(i.label)}`:""}
                ${i.address?`<br><small>${this.escape(i.address)}</small>`:""}
            `,{direction:"top"}),c.addTo(this._layer),a.push([n,r])}),a.length&&this._map.fitBounds(a,{padding:[40,40],maxZoom:15})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const Tt=[{key:"employees",icon:"👥",title:"کارمندان",desc:"اطلاعات کامل + موقعیت",Class:to},{key:"departments",icon:"🏢",title:"بخش‌ها",desc:"ساختار سازمانی",Class:so},{key:"positions",icon:"📋",title:"سمت‌ها",desc:"شغل و سطح",Class:ao},{key:"attendance",icon:"⏰",title:"حضور غیاب",desc:"ورود/خروج + GPS",Class:no},{key:"leaves",icon:"🌴",title:"مرخصی‌ها",desc:"درخواست و تأیید",Class:ro},{key:"map",icon:"🗺️",title:"نقشه پرسنل",desc:"محل سکونت/کار",Class:oo}];class ta extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="employees",this._sections={}}async template(){const t=Tt.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
                <div class="sp-nav-card__desc">${a.desc}</div>
            </div>
        `).join(""),s=Tt.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=Tt.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(ta,"title","نیروی انسانی"),E.register("hr",ta);const lo={pending:"#94a3b8",ordered:"#6366f1",preparing:"#3b82f6",packed:"#06b6d4",picked_up:"#8b5cf6",in_transit:"#f59e0b",out_for_delivery:"#f97316",arrived:"#10b981",inspection:"#eab308",received:"#059669",delivered:"#059669",rejected:"#ef4444",failed:"#ef4444",returned:"#dc2626",cancelled:"#64748b"},co={pending:"در انتظار",ordered:"سفارش شده",preparing:"آماده‌سازی",packed:"بسته‌بندی شده",picked_up:"تحویل به حمل",in_transit:"در حال حمل",out_for_delivery:"ارسال نهایی",arrived:"رسید",inspection:"بازرسی",received:"پذیرفته شد",delivered:"تحویل مشتری",rejected:"رد شد",failed:"ناموفق",returned:"مرجوعی",cancelled:"لغو شد"};class po extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📊 داشبورد حمل و نقل</h2>
                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/ship/dashboard");this._render(e)}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(e){var n;const t=(e.by_status??[]).reduce((r,o)=>{const l=`${o.direction}:${o.status}`;return r[l]=(r[l]??0)+parseInt(o.cnt),r},{}),s=["pending","ordered","preparing","picked_up","in_transit","arrived","inspection","received"],a=["pending","preparing","packed","picked_up","in_transit","out_for_delivery","delivered"],i=(r,o,l,c)=>{const d=o.reduce((h,u)=>h+(t[`${r}:${u}`]??0),0);return`
            <div style="background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:14px;margin-bottom:12px;">
                <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:10px;">
                    <h3 style="margin:0;font-size:14px;">${c} ${l}</h3>
                    <span style="background:#eff6ff;color:#1e40af;padding:2px 10px;border-radius:10px;font-size:12px;font-weight:700;">جمع: ${d}</span>
                </div>
                <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(110px,1fr));gap:6px;">
                    ${o.map(h=>{const u=t[`${r}:${h}`]??0,f=lo[h]??"#64748b";return`
                        <div style="background:${f}1a;border:1px solid ${f}55;border-radius:8px;padding:8px;text-align:center;cursor:pointer;"
                             data-filter='{"direction":"${r}","status":"${h}"}'>
                            <div style="font-size:10px;color:${f};font-weight:600;">${co[h]}</div>
                            <div style="font-size:18px;font-weight:700;color:${f};">${u}</div>
                        </div>`}).join("")}
                </div>
            </div>`};this.ref("wrap").innerHTML=`
        <!-- KPI cards -->
        <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:16px;">
            <div style="background:linear-gradient(135deg,#3b82f6,#1d4ed8);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">🚚 محموله فعال</div>
                <div style="font-size:28px;font-weight:700;margin-top:4px;">${e.active_count??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">⏰ تأخیردار</div>
                <div style="font-size:28px;font-weight:700;margin-top:4px;">${e.delayed_count??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#10b981,#059669);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">⭐ کیفیت میانگین</div>
                <div style="font-size:28px;font-weight:700;margin-top:4px;">${e.avg_quality??0}<small style="font-size:14px;">/100</small></div>
            </div>
            <div style="background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">⏱️ زمان میانگین (ساعت)</div>
                <div style="font-size:28px;font-weight:700;margin-top:4px;">${(n=e.avg_time)!=null&&n.avg_hours?Math.round(e.avg_time.avg_hours):"—"}</div>
            </div>
        </div>

        ${i("inbound",s,"محموله‌های ورودی (خرید)","📥")}
        ${i("outbound",a,"محموله‌های خروجی (فروش)","📤")}
        `,this.ref("wrap").querySelectorAll("[data-filter]").forEach(r=>r.addEventListener("click",()=>this._toast("💡 برای فیلتر دقیق به بخش «محموله‌ها» بروید","#3b82f6")))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const me={pending:"#94a3b8",ordered:"#6366f1",preparing:"#3b82f6",packed:"#06b6d4",picked_up:"#8b5cf6",in_transit:"#f59e0b",out_for_delivery:"#f97316",arrived:"#10b981",inspection:"#eab308",received:"#059669",delivered:"#059669",rejected:"#ef4444",failed:"#ef4444",returned:"#dc2626",cancelled:"#64748b"},ie={pending:"در انتظار",ordered:"سفارش شده",preparing:"آماده‌سازی",packed:"بسته‌بندی شده",picked_up:"تحویل به حمل",in_transit:"در حال حمل",out_for_delivery:"ارسال نهایی",arrived:"رسید",inspection:"بازرسی",received:"پذیرفته شد",delivered:"تحویل مشتری",rejected:"رد شد",failed:"ناموفق",returned:"مرجوعی",cancelled:"لغو شد"};class ho extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🚚 محموله‌ها</h2>
                <div style="display:flex;gap:8px;flex-wrap:wrap;">
                    <select data-ref="dirFilter" class="acc-input">
                        <option value="">همه جهت‌ها</option>
                        <option value="inbound">📥 ورودی (خرید)</option>
                        <option value="outbound">📤 خروجی (فروش)</option>
                        <option value="transfer">🔄 انتقالی</option>
                    </select>
                    <select data-ref="statusFilter" class="acc-input">
                        <option value="">همه وضعیت‌ها</option>
                        ${Object.entries(ie).map(([e,t])=>`<option value="${e}">${t}</option>`).join("")}
                    </select>
                    <input type="text" data-ref="search" placeholder="🔍 شماره/کد رهگیری/گیرنده" class="acc-input" style="width:220px;">
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("dirFilter"),"change",()=>this._load()),this.on(this.ref("statusFilter"),"change",()=>this._load()),this.on(this.ref("search"),"input",()=>{clearTimeout(this._t),this._t=setTimeout(()=>this._load(),300)})}async _load(){var i,n,r,o;const e={},t=(i=this.ref("dirFilter"))==null?void 0:i.value,s=(n=this.ref("statusFilter"))==null?void 0:n.value,a=(o=(r=this.ref("search"))==null?void 0:r.value)==null?void 0:o.trim();t&&(e.direction=t),s&&(e.status=s),a&&(e.search=a),this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const l=await this.api.get("/ship/shipments",e);this._rows=(l==null?void 0:l.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">محموله‌ای یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>شماره</th><th>جهت</th><th>روش حمل</th><th>وضعیت</th>
                <th>مرجع</th><th>گیرنده</th><th>زمان</th><th>اقدام</th>
            </tr></thead>
            <tbody>
            ${this._rows.map(e=>{const t=me[e.status]??"#64748b",s=ie[e.status]??e.status,a=e.direction==="outbound"?"📤":e.direction==="transfer"?"🔄":"📥",i=e.planned_delivery_date&&new Date(e.planned_delivery_date)<new Date&&!e.actual_delivery_date&&!["received","delivered","cancelled","rejected"].includes(e.status);return`<tr ${i?'style="background:#fef2f2;"':""}>
                    <td>
                        <b style="font-family:monospace;">${this.escape(e.shipment_no)}</b>
                        ${i?'<br><small style="color:#ef4444;">⏰ تأخیر</small>':""}
                    </td>
                    <td>${a}</td>
                    <td>${e.method_icon||"🚚"} <small>${this.escape(e.method_name??"—")}</small></td>
                    <td><span style="background:${t}1a;color:${t};padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${s}</span></td>
                    <td><small>${this.escape(e.ref_no??"—")}</small></td>
                    <td><small>${this.escape(e.recipient_name??"—")}</small></td>
                    <td><small>${e.planned_delivery_date??"—"}</small></td>
                    <td><button class="acc-btn acc-btn--xs acc-btn--primary" data-view="${e.id}">📦 مشاهده</button></td>
                </tr>`}).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-view]").forEach(e=>e.addEventListener("click",()=>this._viewShipment(parseInt(e.dataset.view))))}async _viewShipment(e){try{const t=await this.api.get(`/ship/shipments/${e}`),s=t==null?void 0:t.data;if(!s)return;this._renderShipmentModal(s)}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}_renderShipmentModal(e){const t=me[e.status]??"#64748b",s=ie[e.status]??e.status,a=e.direction==="outbound"?"📤 خروجی":"📥 ورودی",i=this._getNextStages(e.direction,e.status),n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
        <div class="acc-modal" style="max-width:780px;max-height:92vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${e.method_icon??"🚚"} محموله ${this.escape(e.shipment_no)}</div>

            <!-- وضعیت -->
            <div style="background:${t}1a;border-right:4px solid ${t};padding:10px 14px;border-radius:6px;margin-bottom:14px;">
                <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:8px;">
                    <div>
                        <span style="color:${t};font-weight:700;font-size:16px;">${s}</span>
                        <div style="font-size:11px;color:#64748b;margin-top:2px;">${a} | ${this.escape(e.method_name??"")}</div>
                    </div>
                    <div style="display:flex;gap:6px;flex-wrap:wrap;">
                        ${i.map(l=>`
                        <button class="acc-btn acc-btn--xs" data-advance="${l}" style="background:${me[l]}1a;color:${me[l]};border:1px solid ${me[l]}55;">
                            ⏭️ ${ie[l]}
                        </button>
                        `).join("")}
                        ${e.direction==="inbound"&&["arrived","inspection"].includes(e.status)?`
                        <button class="acc-btn acc-btn--xs" data-action="inspect" style="background:#fef9c3;color:#854d0e;">🔍 ثبت بازرسی</button>`:""}
                    </div>
                </div>
            </div>

            <!-- مشخصات -->
            <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:14px;font-size:12px;">
                ${e.ref_no?`<div><b>مرجع:</b> ${this.escape(e.ref_no)}</div>`:""}
                ${e.warehouse_name?`<div><b>انبار مقصد:</b> ${this.escape(e.warehouse_name)}</div>`:""}
                ${e.from_warehouse_name?`<div><b>انبار مبدأ:</b> ${this.escape(e.from_warehouse_name)}</div>`:""}
                ${e.carrier_full_name?`<div><b>شرکت حمل:</b> ${this.escape(e.carrier_full_name)}</div>`:""}
                ${e.driver_name?`<div><b>راننده:</b> ${this.escape(e.driver_name)}</div>`:""}
                ${e.vehicle_plate?`<div><b>پلاک:</b> <span dir="ltr">${this.escape(e.vehicle_plate)}</span></div>`:""}
                ${e.tracking_code?`<div><b>کد رهگیری:</b> <span dir="ltr">${this.escape(e.tracking_code)}</span></div>`:""}
                ${e.recipient_name?`<div><b>گیرنده:</b> ${this.escape(e.recipient_name)} ${e.recipient_phone?"— "+this.escape(e.recipient_phone):""}</div>`:""}
                ${e.planned_delivery_date?`<div><b>برنامه تحویل:</b> ${e.planned_delivery_date}</div>`:""}
                ${e.actual_delivery_date?`<div style="color:#10b981;"><b>زمان واقعی تحویل:</b> ${e.actual_delivery_date}</div>`:""}
            </div>

            <!-- آیتم‌ها -->
            <div style="margin-bottom:14px;">
                <h4 style="margin:0 0 8px 0;font-size:13px;color:#475569;">📦 آیتم‌های محموله</h4>
                <table class="acc-table" style="font-size:12px;">
                    <thead><tr><th>محصول</th><th>تعداد برنامه</th><th>تحویل</th><th>دریافت</th><th>خسارت</th></tr></thead>
                    <tbody>
                    ${(e.items??[]).map(l=>`<tr>
                        <td>${this.escape(l.product_name)}</td>
                        <td>${this._fmt(l.qty_planned)} ${this.escape(l.unit??"")}</td>
                        <td>${this._fmt(l.qty_shipped)}</td>
                        <td>${this._fmt(l.qty_received)}</td>
                        <td style="color:${parseFloat(l.qty_damaged)>0?"#ef4444":"inherit"};">${this._fmt(l.qty_damaged)}</td>
                    </tr>`).join("")}
                    </tbody>
                </table>
            </div>

            <!-- Timeline -->
            <div style="margin-bottom:14px;">
                <h4 style="margin:0 0 8px 0;font-size:13px;color:#475569;">⏱️ Timeline مراحل</h4>
                <div style="border-right:2px solid #e2e8f0;padding-right:14px;">
                    ${(e.stages??[]).reverse().map(l=>`
                    <div style="position:relative;padding:6px 0;">
                        <div style="position:absolute;right:-20px;top:10px;width:10px;height:10px;background:#3b82f6;border-radius:50%;border:2px solid #fff;box-shadow:0 0 0 1px #3b82f6;"></div>
                        <div style="font-size:12px;font-weight:600;color:#1e293b;">${this.escape(l.title)}</div>
                        <div style="font-size:11px;color:#94a3b8;">${l.created_at} ${l.actor_name?"— "+this.escape(l.actor_name):""}</div>
                        ${l.notes?`<div style="font-size:11px;color:#64748b;margin-top:2px;">${this.escape(l.notes)}</div>`:""}
                    </div>`).join("")||'<div style="color:#94a3b8;font-size:12px;">مرحله‌ای ثبت نشده</div>'}
                </div>
            </div>

            <!-- بازرسی‌ها -->
            ${(e.inspections??[]).length?`
            <div style="margin-bottom:14px;">
                <h4 style="margin:0 0 8px 0;font-size:13px;color:#475569;">🔍 بازرسی‌ها</h4>
                ${e.inspections.map(l=>`
                <div style="background:#fef9c3;border-right:3px solid #eab308;padding:8px 12px;border-radius:6px;margin-bottom:6px;font-size:12px;">
                    <b>امتیاز: ${l.quality_score}/100</b> — ${l.result}
                    ${l.damage_report?"<br>"+this.escape(l.damage_report):""}
                    <div style="font-size:10px;color:#94a3b8;margin-top:3px;">👤 ${this.escape(l.inspector_name)} — ${l.inspection_date}</div>
                </div>
                `).join("")}
            </div>`:""}

            <div class="acc-modal__actions">
                <button class="acc-btn acc-btn--secondary" data-action="close">بستن</button>
            </div>
        </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector("[data-action=close]").addEventListener("click",r),n.addEventListener("click",l=>{l.target===n&&r()}),n.querySelectorAll("[data-advance]").forEach(l=>l.addEventListener("click",async()=>{const c=l.dataset.advance,d=prompt(`یادداشت برای انتقال به «${ie[c]}»:`,"");if(d!==null)try{await this.api.post(`/ship/shipments/${e.id}/advance`,{status:c,notes:d}),this._toast(`✅ منتقل شد به: ${ie[c]}`),r(),this._load()}catch(h){alert("خطا: "+((h==null?void 0:h.message)??""))}}));const o=n.querySelector("[data-action=inspect]");o&&o.addEventListener("click",()=>{r(),this._openInspectModal(e.id)})}_openInspectModal(e){const t=document.createElement("div");t.className="acc-modal-overlay",t.innerHTML=`
        <div class="acc-modal" style="max-width:420px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🔍 ثبت بازرسی محموله</div>
            <form>
                <div class="acc-form-group"><label>امتیاز کیفی (0-100)</label>
                    <input name="quality_score" type="number" min="0" max="100" value="80" required>
                </div>
                <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px;margin:10px 0;">
                    <label style="display:flex;gap:4px;align-items:center;font-size:12px;">
                        <input type="checkbox" name="packaging_ok" value="1" checked> ✅ بسته‌بندی
                    </label>
                    <label style="display:flex;gap:4px;align-items:center;font-size:12px;">
                        <input type="checkbox" name="quantity_ok" value="1" checked> ✅ تعداد
                    </label>
                    <label style="display:flex;gap:4px;align-items:center;font-size:12px;">
                        <input type="checkbox" name="specs_ok" value="1" checked> ✅ مشخصات
                    </label>
                </div>
                <div class="acc-form-group"><label>نتیجه نهایی</label>
                    <select name="result">
                        <option value="accepted">✅ پذیرفته شد</option>
                        <option value="partial">🟡 پذیرش جزئی</option>
                        <option value="rejected">❌ رد شد</option>
                    </select>
                </div>
                <div class="acc-form-group"><label>گزارش خسارت</label>
                    <textarea name="damage_report" rows="2"></textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ثبت بازرسی</button>
                </div>
            </form>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector("[data-action=cancel]").addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries());i.packaging_ok=i.packaging_ok?1:0,i.quantity_ok=i.quantity_ok?1:0,i.specs_ok=i.specs_ok?1:0;try{await this.api.post(`/ship/shipments/${e}/inspect`,i),s(),this._toast("✅ بازرسی ثبت شد"),this._load()}catch(n){alert("خطا: "+((n==null?void 0:n.message)??""))}})}_getNextStages(e,t){const i=e==="outbound"?["pending","preparing","packed","picked_up","in_transit","out_for_delivery","delivered"]:["pending","ordered","preparing","picked_up","in_transit","arrived","inspection","received"],n=i.indexOf(t);if(n<0||n===i.length-1)return[];const r=[i[n+1]];return e==="inbound"&&r.push("cancelled","rejected"),e==="outbound"&&r.push("failed","returned","cancelled"),r}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Number(e??0))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}class uo extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🏢 شرکت‌های حمل</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ شرکت جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/ship/carriers");this._rows=(e==null?void 0:e.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">شرکتی ثبت نشده</div>';return}this.ref("wrap").innerHTML=`
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;">
            ${this._rows.map(e=>`
            <div style="border:1px solid #e2e8f0;border-radius:10px;padding:14px;background:#fff;">
                <div style="font-weight:700;font-size:14px;">🏢 ${this.escape(e.name)}</div>
                ${e.contact_name?`<div style="font-size:12px;color:#475569;margin-top:6px;">👤 ${this.escape(e.contact_name)}</div>`:""}
                ${e.phone?`<div style="font-size:12px;color:#475569;direction:ltr;text-align:right;">📞 ${this.escape(e.phone)}</div>`:""}
                ${e.email?`<div style="font-size:11px;color:#94a3b8;direction:ltr;text-align:right;">${this.escape(e.email)}</div>`:""}
                <div style="font-size:12px;color:#3b82f6;margin-top:8px;font-weight:700;">📦 ${e.shipment_count} محموله</div>
                <div style="display:flex;gap:4px;margin-top:10px;">
                    <button class="acc-btn acc-btn--xs" data-edit="${e.id}">✏️</button>
                    <button class="acc-btn acc-btn--xs" data-loc="${e.id}" data-name="${this.escape(e.name)}" style="background:#dbeafe;color:#1e40af;">📍</button>
                    <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${e.id}">🗑️</button>
                </div>
            </div>`).join("")}
        </div>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(e=>e.addEventListener("click",()=>this._openModal(this._rows.find(t=>t.id==e.dataset.edit)))),this.ref("wrap").querySelectorAll("[data-del]").forEach(e=>e.addEventListener("click",async()=>{if(confirm("حذف؟"))try{await this.api.delete(`/ship/carriers/${e.dataset.del}`),this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}})),this.ref("wrap").querySelectorAll("[data-loc]").forEach(e=>e.addEventListener("click",()=>z.openModal({api:this.api,entityType:"carrier",entityId:parseInt(e.dataset.loc),entityName:e.dataset.name})))}_openModal(e=null){const t=!!e,s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
        <div class="acc-modal" style="max-width:440px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش":"➕ شرکت حمل جدید"}</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد</label><input name="code" value="${this.escape((e==null?void 0:e.code)??"")}"></div>
                    <div class="acc-form-group"><label>نام *</label><input name="name" required value="${this.escape((e==null?void 0:e.name)??"")}"></div>
                </div>
                <div class="acc-form-group"><label>نام رابط</label>
                    <input name="contact_name" value="${this.escape((e==null?void 0:e.contact_name)??"")}">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تلفن</label>
                        <input name="phone" value="${this.escape((e==null?void 0:e.phone)??"")}" dir="ltr">
                    </div>
                    <div class="acc-form-group"><label>ایمیل</label>
                        <input name="email" type="email" value="${this.escape((e==null?void 0:e.email)??"")}" dir="ltr">
                    </div>
                </div>
                <div class="acc-form-group"><label>آدرس</label>
                    <textarea name="address" rows="2">${this.escape((e==null?void 0:e.address)??"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action=cancel]").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries());try{t?await this.api.put(`/ship/carriers/${e.id}`,n):await this.api.post("/ship/carriers",n),a(),this._load()}catch(r){alert("خطا: "+((r==null?void 0:r.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const Mt=[{key:"dashboard",icon:"📊",title:"داشبورد",desc:"آمار و وضعیت",Class:po},{key:"shipments",icon:"🚚",title:"محموله‌ها",desc:"خرید + فروش",Class:ho},{key:"carriers",icon:"🏢",title:"شرکت‌های حمل",desc:"باربری‌ها",Class:uo}];class sa extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="dashboard",this._sections={}}async template(){const t=Mt.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
                <div class="sp-nav-card__desc">${a.desc}</div>
            </div>
        `).join(""),s=Mt.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=Mt.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(sa,"title","حمل و نقل"),E.register("shipping",sa);class fo extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📊 داشبورد اموال</h2>
                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/assets/dashboard");this._render(e)}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(e){this.ref("wrap").innerHTML=`
        <!-- KPI -->
        <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-bottom:16px;">
            <div style="background:linear-gradient(135deg,#3b82f6,#1d4ed8);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">📦 کل اموال</div>
                <div style="font-size:28px;font-weight:700;">${e.total_assets??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#10b981,#059669);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">💰 ارزش دفتری</div>
                <div style="font-size:24px;font-weight:700;">${this._fmt(e.active_value)}</div>
            </div>
            <div style="background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">🔧 در تعمیر</div>
                <div style="font-size:28px;font-weight:700;">${e.in_repair_count??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">📋 درخواست تعمیر باز</div>
                <div style="font-size:28px;font-weight:700;">${e.open_wo_count??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#8b5cf6,#6d28d9);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">📅 نگهداری در راه</div>
                <div style="font-size:28px;font-weight:700;">${e.due_pm_count??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#06b6d4,#0891b2);color:#fff;padding:14px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">💵 هزینه تعمیر (امسال)</div>
                <div style="font-size:22px;font-weight:700;">${this._fmt(e.maintenance_cost_ytd)}</div>
            </div>
        </div>

        <!-- توزیع بر اساس دسته -->
        <div style="background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:14px;">
            <h3 style="margin:0 0 12px 0;font-size:14px;">📊 توزیع بر اساس دسته</h3>
            <table class="acc-table">
                <thead><tr><th>دسته</th><th>تعداد</th><th>ارزش دفتری</th></tr></thead>
                <tbody>
                ${(e.by_category??[]).map(t=>`<tr>
                    <td><b>${t.icon} ${this.escape(t.name)}</b></td>
                    <td><span style="background:#dbeafe;color:#1e40af;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${t.cnt}</span></td>
                    <td><b style="color:#059669;">${this._fmt(t.value)} ﷼</b></td>
                </tr>`).join("")}
                </tbody>
            </table>
        </div>`}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const Rt={active:{label:"فعال",color:"#10b981"},in_repair:{label:"در تعمیر",color:"#f59e0b"},retired:{label:"بازنشسته",color:"#94a3b8"},sold:{label:"فروخته شده",color:"#06b6d4"},damaged:{label:"آسیب‌دیده",color:"#ef4444"}},mo={excellent:"عالی",good:"خوب",fair:"متوسط",poor:"ضعیف",broken:"خراب"};class vo extends x{constructor(e){super(e),this._cats=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📦 اموال</h2>
                <div style="display:flex;gap:8px;flex-wrap:wrap;">
                    <input type="text" data-ref="search" placeholder="🔍 جستجو..." class="acc-input" style="width:200px;">
                    <select data-ref="catFilter" class="acc-input"><option value="">همه دسته‌ها</option></select>
                    <select data-ref="statusFilter" class="acc-input">
                        <option value="">همه وضعیت‌ها</option>
                        ${Object.entries(Rt).map(([e,t])=>`<option value="${e}">${t.label}</option>`).join("")}
                    </select>
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ دارایی جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){try{const e=await this.api.get("/assets/categories");this._cats=(e==null?void 0:e.data)??[];const t=this.ref("catFilter");this._cats.forEach(s=>{const a=document.createElement("option");a.value=s.id,a.textContent=`${s.icon} ${s.name}`,t.appendChild(a)})}catch{}await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal()),this.on(this.ref("search"),"input",()=>{clearTimeout(this._t),this._t=setTimeout(()=>this._load(),300)}),this.on(this.ref("catFilter"),"change",()=>this._load()),this.on(this.ref("statusFilter"),"change",()=>this._load())}async _load(){var i,n,r,o;const e={},t=(n=(i=this.ref("search"))==null?void 0:i.value)==null?void 0:n.trim(),s=(r=this.ref("catFilter"))==null?void 0:r.value,a=(o=this.ref("statusFilter"))==null?void 0:o.value;t&&(e.search=t),s&&(e.category_id=s),a&&(e.status=a),this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const l=await this.api.get("/assets",e);this._rows=(l==null?void 0:l.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">دارایی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:14px;">
            ${this._rows.map(e=>{const t=Rt[e.status]??{label:e.status,color:"#64748b"};return`
                <div style="border:1px solid #e2e8f0;border-radius:10px;padding:14px;background:#fff;">
                    <div style="display:flex;justify-content:space-between;align-items:start;">
                        <div style="flex:1;">
                            <div style="font-size:20px;">${e.category_icon||"📦"}</div>
                            <div style="font-weight:700;font-size:14px;margin-top:4px;">${this.escape(e.name)}</div>
                            <small style="color:#94a3b8;font-family:monospace;">${this.escape(e.asset_code)}</small>
                        </div>
                        <span style="background:${t.color}1a;color:${t.color};padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${t.label}</span>
                    </div>
                    <div style="font-size:12px;color:#64748b;margin-top:8px;line-height:1.6;">
                        ${e.brand?`🏷️ ${this.escape(e.brand)} ${this.escape(e.model||"")}<br>`:""}
                        ${e.serial_no?`🔢 <span dir="ltr">${this.escape(e.serial_no)}</span><br>`:""}
                        ${e.assigned_name?`👤 ${this.escape(e.assigned_name)}<br>`:""}
                        ${parseFloat(e.current_value)>0?`💰 ارزش: <b style="color:#059669;">${this._fmt(e.current_value)} ﷼</b>`:""}
                    </div>
                    <div style="display:flex;gap:4px;margin-top:10px;flex-wrap:wrap;">
                        <button class="acc-btn acc-btn--xs" data-edit="${e.id}">✏️</button>
                        <button class="acc-btn acc-btn--xs" data-loc="${e.id}" data-name="${this.escape(e.name)}" style="background:#dbeafe;color:#1e40af;">📍</button>
                        <button class="acc-btn acc-btn--xs" data-repair="${e.id}" data-name="${this.escape(e.name)}" style="background:#fef3c7;color:#92400e;">🔧 تعمیر</button>
                        <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${e.id}">🗑️</button>
                    </div>
                </div>`}).join("")}
        </div>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(e=>e.addEventListener("click",()=>this._openModal(this._rows.find(t=>t.id==e.dataset.edit)))),this.ref("wrap").querySelectorAll("[data-loc]").forEach(e=>e.addEventListener("click",()=>z.openModal({api:this.api,entityType:"asset",entityId:parseInt(e.dataset.loc),entityName:e.dataset.name}))),this.ref("wrap").querySelectorAll("[data-repair]").forEach(e=>e.addEventListener("click",()=>this._openRepairModal(parseInt(e.dataset.repair),e.dataset.name))),this.ref("wrap").querySelectorAll("[data-del]").forEach(e=>e.addEventListener("click",async()=>{if(confirm("بازنشسته کردن این دارایی؟"))try{await this.api.delete(`/assets/${e.dataset.del}`),this._load()}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}))}_openModal(e=null){const t=!!e,s=this._cats.map(o=>`<option value="${o.id}" ${(e==null?void 0:e.category_id)==o.id?"selected":""}>${o.icon} ${this.escape(o.name)}</option>`).join(""),a=Object.entries(Rt).map(([o,l])=>`<option value="${o}" ${(e==null?void 0:e.status)===o?"selected":""}>${l.label}</option>`).join(""),i=Object.entries(mo).map(([o,l])=>`<option value="${o}" ${(e==null?void 0:e.condition_grade)===o?"selected":""}>${l}</option>`).join(""),n=document.createElement("div");n.className="acc-modal-overlay",n.innerHTML=`
        <div class="acc-modal" style="max-width:640px;max-height:92vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش":"➕ دارایی جدید"}</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد دارایی</label>
                        <input name="asset_code" value="${this.escape((e==null?void 0:e.asset_code)??"")}" placeholder="(خودکار)">
                    </div>
                    <div class="acc-form-group"><label>دسته‌بندی</label>
                        <select name="category_id"><option value="">—</option>${s}</select>
                    </div>
                </div>
                <div class="acc-form-group"><label>نام *</label>
                    <input name="name" required value="${this.escape((e==null?void 0:e.name)??"")}">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>برند</label><input name="brand" value="${this.escape((e==null?void 0:e.brand)??"")}"></div>
                    <div class="acc-form-group"><label>مدل</label><input name="model" value="${this.escape((e==null?void 0:e.model)??"")}"></div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>شماره سریال</label>
                        <input name="serial_no" value="${this.escape((e==null?void 0:e.serial_no)??"")}" dir="ltr">
                    </div>
                    <div class="acc-form-group"><label>پلاک (خودرو)</label>
                        <input name="plate_no" value="${this.escape((e==null?void 0:e.plate_no)??"")}" dir="ltr">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>وضعیت</label><select name="status">${a}</select></div>
                    <div class="acc-form-group"><label>کیفیت</label><select name="condition_grade">${i}</select></div>
                </div>
                <div class="gis-info-divider">خرید</div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>تاریخ خرید</label>
                        <input name="purchase_date" type="date" value="${(e==null?void 0:e.purchase_date)??""}">
                    </div>
                    <div class="acc-form-group"><label>قیمت خرید (﷼)</label>
                        <input name="purchase_price" type="number" min="0" value="${(e==null?void 0:e.purchase_price)??0}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>ارزش فعلی (﷼)</label>
                        <input name="current_value" type="number" min="0" value="${(e==null?void 0:e.current_value)??0}">
                    </div>
                    <div class="acc-form-group"><label>تاریخ سرویس بعدی</label>
                        <input name="next_service_date" type="date" value="${(e==null?void 0:e.next_service_date)??""}">
                    </div>
                </div>
                <div class="gis-info-divider">گارانتی و بیمه</div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>انقضای گارانتی</label>
                        <input name="warranty_expiry" type="date" value="${(e==null?void 0:e.warranty_expiry)??""}">
                    </div>
                    <div class="acc-form-group"><label>انقضای بیمه</label>
                        <input name="insurance_expiry" type="date" value="${(e==null?void 0:e.insurance_expiry)??""}">
                    </div>
                </div>
                <div class="acc-form-group"><label>مسئول/تحویل‌گیرنده</label>
                    <input name="assigned_name" value="${this.escape((e==null?void 0:e.assigned_name)??"")}">
                </div>
                <div class="acc-form-group"><label>توضیحات</label>
                    <textarea name="description" rows="2">${this.escape((e==null?void 0:e.description)??"")}</textarea>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(n);const r=()=>n.remove();n.querySelector(".acc-modal__close").addEventListener("click",r),n.querySelector("[data-action=cancel]").addEventListener("click",r),n.addEventListener("click",o=>{o.target===n&&r()}),n.querySelector("form").addEventListener("submit",async o=>{o.preventDefault();const l=Object.fromEntries(new FormData(o.target).entries());try{t?await this.api.put(`/assets/${e.id}`,l):await this.api.post("/assets",l),r(),this._load()}catch(c){alert("خطا: "+((c==null?void 0:c.message)??""))}})}_openRepairModal(e,t){const s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
        <div class="acc-modal" style="max-width:440px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🔧 درخواست تعمیر — ${this.escape(t)}</div>
            <form>
                <div class="acc-form-group"><label>عنوان مشکل *</label>
                    <input name="title" required placeholder="مثلاً: صدای غیرعادی موتور">
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>نوع</label>
                        <select name="type">
                            <option value="corrective">🔧 اصلاحی (خرابی)</option>
                            <option value="preventive">📅 پیشگیرانه</option>
                            <option value="inspection">🔍 بازرسی</option>
                            <option value="emergency">🚨 اضطراری</option>
                        </select>
                    </div>
                    <div class="acc-form-group"><label>اولویت</label>
                        <select name="priority">
                            <option value="low">پایین</option>
                            <option value="medium" selected>متوسط</option>
                            <option value="high">بالا</option>
                            <option value="urgent">فوری</option>
                        </select>
                    </div>
                </div>
                <div class="acc-form-group"><label>توضیح مشکل</label>
                    <textarea name="problem_desc" rows="3"></textarea>
                </div>
                <div class="acc-form-group"><label>تخصیص به</label>
                    <input name="assigned_name" placeholder="نام تعمیرکار/پیمانکار">
                </div>
                <div class="acc-form-group"><label>تاریخ موعد</label>
                    <input name="due_date" type="date">
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ایجاد درخواست</button>
                </div>
            </form>
        </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action=cancel]").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries());n.asset_id=e;try{const r=await this.api.post("/assets/work-orders",n);a(),alert(`✅ درخواست تعمیر ${r==null?void 0:r.wo_no} ایجاد شد`),this._load()}catch(r){alert("خطا: "+((r==null?void 0:r.message)??""))}})}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}class bo extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🗂️ دسته‌بندی اموال</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ دسته جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/assets/categories");this._rows=(e==null?void 0:e.data)??[],this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">دسته‌ای ثبت نشده</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr><th>کد</th><th>نام</th><th>عمر مفید (سال)</th><th>ارزش اسقاط (٪)</th><th>تعداد دارایی</th><th>اقدام</th></tr></thead>
            <tbody>
            ${this._rows.map(e=>`<tr>
                <td><small style="font-family:monospace;">${this.escape(e.code)}</small></td>
                <td><b>${e.icon} ${this.escape(e.name)}</b></td>
                <td><b style="color:#3b82f6;">${e.useful_years}</b> سال</td>
                <td>${e.salvage_pct}٪</td>
                <td><span style="background:#dbeafe;color:#1e40af;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${e.asset_count}</span></td>
                <td><button class="acc-btn acc-btn--xs" data-edit="${e.id}">✏️</button></td>
            </tr>`).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(e=>e.addEventListener("click",()=>this._openModal(this._rows.find(t=>t.id==e.dataset.edit))))}_openModal(e=null){const t=!!e,s=document.createElement("div");s.className="acc-modal-overlay",s.innerHTML=`
        <div class="acc-modal" style="max-width:440px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش":"➕ دسته جدید"}</div>
            <form>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>کد</label><input name="code" value="${this.escape((e==null?void 0:e.code)??"")}"></div>
                    <div class="acc-form-group"><label>نام *</label><input name="name" required value="${this.escape((e==null?void 0:e.name)??"")}"></div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>آیکن</label><input name="icon" value="${this.escape((e==null?void 0:e.icon)??"📦")}"></div>
                    <div class="acc-form-group"><label>روش استهلاک</label>
                        <select name="depr_method">
                            <option value="straight_line" ${(e==null?void 0:e.depr_method)==="straight_line"?"selected":""}>خط مستقیم</option>
                            <option value="declining" ${(e==null?void 0:e.depr_method)==="declining"?"selected":""}>کاهنده</option>
                            <option value="none" ${(e==null?void 0:e.depr_method)==="none"?"selected":""}>بدون استهلاک</option>
                        </select>
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>عمر مفید (سال)</label>
                        <input name="useful_years" type="number" min="1" max="100" value="${(e==null?void 0:e.useful_years)??5}">
                    </div>
                    <div class="acc-form-group"><label>ارزش اسقاط (٪)</label>
                        <input name="salvage_pct" type="number" min="0" max="100" step="0.1" value="${(e==null?void 0:e.salvage_pct)??0}">
                    </div>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(s);const a=()=>s.remove();s.querySelector(".acc-modal__close").addEventListener("click",a),s.querySelector("[data-action=cancel]").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s.querySelector("form").addEventListener("submit",async i=>{i.preventDefault();const n=Object.fromEntries(new FormData(i.target).entries());try{t?await this.api.put(`/assets/categories/${e.id}`,n):await this.api.post("/assets/categories",n),a(),this._load()}catch(r){alert("خطا: "+((r==null?void 0:r.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const Ve={open:{label:"باز",color:"#3b82f6"},in_progress:{label:"در حال انجام",color:"#f59e0b"},waiting:{label:"منتظر قطعه",color:"#8b5cf6"},closed:{label:"بسته شده",color:"#10b981"},cancelled:{label:"لغو شده",color:"#94a3b8"}},qt={corrective:"🔧 اصلاحی",preventive:"📅 پیشگیرانه",inspection:"🔍 بازرسی",emergency:"🚨 اضطراری"},go={low:{label:"پایین",color:"#94a3b8"},medium:{label:"متوسط",color:"#3b82f6"},high:{label:"بالا",color:"#f59e0b"},urgent:{label:"فوری",color:"#ef4444"}};class yo extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🔧 درخواست‌های تعمیر</h2>
                <div style="display:flex;gap:8px;">
                    <select data-ref="statusFilter" class="acc-input">
                        <option value="">همه وضعیت‌ها</option>
                        ${Object.entries(Ve).map(([e,t])=>`<option value="${e}">${t.label}</option>`).join("")}
                    </select>
                    <select data-ref="typeFilter" class="acc-input">
                        <option value="">همه نوع‌ها</option>
                        ${Object.entries(qt).map(([e,t])=>`<option value="${e}">${t}</option>`).join("")}
                    </select>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("statusFilter"),"change",()=>this._load()),this.on(this.ref("typeFilter"),"change",()=>this._load())}async _load(){var a,i;const e={},t=(a=this.ref("statusFilter"))==null?void 0:a.value,s=(i=this.ref("typeFilter"))==null?void 0:i.value;t&&(e.status=t),s&&(e.type=s),this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const n=await this.api.get("/assets/work-orders",e);this._render((n==null?void 0:n.data)??[])}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(e){if(!e.length){this.ref("wrap").innerHTML='<div class="acc-empty">درخواست تعمیری یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>شماره</th><th>دارایی</th><th>عنوان</th><th>نوع</th>
                <th>اولویت</th><th>وضعیت</th><th>تخصیص</th><th>هزینه</th><th>اقدام</th>
            </tr></thead>
            <tbody>
            ${e.map(t=>{const s=Ve[t.status]??{label:t.status,color:"#64748b"},a=go[t.priority]??{label:t.priority,color:"#64748b"};return`<tr>
                    <td><b style="font-family:monospace;">${this.escape(t.wo_no)}</b></td>
                    <td>
                        <div>${this.escape(t.asset_name??"—")}</div>
                        <small style="color:#94a3b8;">${this.escape(t.asset_code??"")}</small>
                    </td>
                    <td>${this.escape(t.title)}</td>
                    <td><small>${qt[t.type]??t.type}</small></td>
                    <td><span style="background:${a.color}1a;color:${a.color};padding:1px 8px;border-radius:8px;font-size:11px;font-weight:700;">${a.label}</span></td>
                    <td><span style="background:${s.color}1a;color:${s.color};padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${s.label}</span></td>
                    <td><small>${this.escape(t.assigned_name??"—")}</small></td>
                    <td>${parseFloat(t.total_cost)>0?"<b>"+this._fmt(t.total_cost)+"</b>":"—"}</td>
                    <td><button class="acc-btn acc-btn--xs acc-btn--primary" data-view="${t.id}">👁️ مدیریت</button></td>
                </tr>`}).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-view]").forEach(t=>t.addEventListener("click",()=>this._viewWo(parseInt(t.dataset.view))))}async _viewWo(e){try{const t=await this.api.get(`/assets/work-orders/${e}`);this._renderWoModal(t==null?void 0:t.data)}catch(t){alert("خطا: "+((t==null?void 0:t.message)??""))}}_renderWoModal(e){const t=Ve[e.status]??{label:e.status,color:"#64748b"},s=e.items??[];s.reduce((l,c)=>l+parseFloat(c.total_cost),0);const a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
        <div class="acc-modal" style="max-width:680px;max-height:92vh;overflow-y:auto;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">🔧 ${this.escape(e.wo_no)}</div>

            <div style="background:${t.color}1a;border-right:4px solid ${t.color};padding:10px;border-radius:6px;margin-bottom:14px;">
                <div style="font-weight:700;color:${t.color};">${t.label}</div>
                <div style="font-size:12px;color:#64748b;margin-top:4px;">${qt[e.type]??e.type}</div>
            </div>

            <h4 style="margin:0 0 6px 0;font-size:13px;">📦 دارایی: ${this.escape(e.asset_name)}</h4>
            <div style="font-size:12px;color:#64748b;margin-bottom:14px;"><b>عنوان:</b> ${this.escape(e.title)}</div>

            <form id="wo-form">
                <div class="acc-form-group"><label>توضیح مشکل</label>
                    <textarea name="problem_desc" rows="2">${this.escape(e.problem_desc??"")}</textarea>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>وضعیت</label>
                        <select name="status">
                            ${Object.entries(Ve).map(([l,c])=>`<option value="${l}" ${e.status===l?"selected":""}>${c.label}</option>`).join("")}
                        </select>
                    </div>
                    <div class="acc-form-group"><label>تخصیص به</label>
                        <input name="assigned_name" value="${this.escape(e.assigned_name??"")}">
                    </div>
                </div>

                <h4 style="margin:12px 0 6px 0;font-size:13px;">📦 قطعات/کار:</h4>
                <div id="wo-items">
                    ${s.map((l,c)=>this._renderItemRow(l,c)).join("")||'<div style="color:#94a3b8;font-size:12px;">ردیفی نیست</div>'}
                </div>
                <button type="button" class="acc-btn acc-btn--xs" id="wo-add-item">➕ افزودن ردیف</button>

                <div class="doc-form-row" style="margin-top:14px;">
                    <div class="acc-form-group"><label>هزینه دستمزد (﷼)</label>
                        <input name="labor_cost" type="number" value="${e.labor_cost??0}">
                    </div>
                    <div class="acc-form-group"><label>زمان توقف (ساعت)</label>
                        <input name="downtime_hours" type="number" step="0.1" value="${e.downtime_hours??0}">
                    </div>
                </div>

                <div class="acc-form-group"><label>توضیح راه‌حل</label>
                    <textarea name="solution_desc" rows="2">${this.escape(e.solution_desc??"")}</textarea>
                </div>

                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="button" class="acc-btn acc-btn--primary" data-action="save">💾 ذخیره</button>
                    ${e.status!=="closed"?'<button type="button" class="acc-btn acc-btn--success" data-action="complete">✅ تکمیل و بستن</button>':""}
                </div>
            </form>
        </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action=cancel]").addEventListener("click",i),a.addEventListener("click",l=>{l.target===a&&i()});let n=s.length;a.querySelector("#wo-add-item").addEventListener("click",()=>{const l=document.createElement("div");l.innerHTML=this._renderItemRow({},n++),a.querySelector("#wo-items").appendChild(l.firstElementChild)});const r=()=>{const l=new FormData(a.querySelector("#wo-form")),c=Object.fromEntries(l.entries());return c.items=[],a.querySelectorAll(".wo-item").forEach(d=>{var m,b,v;const h=(m=d.querySelector("[name='item_desc']"))==null?void 0:m.value,u=parseFloat(((b=d.querySelector("[name='item_qty']"))==null?void 0:b.value)??0),f=parseFloat(((v=d.querySelector("[name='item_cost']"))==null?void 0:v.value)??0);h&&u>0&&c.items.push({description:h,qty:u,unit_cost:f,item_type:"part"})}),c};a.querySelector("[data-action=save]").addEventListener("click",async()=>{try{await this.api.put(`/assets/work-orders/${e.id}`,r()),i(),this._load()}catch(l){alert("خطا: "+((l==null?void 0:l.message)??""))}});const o=a.querySelector("[data-action=complete]");o&&o.addEventListener("click",async()=>{await this.api.put(`/assets/work-orders/${e.id}`,r());const l=r();try{await this.api.post(`/assets/work-orders/${e.id}/complete`,{solution_desc:l.solution_desc,labor_cost:l.labor_cost}),i(),this._load(),alert("✅ درخواست تعمیر تکمیل شد")}catch(c){alert("خطا: "+((c==null?void 0:c.message)??""))}})}_renderItemRow(e,t){return`
        <div class="wo-item" style="display:grid;grid-template-columns:2fr 1fr 1fr auto;gap:6px;margin-bottom:4px;">
            <input name="item_desc" placeholder="شرح قطعه/کار" value="${this.escape(e.description??"")}" class="acc-input">
            <input name="item_qty"  type="number" placeholder="تعداد" value="${e.qty??1}" class="acc-input">
            <input name="item_cost" type="number" placeholder="قیمت واحد" value="${e.unit_cost??0}" class="acc-input">
            <button type="button" class="acc-btn acc-btn--xs gis-btn--danger" onclick="this.parentElement.remove()">✕</button>
        </div>`}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const aa={low:{label:"پایین",color:"#94a3b8"},medium:{label:"متوسط",color:"#3b82f6"},high:{label:"بالا",color:"#f59e0b"},urgent:{label:"فوری",color:"#ef4444"}};class _o extends x{constructor(e){super(e),this._assets=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📅 نگهداری پیشگیرانه</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--warning" data-ref="dueBtn">⏰ سررسید نزدیک</button>
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ برنامه جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){try{const e=await this.api.get("/assets");this._assets=(e==null?void 0:e.data)??[]}catch{}await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openModal()),this.on(this.ref("dueBtn"),"click",()=>this._loadDue())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/assets/pm-schedules");this._render((e==null?void 0:e.data)??[])}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}async _loadDue(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری سررسیدها...</div>';try{const e=await this.api.get("/assets/pm-schedules/due",{days:30});this._render((e==null?void 0:e.data)??[],!0)}catch{}}_render(e,t=!1){if(!e.length){this.ref("wrap").innerHTML=`<div class="acc-empty">${t?"✅ سررسید در راه نیست":"برنامه‌ای ثبت نشده"}</div>`;return}this.ref("wrap").innerHTML=`
        ${t?`<div style="background:#fef9c3;padding:10px;border-radius:6px;color:#854d0e;margin-bottom:10px;">⏰ ${e.length} برنامه نگهداری در ۳۰ روز آینده</div>`:""}
        <table class="acc-table">
            <thead><tr>
                <th>دارایی</th><th>عنوان</th><th>فاصله</th><th>آخرین انجام</th><th>سررسید بعدی</th>
                ${t?"<th>روز باقیمانده</th>":""}
                <th>اولویت</th><th>اقدام</th>
            </tr></thead>
            <tbody>
            ${e.map(s=>{const a=aa[s.priority]??{label:s.priority,color:"#64748b"},i=s.days_left!==void 0?parseInt(s.days_left):null,n=i!==null&&i<=0;return`<tr ${n?'style="background:#fef2f2;"':""}>
                    <td><b>${this.escape(s.asset_name??"—")}</b><br><small style="color:#94a3b8;">${this.escape(s.asset_code??"")}</small></td>
                    <td>${this.escape(s.title)}</td>
                    <td><b>${s.interval_days}</b> روز</td>
                    <td>${s.last_done_date??"—"}</td>
                    <td style="color:${n?"#ef4444":"inherit"};font-weight:700;">${s.next_due_date??"—"}</td>
                    ${t?`<td style="color:${i<=7?"#ef4444":"#f59e0b"};font-weight:700;">${i<=0?"گذشته":i+" روز"}</td>`:""}
                    <td><span style="background:${a.color}1a;color:${a.color};padding:1px 8px;border-radius:8px;font-size:11px;font-weight:700;">${a.label}</span></td>
                    <td style="display:flex;gap:4px;">
                        <button class="acc-btn acc-btn--xs" data-edit="${s.id}">✏️</button>
                        <button class="acc-btn acc-btn--xs" data-wo="${s.id}" data-asset="${s.asset_id}" data-title="${this.escape(s.title)}" style="background:#fef3c7;color:#92400e;">🔧 ساخت WO</button>
                        <button class="acc-btn acc-btn--xs gis-btn--danger" data-del="${s.id}">🗑️</button>
                    </td>
                </tr>`}).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(s=>s.addEventListener("click",async()=>{const a=await this.api.get("/assets/pm-schedules"),i=((a==null?void 0:a.data)??[]).find(n=>n.id==s.dataset.edit);i&&this._openModal(i)})),this.ref("wrap").querySelectorAll("[data-del]").forEach(s=>s.addEventListener("click",async()=>{if(confirm("حذف این برنامه؟"))try{await this.api.delete(`/assets/pm-schedules/${s.dataset.del}`),this._load()}catch(a){alert("خطا: "+((a==null?void 0:a.message)??""))}})),this.ref("wrap").querySelectorAll("[data-wo]").forEach(s=>s.addEventListener("click",async()=>{try{await this.api.post("/assets/work-orders",{asset_id:parseInt(s.dataset.asset),title:s.dataset.title,type:"preventive",priority:"medium",pm_schedule_id:parseInt(s.dataset.wo)}),alert("✅ درخواست تعمیر ایجاد شد")}catch(a){alert("خطا: "+((a==null?void 0:a.message)??""))}}))}_openModal(e=null){const t=!!e,s=this._assets.map(n=>`<option value="${n.id}" ${(e==null?void 0:e.asset_id)==n.id?"selected":""}>${this.escape(n.name)} [${this.escape(n.asset_code)}]</option>`).join(""),a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
        <div class="acc-modal" style="max-width:440px;">
            <button class="acc-modal__close">✕</button>
            <div class="acc-modal__title">${t?"✏️ ویرایش":"➕ برنامه نگهداری جدید"}</div>
            <form>
                <div class="acc-form-group"><label>دارایی *</label>
                    <select name="asset_id" required>${s||"<option>—</option>"}</select>
                </div>
                <div class="acc-form-group"><label>عنوان *</label>
                    <input name="title" required value="${this.escape((e==null?void 0:e.title)??"")}" placeholder="مثلاً: تعویض روغن">
                </div>
                <div class="acc-form-group"><label>توضیحات</label>
                    <textarea name="description" rows="2">${this.escape((e==null?void 0:e.description)??"")}</textarea>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>فاصله (روز) *</label>
                        <input name="interval_days" type="number" min="1" required value="${(e==null?void 0:e.interval_days)??90}">
                    </div>
                    <div class="acc-form-group"><label>هزینه تخمینی (﷼)</label>
                        <input name="estimated_cost" type="number" min="0" value="${(e==null?void 0:e.estimated_cost)??0}">
                    </div>
                </div>
                <div class="doc-form-row">
                    <div class="acc-form-group"><label>آخرین انجام</label>
                        <input name="last_done_date" type="date" value="${(e==null?void 0:e.last_done_date)??""}">
                    </div>
                    <div class="acc-form-group"><label>اولویت</label>
                        <select name="priority">
                            ${Object.entries(aa).map(([n,r])=>`<option value="${n}" ${(e==null?void 0:e.priority)===n?"selected":""}>${r.label}</option>`).join("")}
                        </select>
                    </div>
                </div>
                <div class="acc-modal__actions">
                    <button type="button" class="acc-btn acc-btn--secondary" data-action="cancel">انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action=cancel]").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()}),a.querySelector("form").addEventListener("submit",async n=>{n.preventDefault();const r=Object.fromEntries(new FormData(n.target).entries());try{t?await this.api.put(`/assets/pm-schedules/${e.id}`,r):await this.api.post("/assets/pm-schedules",r),i(),this._load()}catch(o){alert("خطا: "+((o==null?void 0:o.message)??""))}})}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}class xo extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📉 استهلاک</h2>
            </div>

            <!-- اجرا -->
            <div style="background:#eff6ff;padding:14px;border-radius:8px;margin-bottom:14px;border:1px solid #bfdbfe;">
                <h3 style="margin:0 0 10px 0;font-size:14px;color:#1e40af;">⚙️ اجرای استهلاک ماهانه</h3>
                <div style="display:flex;gap:10px;align-items:end;flex-wrap:wrap;">
                    <div class="acc-form-group" style="margin:0;">
                        <label style="font-size:11px;">سال میلادی</label>
                        <input data-ref="year" type="number" class="acc-input" value="${new Date().getFullYear()}" min="2020" max="2100">
                    </div>
                    <div class="acc-form-group" style="margin:0;">
                        <label style="font-size:11px;">ماه</label>
                        <select data-ref="month" class="acc-input">
                            ${[1,2,3,4,5,6,7,8,9,10,11,12].map(e=>`<option value="${e}" ${e===new Date().getMonth()+1?"selected":""}>${e}</option>`).join("")}
                        </select>
                    </div>
                    <button class="acc-btn acc-btn--primary" data-ref="runBtn">▶️ اجرای استهلاک</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
                <small style="color:#64748b;font-size:11px;">💡 استهلاک بر اساس روش هر دسته‌بندی محاسبه می‌شود</small>
            </div>

            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری اموال...</div></div>
        </div>`}async afterRender(){await this._loadAssets(),this.on(this.ref("runBtn"),"click",()=>this._run()),this.on(this.ref("refreshBtn"),"click",()=>this._loadAssets())}async _loadAssets(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const e=await this.api.get("/assets",{status:"active"});this._render((e==null?void 0:e.data)??[])}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا</div>'}}_render(e){if(!e.length){this.ref("wrap").innerHTML='<div class="acc-empty">دارایی فعالی نیست</div>';return}const t=e.reduce((i,n)=>i+parseFloat(n.purchase_price),0),s=e.reduce((i,n)=>i+parseFloat(n.current_value),0),a=t-s;this.ref("wrap").innerHTML=`
        <div style="background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:14px;margin-bottom:14px;">
            <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:12px;">
                <div>
                    <div style="font-size:11px;color:#64748b;">قیمت کل خرید</div>
                    <div style="font-size:18px;font-weight:700;color:#3b82f6;">${this._fmt(t)} ﷼</div>
                </div>
                <div>
                    <div style="font-size:11px;color:#64748b;">ارزش دفتری فعلی</div>
                    <div style="font-size:18px;font-weight:700;color:#10b981;">${this._fmt(s)} ﷼</div>
                </div>
                <div>
                    <div style="font-size:11px;color:#64748b;">استهلاک تجمعی</div>
                    <div style="font-size:18px;font-weight:700;color:#ef4444;">${this._fmt(a)} ﷼</div>
                </div>
            </div>
        </div>

        <table class="acc-table">
            <thead><tr><th>دارایی</th><th>تاریخ خرید</th><th>قیمت خرید</th><th>ارزش فعلی</th><th>استهلاک</th><th>%</th></tr></thead>
            <tbody>
            ${e.map(i=>{const n=parseFloat(i.purchase_price)-parseFloat(i.current_value),r=parseFloat(i.purchase_price)>0?n/parseFloat(i.purchase_price)*100:0;return`<tr>
                    <td>
                        <b>${this.escape(i.name)}</b>
                        <br><small style="color:#94a3b8;">${this.escape(i.asset_code)} | ${i.category_icon||""} ${this.escape(i.category_name??"")}</small>
                    </td>
                    <td>${i.purchase_date??"—"}</td>
                    <td>${this._fmt(i.purchase_price)}</td>
                    <td><b style="color:#10b981;">${this._fmt(i.current_value)}</b></td>
                    <td><b style="color:#ef4444;">${this._fmt(n)}</b></td>
                    <td>
                        <div style="display:flex;align-items:center;gap:6px;">
                            <div style="flex:1;height:6px;background:#e2e8f0;border-radius:3px;overflow:hidden;">
                                <div style="height:100%;width:${Math.min(100,r)}%;background:#ef4444;"></div>
                            </div>
                            <small>${r.toFixed(1)}٪</small>
                        </div>
                    </td>
                </tr>`}).join("")}
            </tbody>
        </table>`}async _run(){var a,i;const e=parseInt(((a=this.ref("year"))==null?void 0:a.value)??new Date().getFullYear()),t=parseInt(((i=this.ref("month"))==null?void 0:i.value)??new Date().getMonth()+1);if(!confirm(`اجرای استهلاک برای ماه ${t}/${e}؟`))return;const s=this.ref("runBtn");s.disabled=!0,s.textContent="⏳ در حال اجرا...";try{const n=await this.api.post("/assets/depreciation/run",{year:e,month:t});alert(`✅ استهلاک برای ${n==null?void 0:n.processed} دارایی محاسبه شد`),this._loadAssets()}catch(n){alert("خطا: "+((n==null?void 0:n.message)??""))}finally{s.disabled=!1,s.textContent="▶️ اجرای استهلاک"}}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const Ht=[{key:"dashboard",icon:"📊",title:"داشبورد",desc:"آمار کلی",Class:fo},{key:"assets",icon:"📦",title:"اموال",desc:"لیست + مدیریت",Class:vo},{key:"categories",icon:"🗂️",title:"دسته‌بندی",desc:"درختی + استهلاک",Class:bo},{key:"workorders",icon:"🔧",title:"تعمیرات",desc:"درخواست کار",Class:yo},{key:"pm",icon:"📅",title:"نگهداری",desc:"پیشگیرانه",Class:_o},{key:"depreciation",icon:"📉",title:"استهلاک",desc:"اجرا و گزارش",Class:xo}];class ia extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="dashboard",this._sections={}}async template(){const t=Ht.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
                <div class="sp-nav-card__desc">${a.desc}</div>
            </div>
        `).join(""),s=Ht.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=Ht.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(ia,"title","مدیریت اموال"),E.register("assets",ia);const na={1:{label:"جریمه",color:"#f59e0b",icon:"💰"},3:{label:"تخریب / قلع بنا",color:"#ef4444",icon:"🔨"},4:{label:"سایر",color:"#64748b",icon:"📋"},8:{label:"برائت",color:"#10b981",icon:"✅"},9:{label:"منتفی",color:"#94a3b8",icon:"➖"},12:{label:"اعاده به حالت اولیه",color:"#dc2626",icon:"↩️"}},wo={1:"بدوی",2:"تجدیدنظر",4:"اصلاحی"},$o={جريمه:{color:"#f59e0b"},جریمه:{color:"#f59e0b"},تخريب:{color:"#ef4444"},تخریب:{color:"#ef4444"},برائت:{color:"#10b981"},منتفی:{color:"#94a3b8"},منتفي:{color:"#94a3b8"},ساير:{color:"#64748b"},سایر:{color:"#64748b"},"اعاده به حالت اولیه":{color:"#dc2626"}};class ko extends x{constructor(e={}){super(e),this._initialCode=e.initialCode??null,this._currentCode=null,this._data=null}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🔨 کمیسیون ماده ۱۰۰</h2>
                <div style="display:flex;gap:8px;align-items:center;">
                    <input type="text" data-ref="codeInput"
                           placeholder="کد نوسازی... مثلاً 10-76-363-21-1-0-0"
                           class="acc-input"
                           dir="ltr"
                           style="width:280px;text-align:center;font-family:monospace;">
                    <button class="acc-btn acc-btn--primary" data-ref="searchBtn">🔍 جستجو</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-empty">کد نوسازی را وارد کنید</div></div>
        </div>`}async afterRender(){this.on(this.ref("searchBtn"),"click",()=>this._load()),this.on(this.ref("refreshBtn"),"click",()=>this._load(!0)),this.on(this.ref("codeInput"),"keydown",e=>{e.key==="Enter"&&(e.preventDefault(),this._load())}),this._initialCode&&(this.ref("codeInput").value=this._initialCode,await this._load())}async _load(e=!1){var s,a;const t=(a=(s=this.ref("codeInput"))==null?void 0:s.value)==null?void 0:a.trim();if(!t){this._toast("کد را وارد کنید","#f59e0b");return}this._currentCode=t,this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری پرونده‌ها...</div>';try{const i=await this.api.get("/commission/by-code",{code:t});this._data=i,this._render()}catch{this.ref("wrap").innerHTML='<div class="acc-error">❌ خطا در بارگذاری</div>'}}_render(){var t;const e=this._data;if(!((t=e==null?void 0:e.files)!=null&&t.length)){this.ref("wrap").innerHTML=`
            <div class="acc-empty" style="padding:40px;text-align:center;">
                <div style="font-size:48px;">📭</div>
                <div style="margin-top:8px;">پرونده‌ای برای کد <b>${this.escape(e==null?void 0:e.code)}</b> یافت نشد</div>
            </div>`;return}this.ref("wrap").innerHTML=`
        ${this._renderSummary(e)}
        ${this._renderTimeline(e.files)}
        ${this._renderFiles(e.files)}
        `,this.ref("wrap").querySelectorAll("[data-vote-id]").forEach(s=>s.addEventListener("click",()=>this._showVoteDetail(s.dataset.voteId)))}_renderSummary(e){const t=e.summary??{};return`
        <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin-bottom:14px;">
            <div style="background:linear-gradient(135deg,#3b82f6,#1d4ed8);color:#fff;padding:12px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">📁 پرونده‌ها</div>
                <div style="font-size:24px;font-weight:700;">${t.files_count??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#ef4444,#dc2626);color:#fff;padding:12px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">⚠️ تخلفات</div>
                <div style="font-size:24px;font-weight:700;">${t.trepass_count??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#8b5cf6,#6d28d9);color:#fff;padding:12px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">⚖️ رأی‌ها</div>
                <div style="font-size:24px;font-weight:700;">${t.votes_count??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#f59e0b,#d97706);color:#fff;padding:12px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">📋 خلاصه</div>
                <div style="font-size:24px;font-weight:700;">${t.summary_count??0}</div>
            </div>
            <div style="background:linear-gradient(135deg,#10b981,#059669);color:#fff;padding:12px;border-radius:10px;">
                <div style="font-size:11px;opacity:.85;">💰 جمع جریمه</div>
                <div style="font-size:16px;font-weight:700;">${this._fmt(t.total_penalty)} ﷼</div>
            </div>
            ${t.first_date?`
            <div style="background:#fff;border:1px solid #e2e8f0;padding:12px;border-radius:10px;">
                <div style="font-size:11px;color:#64748b;">📅 بازه</div>
                <div style="font-size:12px;font-weight:700;color:#475569;margin-top:4px;">از ${t.first_date}</div>
                <div style="font-size:12px;font-weight:700;color:#475569;">تا ${t.last_date}</div>
            </div>`:""}
        </div>`}_renderTimeline(e){const t=[];return e.forEach(s=>{s.UrbanRequestDate&&t.push({date:s.UrbanRequestDate,type:"request",file:s,label:`📥 درخواست پرونده #${s.UrbanNidKartablItem??"—"}`}),s.CommissionDate&&t.push({date:s.CommissionDate,type:"commission",file:s,label:`🏛️ کمیسیون پرونده #${s.UrbanNidKartablItem??"—"}`}),(s.votes??[]).forEach(a=>{const i=na[a.CI_VoteType]??{label:"سایر",color:"#64748b",icon:"📋"};t.push({date:a.VoteDate,type:"vote",file:s,vote:a,label:`${i.icon} رأی ${i.label} ${a.VoteValue>0?"— "+this._fmt(a.VoteValue)+" ﷼":""}`,color:i.color})})}),t.sort((s,a)=>(s.date??"").localeCompare(a.date??"")),t.length?`
        <details style="margin-bottom:14px;background:#fff;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;">
            <summary style="padding:10px 14px;cursor:pointer;font-weight:700;background:#f8fafc;">
                ⏱️ Timeline رویدادها (${t.length})
            </summary>
            <div style="padding:14px;">
                <div style="border-right:2px solid #cbd5e1;padding-right:14px;">
                    ${t.map(s=>`
                    <div style="position:relative;padding:6px 0;">
                        <div style="position:absolute;right:-21px;top:10px;width:12px;height:12px;background:${s.color??"#3b82f6"};border-radius:50%;border:2px solid #fff;box-shadow:0 0 0 1px ${s.color??"#3b82f6"};"></div>
                        <div style="font-size:12px;font-weight:600;color:#1e293b;">${s.label}</div>
                        <div style="font-size:11px;color:#94a3b8;">${s.date??""}</div>
                    </div>`).join("")}
                </div>
            </div>
        </details>`:""}_renderFiles(e){return e.map((t,s)=>this._renderFile(t,s)).join("")}_renderFile(e,t){const s=wo[e.CI_Commission]??`نوع ${e.CI_Commission??"—"}`,a=e.IsRun==1?"#10b981":e.votes.length?"#3b82f6":"#f59e0b";return`
        <details ${t===0?"open":""} style="margin-bottom:10px;background:#fff;border:1.5px solid ${a};border-radius:10px;overflow:hidden;">
            <summary style="padding:12px 14px;cursor:pointer;background:${a}1a;">
                <div style="display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:6px;">
                    <div>
                        <b style="font-size:14px;color:${a};">📁 پرونده #${this.escape(e.UrbanNidKartablItem??"—")}</b>
                        <small style="color:#64748b;margin-right:8px;">${s}</small>
                    </div>
                    <div style="display:flex;gap:6px;flex-wrap:wrap;align-items:center;">
                        <span style="background:${a};color:#fff;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${this.escape(e.status_label)}</span>
                        ${e.total_penalty>0?`<span style="background:#fef3c7;color:#92400e;padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">💰 ${this._fmt(e.total_penalty)} ﷼</span>`:""}
                    </div>
                </div>
                <div style="margin-top:6px;font-size:12px;color:#64748b;">
                    👤 ${this.escape(e.OwnerName??"—")}
                    ${e.Regplaque?` | پلاک ثبتی: ${this.escape(e.Regplaque)}`:""}
                    ${e.CommissionDate?` | 📅 ${e.CommissionDate}`:""}
                </div>
                ${e.Address?`<div style="margin-top:4px;font-size:12px;color:#475569;">📍 ${this.escape(e.Address)}</div>`:""}
            </summary>

            <div style="padding:14px;">
                ${this._renderFileMeta(e)}
                ${this._renderTrepassList(e.trepasses)}
                ${this._renderVoteList(e.votes,e.trepasses)}
                ${this._renderSummaryRows(e.summary_rows)}
                ${this._renderAdminInfo(e)}
            </div>
        </details>`}_renderTrepassList(e){return e!=null&&e.length?`
        <h4 style="margin:8px 0 6px 0;font-size:13px;color:#475569;">⚠️ تخلفات (${e.length})</h4>
        <div style="display:flex;flex-direction:column;gap:4px;">
        ${e.map(t=>{const s=parseFloat(t.MaxPenalty)||0;return`
            <div style="background:#fef3c7;border-right:3px solid #f59e0b;padding:8px 12px;border-radius:6px;font-size:12px;">
                <div style="display:flex;justify-content:space-between;align-items:start;gap:8px;flex-wrap:wrap;">
                    <div style="flex:1;min-width:0;">
                        <b>${this.escape(t.Title??"—")}</b>
                        ${t.TrepassValue?`<span style="color:#7c2d12;margin-right:6px;">— ${t.TrepassValue} م²</span>`:""}
                        ${t.Floor!=null&&t.Floor!==""?`<small style="color:#92400e;margin-right:6px;">طبقه ${t.Floor}</small>`:""}
                        ${t.CI_Years?`<small style="background:#fff;padding:1px 6px;border-radius:4px;margin-right:6px;">سال ${t.CI_Years}</small>`:""}
                    </div>
                    ${s>0?`<span style="background:#fff;color:#92400e;padding:1px 8px;border-radius:6px;font-size:11px;font-weight:700;white-space:nowrap;">حداکثر ${this._fmt(s)}</span>`:""}
                </div>
                ${t.Trepass_Comments?`<div style="margin-top:4px;color:#78350f;font-size:11px;">${this.escape(t.Trepass_Comments)}</div>`:""}
                ${t.UsingTitle||t.UsingGroupTitle?`<div style="margin-top:3px;font-size:10px;color:#a16207;">${this.escape(t.UsingGroupTitle??"")} ${t.UsingTitle?"— "+this.escape(t.UsingTitle):""}</div>`:""}
            </div>`}).join("")}
        </div>`:'<div style="color:#94a3b8;font-size:12px;padding:6px;">⚠️ تخلفی ثبت نشده</div>'}_renderSummaryRows(e){return e!=null&&e.length?`
        <h4 style="margin:14px 0 6px 0;font-size:13px;color:#475569;">📋 خلاصه (از wp_gis_commission) — ${e.length} ردیف</h4>
        <table class="acc-table" style="font-size:11px;">
            <thead><tr>
                <th>نوع رأی</th><th>نوع کمیسیون</th><th>شماره</th><th>تاریخ</th><th>کاربری</th><th>مبلغ رأی</th>
            </tr></thead>
            <tbody>
            ${e.map(t=>{const s=$o[t.VoteType]??{color:"#64748b"};return`<tr>
                    <td><span style="background:${s.color}1a;color:${s.color};padding:1px 6px;border-radius:6px;font-weight:700;">${this.escape(t.VoteType??"—")}</span></td>
                    <td>${this.escape(t.CommissionType??"—")}</td>
                    <td style="font-family:monospace;">${this.escape(t.VoteNo??"—")}</td>
                    <td>${this.escape(t.VoteDate??"—")}</td>
                    <td><small>${this.escape(t.UsingGroup??"—")}</small></td>
                    <td>${parseFloat(t.votevalue)>0?"<b>"+this._fmt(t.votevalue)+"</b>":"—"}</td>
                </tr>`}).join("")}
            </tbody>
        </table>`:""}_renderAdminInfo(e){const t=[];e.SecretariatNo&&t.push(["شماره دبیرخانه",e.SecretariatNo]),e.PenaltyValue&&t.push(["مقدار جریمه",e.PenaltyValue]),e.OwnerCellNo&&t.push(["موبایل مالک",e.OwnerCellNo]),e.OwnerNationalCode&&t.push(["کد ملی مالک",e.OwnerNationalCode]),e.BackStateTitle&&t.push(["وضعیت",e.BackStateTitle]),e.WorkflowTitel&&t.push(["Workflow",e.WorkflowTitel]);const s=[];return e.CommissionComments&&s.push(["💬 توضیح کمیسیون",e.CommissionComments]),e.Run_Comments&&s.push(["🏃 توضیح اجرا",e.Run_Comments]),e.AllUrbanComments&&s.push(["🏙️ توضیحات شهرسازی",e.AllUrbanComments]),!t.length&&!s.length?"":`
        <details style="margin-top:10px;">
            <summary style="cursor:pointer;font-size:12px;color:#3b82f6;">📋 اطلاعات اداری بیشتر</summary>
            ${t.length?`
            <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:6px;background:#f8fafc;padding:8px;border-radius:6px;margin-top:6px;font-size:12px;">
                ${t.map(([a,i])=>`<div><b>${a}:</b> ${this.escape(i)}</div>`).join("")}
            </div>`:""}
            ${s.length?s.map(([a,i])=>`
            <div style="margin-top:6px;background:#fff7ed;border-right:3px solid #f97316;padding:8px;border-radius:6px;font-size:11px;">
                <b>${a}:</b><br>${this.escape(i)}
            </div>`).join(""):""}
        </details>`}_renderFileMeta(e){const t=[];return e.CurrentArea&&t.push(["متراژ فعلی",e.CurrentArea+" م²"]),e.DocArea&&t.push(["متراژ سند",e.DocArea+" م²"]),e.Density&&t.push(["تراکم",e.Density+"%"]),e.UsingGroup_Mojood&&t.push(["کاربری",e.UsingGroup_Mojood]),e.ExpertName&&t.push(["کارشناس",e.ExpertName]),e.VoterUserName&&t.push(["دبیر",e.VoterUserName]),t.length?`
        <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:6px;background:#f8fafc;padding:8px;border-radius:6px;margin-bottom:10px;font-size:12px;">
            ${t.map(([s,a])=>`<div><b>${s}:</b> ${this.escape(a)}</div>`).join("")}
        </div>`:""}_renderVoteList(e,t){if(!(e!=null&&e.length))return'<div style="color:#94a3b8;font-size:12px;padding:6px;margin-top:10px;">⚖️ رأیی صادر نشده</div>';const s={};return(t??[]).forEach(a=>s[a.NidTrepass]=a),`
        <h4 style="margin:14px 0 6px 0;font-size:13px;color:#475569;">⚖️ رأی‌ها (${e.length})</h4>
        <div style="display:flex;flex-direction:column;gap:6px;">
        ${e.map(a=>{const i=na[a.CI_VoteType]??{label:"سایر",color:"#64748b",icon:"📋"},n=(a.trepass_nids??[]).map(r=>{var o;return(o=s[r])==null?void 0:o.Title}).filter(Boolean);return`
            <div style="background:${i.color}1a;border-right:3px solid ${i.color};padding:10px 12px;border-radius:6px;font-size:12px;">
                <div style="display:flex;justify-content:space-between;align-items:start;gap:8px;flex-wrap:wrap;">
                    <div style="flex:1;min-width:0;">
                        <b style="color:${i.color};">${i.icon} ${i.label}</b>
                        ${a.VoteNo?`<small style="color:#64748b;margin-right:6px;font-family:monospace;">رأی #${this.escape(a.VoteNo)}</small>`:""}
                        ${a.VoteDate?`<small style="color:#94a3b8;margin-right:6px;">📅 ${a.VoteDate}</small>`:""}
                    </div>
                    ${parseFloat(a.VoteValue)>0?`<span style="background:${i.color};color:#fff;padding:2px 10px;border-radius:6px;font-size:12px;font-weight:700;white-space:nowrap;">${this._fmt(a.VoteValue)} ﷼</span>`:""}
                </div>
                ${n.length?`<div style="margin-top:4px;font-size:11px;color:#64748b;">🔗 برای: ${n.map(r=>this.escape(r)).join("، ")}</div>`:""}
                ${a.Vote_Comments?`<details style="margin-top:6px;"><summary style="cursor:pointer;font-size:11px;color:${i.color};">📄 متن رأی</summary><div style="margin-top:6px;padding:8px;background:#fff;border-radius:4px;font-size:11px;line-height:1.7;color:#475569;">${this.escape(a.Vote_Comments)}</div></details>`:""}
            </div>`}).join("")}
        </div>`}_fmt(e){return new Intl.NumberFormat("fa-IR").format(Math.round(Number(e??0)))}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}_toast(e,t="#10b981"){const s=document.createElement("div");s.style.cssText=`position:fixed;bottom:24px;left:24px;background:${t};color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;`,s.textContent=e,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}}const Eo=[{key:"viewer",icon:"🔨",title:"بررسی پرونده‌های کد نوسازی",desc:"همه پرونده‌ها / رأی‌ها / تخلفات",Class:ko}];class ra extends C{constructor(t={}){var s,a;super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active="viewer",this._sections={},this._initialCode=((a=(s=t.tab)==null?void 0:s.params)==null?void 0:a.code)??sessionStorage.getItem("acc_commission_pending_code")??null,this._initialCode&&sessionStorage.removeItem("acc_commission_pending_code")}async template(){return'<div data-ref="root"></div>'}async afterRender(){const t=this.ref("root"),s=Eo[0],a=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api,initialCode:this._initialCode});await a.render(t),this._sections.viewer=a}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(ra,"title","کمیسیون ماده ۱۰۰"),E.register("commission",ra);class Lo extends x{async template(){return`
        <div class="acc-section-wrap" dir="rtl">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📊 وضعیت Workflow پروژه‌ها</h2>
                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄 بروزرسانی</button>
            </div>
            <div data-ref="grid" class="wf-status-grid"></div>
        </div>`}async afterRender(){this.on(this.ref("refreshBtn"),"click",()=>this._load()),await this._load()}async _load(){const e=this.ref("grid");e.innerHTML=this._skeletons(6);try{const[t]=await Promise.all([this.api.get("pc/projects"),this.api.get("wf/templates")]),s=(t==null?void 0:t.data)??t??[],a=await Promise.all(s.map(i=>this.api.get(`wf/instances/project/${i.id}`).catch(()=>({data:null}))));e.innerHTML=s.length?s.map((i,n)=>{var r;return this._card(i,(r=a[n])==null?void 0:r.data)}).join(""):'<div class="acc-empty">پروژه‌ای وجود ندارد</div>',this._bindCards(e,s,a)}catch(t){e.innerHTML=`<div class="acc-error">❌ ${this.escape(t.message)}</div>`}}_card(e,t){const s=this.escape(e.name||e.title||`#${e.id}`);if(!t)return`
        <div class="wf-project-card wf-card--no-wf">
            <div class="wf-card-title">${s}</div>
            <div class="wf-card-subtitle">${this.escape(e.code||"")}</div>
            <div class="wf-no-workflow">بدون Workflow</div>
        </div>`;const a=t.stages??[],i=a.find(l=>l.id==t.current_stage_id)||a[0],n=parseFloat(t.progress_pct??0),r=a.map(l=>`<div class="wf-stage-pill ${l.status==="completed"?"wf-stage--done":l.status==="active"?"wf-stage--active":"wf-stage--pending"}">${this.escape(l.icon||"●")} ${this.escape(l.name)}</div>`).join(""),o=((i==null?void 0:i.tasks)??[]).map(l=>{const c=l.status==="completed";return`
            <div class="wf-task-row ${c?"wf-task--done":""}">
                <span>${c?"✅":l.is_required?"🔴":"⬜"}</span>
                <span class="wf-task-title">${this.escape(l.title)}</span>
                ${c?"":`<button class="acc-btn acc-btn--xs acc-btn--primary" data-complete-task="${l.id}">تکمیل</button>`}
            </div>`}).join("")||'<div style="color:#94a3b8;font-size:12px;">وظیفه‌ای تعریف نشده</div>';return`
        <div class="wf-project-card" data-instance-id="${t.id}">
            <div class="wf-card-header">
                <div>
                    <div class="wf-card-title">${s}</div>
                    <div class="wf-card-subtitle">${this.escape(e.code||"")} — ${this.escape(t.template_name||"")}</div>
                </div>
                <button class="acc-btn acc-btn--xs" data-history="${t.id}" title="تاریخچه">📜</button>
            </div>
            <div class="wf-progress-bar"><div class="wf-progress-fill" style="width:${n}%"></div></div>
            <div class="wf-progress-label">${n}% پیشرفت کل</div>
            <div class="wf-stages-strip">${r}</div>
            ${i?`
            <div class="wf-current-stage">
                <div class="wf-stage-name">
                    <span>${i.icon||"📌"}</span>
                    <strong>مرحله جاری: ${this.escape(i.name)}</strong>
                    <span class="wf-stage-progress">${i.progress_pct??0}%</span>
                </div>
                <div class="wf-tasks-list">${o}</div>
                ${i.status==="active"?`
                <div style="text-align:left;margin-top:8px;">
                    <button class="acc-btn acc-btn--primary acc-btn--sm" data-advance="${i.id}">⏭ مرحله بعد</button>
                </div>`:""}
            </div>`:""}
        </div>`}_bindCards(e,t,s){e.querySelectorAll("[data-advance]").forEach(a=>{a.addEventListener("click",()=>this._advance(a.dataset.advance))}),e.querySelectorAll("[data-complete-task]").forEach(a=>{a.addEventListener("click",()=>this._completeTask(a.dataset.completeTask))}),e.querySelectorAll("[data-history]").forEach(a=>{a.addEventListener("click",()=>this._showHistory(a.dataset.history))})}async _advance(e){try{const t=await this.api.post(`wf/stages/${e}/advance`,{});this._toast(t.completed?"🎉 Workflow تکمیل شد!":"✅ مرحله بعدی شروع شد"),await this._load()}catch(t){t.message.includes("اجباری")?confirm(`${t.message}
با force ادامه دهید؟`)&&(await this.api.post(`wf/stages/${e}/advance`,{force:!0}),await this._load()):alert(t.message)}}async _completeTask(e){try{await this.api.post(`wf/tasks/${e}/complete`,{}),this._toast("✅ وظیفه تکمیل شد"),await this._load()}catch(t){alert(t.message)}}async _showHistory(e){try{const t=await this.api.get(`wf/instances/${e}/transitions`),s=(t==null?void 0:t.data)??[],a=document.createElement("div");a.className="acc-modal-overlay",a.innerHTML=`
            <div class="acc-modal" style="max-width:600px;max-height:80vh;overflow-y:auto;">
                <button class="acc-modal__close">✕</button>
                <div class="acc-modal__title">📜 تاریخچه Workflow</div>
                ${s.length?s.map(n=>`
                <div style="border-right:3px solid #3b82f6;padding:10px 12px;margin-bottom:8px;background:#f8fafc;border-radius:6px;">
                    <div style="font-weight:700;font-size:13px;">${this._actionIcon(n.action)} ${this.escape(n.notes)}</div>
                    <div style="font-size:11px;color:#64748b;margin-top:4px;">
                        ${n.from_stage_name?`از: ${this.escape(n.from_stage_name)} ← `:""}
                        ${n.to_stage_name?`به: ${this.escape(n.to_stage_name)}`:""}
                    </div>
                    <div style="font-size:11px;color:#94a3b8;margin-top:3px;">👤 ${this.escape(n.actor_name||"سیستم")} — ${n.created_at}</div>
                </div>`).join(""):'<div class="acc-empty">تاریخچه‌ای نیست</div>'}
                <div class="acc-modal__actions">
                    <button class="acc-btn acc-btn--secondary" data-action="close">بستن</button>
                </div>
            </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-action=close]").addEventListener("click",i),a.addEventListener("click",n=>{n.target===a&&i()})}catch{}}_actionIcon(e){return{create:"🚀",start_stage:"▶️",advance:"⏭️",complete:"🎉"}[e]??"🔄"}_skeletons(e=6){return Array.from({length:e},()=>`
        <div class="wf-project-card" style="animation:sk-shine 1.4s infinite;">
            <div style="height:16px;background:#e2e8f0;border-radius:4px;width:60%;margin-bottom:10px;"></div>
            <div style="height:8px;background:#e2e8f0;border-radius:4px;margin-bottom:8px;"></div>
            <div style="height:8px;background:#e2e8f0;border-radius:4px;width:80%;"></div>
        </div>`).join("")}_toast(e){const t=document.createElement("div");t.style.cssText="position:fixed;bottom:24px;left:24px;background:#10b981;color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;",t.textContent=e,document.body.appendChild(t),setTimeout(()=>t.remove(),3e3)}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}class So extends x{constructor(){super(...arguments);g(this,"_projects",[]);g(this,"_templates",[])}async template(){return`
        <div class="acc-section-wrap" dir="rtl">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📁 تخصیص Workflow به پروژه‌ها</h2>
                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄 بروزرسانی</button>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){this.on(this.ref("refreshBtn"),"click",()=>this._load()),await this._load()}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const[t,s]=await Promise.all([this.api.get("pc/projects"),this.api.get("wf/templates")]);this._projects=(t==null?void 0:t.data)??t??[],this._templates=(s==null?void 0:s.data)??[];const a=await Promise.all(this._projects.map(i=>this.api.get(`wf/instances/project/${i.id}`).catch(()=>({data:null}))));this._render(a)}catch(t){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(t.message)}</div>`}}_render(t){if(!this._projects.length){this.ref("wrap").innerHTML='<div class="acc-empty">پروژه‌ای وجود ندارد</div>';return}const s=this._templates.map(i=>`<option value="${i.id}">${this.escape(i.icon||"")} ${this.escape(i.name)}</option>`).join(""),a=this._projects.map((i,n)=>{var c;const r=(c=t[n])==null?void 0:c.data,o=r?`<span style="background:#d1fae5;color:#065f46;padding:3px 10px;border-radius:10px;font-size:12px;font-weight:600;">✅ ${this.escape(r.template_name||"دارد")}</span>`:'<span style="background:#f1f5f9;color:#94a3b8;padding:3px 10px;border-radius:10px;font-size:12px;">بدون Workflow</span>',l=r?`<button class="acc-btn acc-btn--xs acc-btn--danger" data-remove="${r.id}">🗑 حذف</button>`:`<div style="display:flex;gap:6px;align-items:center;">
                    <select class="acc-select" data-proj="${i.id}">${s}</select>
                    <button class="acc-btn acc-btn--xs acc-btn--primary" data-assign="${i.id}">✅ تخصیص</button>
                   </div>`;return`
            <tr>
                <td>${this.escape(i.name||i.title||`#${i.id}`)}</td>
                <td>${this.escape(i.code||"-")}</td>
                <td>${o}</td>
                <td>${l}</td>
            </tr>`}).join("");this.ref("wrap").innerHTML=`
        <div style="overflow-x:auto;">
            <table class="acc-table">
                <thead><tr><th>نام پروژه</th><th>کد</th><th>وضعیت Workflow</th><th>عملیات</th></tr></thead>
                <tbody>${a}</tbody>
            </table>
        </div>`,this.ref("wrap").querySelectorAll("[data-assign]").forEach(i=>{i.addEventListener("click",async()=>{const n=i.dataset.assign,r=this.ref("wrap").querySelector(`select[data-proj="${n}"]`);if(r!=null&&r.value)try{await this.api.post("wf/instances",{project_id:+n,template_id:+r.value}),this._toast("✅ Workflow تخصیص یافت"),await this._load()}catch(o){alert(o.message)}})}),this.ref("wrap").querySelectorAll("[data-remove]").forEach(i=>{i.addEventListener("click",async()=>{if(confirm("Workflow این پروژه حذف شود؟"))try{await this.api.delete(`wf/instances/${i.dataset.remove}`),this._toast("✅ Workflow حذف شد"),await this._load()}catch(n){alert(n.message)}})})}_toast(t){const s=document.createElement("div");s.style.cssText="position:fixed;bottom:24px;left:24px;background:#10b981;color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;z-index:9999;",s.textContent=t,document.body.appendChild(s),setTimeout(()=>s.remove(),3e3)}escape(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}class Co extends x{constructor(){super(...arguments);g(this,"_templates",[]);g(this,"_selected",null)}async template(){return`
        <div class="acc-section-wrap" dir="rtl">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">⚙️ قالب‌های Workflow</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ قالب جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div style="display:grid;grid-template-columns:240px 1fr;gap:16px;min-height:500px;">
                <div style="background:#f8fafc;border:1px solid #e2e8f0;border-radius:10px;overflow:hidden;">
                    <div style="padding:12px;font-weight:700;font-size:13px;color:#475569;background:#f1f5f9;border-bottom:1px solid #e2e8f0;">قالب‌های موجود</div>
                    <ul data-ref="tplList" style="list-style:none;padding:0;margin:0;"></ul>
                </div>
                <div data-ref="detail" style="background:#fff;border:1px solid #e2e8f0;border-radius:10px;padding:16px;">
                    <div class="acc-empty">یک قالب را انتخاب کنید یا قالب جدید بسازید.</div>
                </div>
            </div>
        </div>`}async afterRender(){this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._renderForm(null)),await this._load()}async _load(){try{const t=await this.api.get("wf/templates");this._templates=(t==null?void 0:t.data)??[],this._renderList()}catch(t){this.ref("tplList").innerHTML=`<li style="padding:12px;color:#dc2626;font-size:12px;">خطا: ${this.escape(t.message)}</li>`}}_renderList(){const t=this.ref("tplList");if(!this._templates.length){t.innerHTML='<li style="padding:12px 16px;color:#94a3b8;font-size:13px;">قالبی وجود ندارد</li>';return}t.innerHTML=this._templates.map(s=>`
        <li data-tpl-id="${s.id}" style="display:flex;justify-content:space-between;align-items:center;
             padding:10px 12px;cursor:pointer;font-size:13px;color:#334155;
             border-bottom:1px solid #f1f5f9;transition:background .1s;"
            onmouseenter="this.style.background='#eff6ff'" onmouseleave="this.style.background=''">
            <span>${this.escape(s.icon||"📋")} ${this.escape(s.name)}</span>
            <span style="font-size:11px;color:#94a3b8;">${s.stage_count??0} مرحله</span>
        </li>`).join(""),t.querySelectorAll("li[data-tpl-id]").forEach(s=>{s.addEventListener("click",async()=>{t.querySelectorAll("li").forEach(a=>a.style.background=""),s.style.background="#dbeafe",s.style.color="#1d4ed8",await this._loadDetail(s.dataset.tplId)})})}async _loadDetail(t){const s=this.ref("detail");s.innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const a=await this.api.get(`wf/templates/${t}`),i=a==null?void 0:a.data;if(!i){s.innerHTML='<div class="acc-empty">یافت نشد</div>';return}this._selected=i,this._renderDetail(i)}catch(a){s.innerHTML=`<div class="acc-error">❌ ${this.escape(a.message)}</div>`}}_renderDetail(t){var i,n,r;const s=this.ref("detail"),a=(t.stages??[]).map((o,l)=>`
        <div style="border:1px solid #e2e8f0;border-radius:8px;overflow:hidden;margin-bottom:10px;">
            <div style="background:#f1f5f9;padding:10px 14px;display:flex;justify-content:space-between;align-items:center;">
                <span style="font-weight:700;font-size:13px;">${this.escape(o.icon||"▶")} ${l+1}. ${this.escape(o.name)}</span>
                <span style="font-size:11px;color:#94a3b8;">ترتیب: ${o.sort_order} | بودجه: ${o.budget_pct}%</span>
            </div>
            <div style="padding:10px 14px;">
                ${(o.tasks??[]).map(c=>`
                <div style="font-size:12px;color:#475569;padding:3px 0;">
                    ${c.is_required?"🔴":"⬜"} ${this.escape(c.title)}
                </div>`).join("")||'<div style="color:#94a3b8;font-size:12px;">وظیفه‌ای تعریف نشده</div>'}
            </div>
        </div>`).join("")||'<div class="acc-empty">مرحله‌ای تعریف نشده</div>';s.innerHTML=`
        <div style="display:flex;justify-content:space-between;align-items:center;margin-bottom:14px;flex-wrap:wrap;gap:8px;">
            <div>
                <span style="font-size:26px;">${t.icon||"📋"}</span>
                <strong style="font-size:16px;margin-right:8px;">${this.escape(t.name)}</strong>
                <span style="background:#f1f5f9;color:#64748b;padding:2px 8px;border-radius:10px;font-size:11px;">${t.instance_count??0} پروژه</span>
            </div>
            <div style="display:flex;gap:6px;">
                <button class="acc-btn acc-btn--sm" data-ref="editBtn">✏️ ویرایش</button>
                ${t.is_system?"":'<button class="acc-btn acc-btn--sm acc-btn--danger" data-ref="delBtn">🗑 حذف</button>'}
                <button class="acc-btn acc-btn--sm acc-btn--primary" data-ref="addStageBtn">+ مرحله</button>
            </div>
        </div>
        ${t.description?`<p style="font-size:13px;color:#64748b;margin-bottom:14px;">${this.escape(t.description)}</p>`:""}
        <div data-ref="stagesWrap">${a}</div>
        <div data-ref="stageFormArea"></div>`,this._bindRefs(),(i=this.ref("editBtn"))==null||i.addEventListener("click",()=>this._renderForm(t)),(n=this.ref("delBtn"))==null||n.addEventListener("click",()=>this._delete(t)),(r=this.ref("addStageBtn"))==null||r.addEventListener("click",()=>this._renderStageForm(t.id))}async _delete(t){if(confirm(`قالب «${t.name}» حذف شود؟`))try{await this.api.delete(`wf/templates/${t.id}`),this.ref("detail").innerHTML='<div class="acc-empty">قالب حذف شد.</div>',await this._load()}catch(s){alert(s.message)}}_renderForm(t){const s=!!t,a=this.ref("detail");a.innerHTML=`
        <h3 style="margin:0 0 16px;font-size:15px;">${s?"✏️ ویرایش قالب":"➕ قالب جدید"}</h3>
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:14px;">
            <label style="display:flex;flex-direction:column;gap:5px;font-size:13px;color:#475569;">نام قالب *
                <input class="acc-input" data-ref="fname" value="${this.escape((t==null?void 0:t.name)||"")}" placeholder="مثلاً: پروژه ساختمانی">
            </label>
            <label style="display:flex;flex-direction:column;gap:5px;font-size:13px;color:#475569;">کد (code)
                <input class="acc-input" data-ref="fcode" value="${this.escape((t==null?void 0:t.code)||"")}" placeholder="construction" ${s?"disabled":""}>
            </label>
            <label style="display:flex;flex-direction:column;gap:5px;font-size:13px;color:#475569;">آیکون
                <input class="acc-input" data-ref="ficon" value="${this.escape((t==null?void 0:t.icon)||"📋")}" maxlength="4">
            </label>
            <label style="display:flex;flex-direction:column;gap:5px;font-size:13px;color:#475569;">رنگ
                <input type="color" class="acc-input" data-ref="fcolor" value="${(t==null?void 0:t.color)||"#3b82f6"}" style="height:36px;padding:3px;">
            </label>
            <label style="display:flex;flex-direction:column;gap:5px;font-size:13px;color:#475569;grid-column:1/-1;">توضیحات
                <textarea class="acc-input" data-ref="fdesc" rows="2">${this.escape((t==null?void 0:t.description)||"")}</textarea>
            </label>
        </div>
        <div style="display:flex;gap:8px;">
            <button class="acc-btn acc-btn--primary" data-ref="saveBtn">💾 ذخیره</button>
            <button class="acc-btn acc-btn--secondary" data-ref="cancelBtn">لغو</button>
        </div>`,this._bindRefs(),this.ref("cancelBtn").addEventListener("click",async()=>{s?this._renderDetail(t):a.innerHTML='<div class="acc-empty">یک قالب را انتخاب کنید یا قالب جدید بسازید.</div>'}),this.ref("saveBtn").addEventListener("click",async()=>{const i=this.ref("fname").value.trim();if(!i){alert("نام الزامی است");return}const n={name:i,description:this.ref("fdesc").value,icon:this.ref("ficon").value,color:this.ref("fcolor").value};s||(n.code=this.ref("fcode").value.trim());try{s?await this.api.put(`wf/templates/${t.id}`,n):await this.api.post("wf/templates",n),await this._load(),s?await this._loadDetail(t.id):a.innerHTML='<div class="acc-empty">قالب ذخیره شد. از لیست انتخاب کنید.</div>'}catch(r){alert(r.message)}})}_renderStageForm(t){const s=this.ref("stageFormArea");if(!s)return;let a=[];s.innerHTML=`
        <div style="border:1px solid #3b82f6;border-radius:10px;padding:16px;margin-top:14px;">
            <h4 style="margin:0 0 14px;font-size:14px;color:#1d4ed8;">➕ مرحله جدید</h4>
            <div style="display:grid;grid-template-columns:1fr 1fr;gap:10px;margin-bottom:12px;">
                <label style="display:flex;flex-direction:column;gap:4px;font-size:12px;">نام *
                    <input class="acc-input" data-ref="sname" placeholder="مثلاً: طراحی">
                </label>
                <label style="display:flex;flex-direction:column;gap:4px;font-size:12px;">کد
                    <input class="acc-input" data-ref="scode" placeholder="design">
                </label>
                <label style="display:flex;flex-direction:column;gap:4px;font-size:12px;">آیکون
                    <input class="acc-input" data-ref="sicon" value="▶" maxlength="4">
                </label>
                <label style="display:flex;flex-direction:column;gap:4px;font-size:12px;">ترتیب
                    <input type="number" class="acc-input" data-ref="sorder" value="10">
                </label>
                <label style="display:flex;flex-direction:column;gap:4px;font-size:12px;">% بودجه
                    <input type="number" class="acc-input" data-ref="sbudget" value="0" min="0" max="100">
                </label>
            </div>
            <div style="background:#fff;border:1px solid #e2e8f0;border-radius:8px;padding:12px;margin-bottom:12px;">
                <div style="font-weight:600;font-size:12px;margin-bottom:8px;">وظایف مرحله:</div>
                <div data-ref="tasksArea"></div>
                <button class="acc-btn acc-btn--xs" data-ref="addTaskBtn">+ وظیفه</button>
            </div>
            <div style="display:flex;gap:8px;">
                <button class="acc-btn acc-btn--primary acc-btn--sm" data-ref="saveStageBtn">💾 ذخیره</button>
                <button class="acc-btn acc-btn--secondary acc-btn--sm" data-ref="cancelStageBtn">لغو</button>
            </div>
        </div>`,this._bindRefs();const i=()=>{const n=this.ref("tasksArea");n.innerHTML=a.map((r,o)=>`
            <div style="display:flex;gap:6px;align-items:center;margin-bottom:6px;">
                <input class="acc-input" style="flex:1;" data-ti="${o}" value="${this.escape(r.title)}" placeholder="عنوان وظیفه">
                <label style="font-size:11px;display:flex;align-items:center;gap:3px;white-space:nowrap;">
                    <input type="checkbox" data-ri="${o}" ${r.is_required?"checked":""}> اجباری
                </label>
                <button class="acc-btn acc-btn--xs acc-btn--danger" data-di="${o}">✕</button>
            </div>`).join(""),n.querySelectorAll("[data-ti]").forEach(r=>r.addEventListener("input",()=>{a[r.dataset.ti].title=r.value})),n.querySelectorAll("[data-ri]").forEach(r=>r.addEventListener("change",()=>{a[r.dataset.ri].is_required=r.checked})),n.querySelectorAll("[data-di]").forEach(r=>r.addEventListener("click",()=>{a.splice(+r.dataset.di,1),i()}))};i(),this.ref("addTaskBtn").addEventListener("click",()=>{a.push({title:"",is_required:!1}),i()}),this.ref("cancelStageBtn").addEventListener("click",()=>{s.innerHTML=""}),this.ref("saveStageBtn").addEventListener("click",async()=>{const n=this.ref("sname").value.trim();if(!n){alert("نام مرحله الزامی است");return}try{await this.api.post(`wf/templates/${t}/stages`,{name:n,code:this.ref("scode").value.trim(),icon:this.ref("sicon").value,sort_order:+this.ref("sorder").value,budget_pct:+this.ref("sbudget").value||0,tasks:a.filter(r=>r.title.trim())}),s.innerHTML="",await this._loadDetail(t)}catch(r){alert(r.message)}})}escape(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}class To extends x{async template(){return`
        <div class="acc-section-wrap" dir="rtl">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📜 تاریخچه Workflow</h2>
            </div>
            <div style="display:flex;align-items:center;gap:10px;margin-bottom:16px;flex-wrap:wrap;">
                <label style="font-size:13px;color:#475569;display:flex;align-items:center;gap:8px;">
                    انتخاب پروژه:
                    <select class="acc-select" data-ref="projSel"></select>
                </label>
                <button class="acc-btn acc-btn--primary" data-ref="loadBtn">نمایش تاریخچه</button>
            </div>
            <div data-ref="table"></div>
        </div>`}async afterRender(){await this._loadProjects(),this.on(this.ref("loadBtn"),"click",()=>this._loadHistory())}async _loadProjects(){try{const e=await this.api.get("pc/projects"),t=(e==null?void 0:e.data)??e??[],s=await Promise.all(t.map(n=>this.api.get(`wf/instances/project/${n.id}`).catch(()=>({data:null})))),a=t.filter((n,r)=>{var o;return(o=s[r])==null?void 0:o.data}),i=this.ref("projSel");if(!a.length){i.innerHTML="<option>هیچ پروژه‌ای با Workflow وجود ندارد</option>";return}i.innerHTML=a.map((n,r)=>{var l;return`<option value="${((l=s[t.indexOf(n)])==null?void 0:l.data).id}">${this.escape(n.name||n.title||`#${n.id}`)}</option>`}).join(""),await this._loadHistory()}catch{}}async _loadHistory(){const e=this.ref("projSel"),t=e==null?void 0:e.value;if(!t)return;const s=this.ref("table");s.innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const a=await this.api.get(`wf/instances/${t}/transitions`),i=(a==null?void 0:a.data)??[];if(!i.length){s.innerHTML='<div class="acc-empty">تاریخچه‌ای ثبت نشده</div>';return}s.innerHTML=`
            <div style="overflow-x:auto;">
                <table class="acc-table">
                    <thead><tr><th>زمان</th><th>عملیات</th><th>از مرحله</th><th>به مرحله</th><th>توسط</th><th>یادداشت</th></tr></thead>
                    <tbody>
                    ${i.map(n=>`
                    <tr>
                        <td style="white-space:nowrap;font-size:11px;">${this.escape(n.created_at||"")}</td>
                        <td><span style="background:${this._actionColor(n.action)};padding:2px 8px;border-radius:4px;font-size:11px;font-weight:700;">${this.escape(n.action)}</span></td>
                        <td>${this.escape(n.from_stage_name||"-")}</td>
                        <td>${this.escape(n.to_stage_name||"-")}</td>
                        <td>${this.escape(n.actor_name||"-")}</td>
                        <td>${this.escape(n.notes||"")}</td>
                    </tr>`).join("")}
                    </tbody>
                </table>
            </div>`}catch(a){s.innerHTML=`<div class="acc-error">❌ ${this.escape(a.message)}</div>`}}_actionColor(e){return{create:"#dbeafe",start_stage:"#ede9fe",advance:"#d1fae5",complete:"#fef3c7"}[e]??"#f1f5f9"}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const Bt=[{key:"status",icon:"📊",title:"وضعیت پروژه‌ها",desc:"مرحله جاری هر پروژه",Class:Lo},{key:"assign",icon:"📁",title:"تخصیص Workflow",desc:"اتصال قالب به پروژه",Class:So},{key:"templates",icon:"⚙️",title:"قالب‌ها",desc:"تعریف مراحل و وظایف",Class:Co},{key:"history",icon:"📜",title:"تاریخچه",desc:"لاگ تغییرات مراحل",Class:To}];class oa extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._active="status",this._sections={}}async template(){const t=Bt.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
                <div class="sp-nav-card__desc">${a.desc}</div>
            </div>
        `).join(""),s=Bt.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=Bt.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(oa,"title","🔄 Workflow پروژه‌ها"),E.register("workflow",oa);const la="acc_cart_v1";class Mo{constructor(){g(this,"_items",[]);g(this,"_listeners",[]);this._load()}add(e,t=1){const s=this._items.find(a=>a.id===e.id);s?s.qty+=t:this._items.push({id:e.id,name:e.name,price:parseFloat(e.price)||0,image:e.image||null,qty:t}),this._save(),this._notify()}remove(e){this._items=this._items.filter(t=>t.id!==e),this._save(),this._notify()}setQty(e,t){const s=this._items.find(a=>a.id===e);if(s){if(t<=0){this.remove(e);return}s.qty=t,this._save(),this._notify()}}clear(){this._items=[],this._save(),this._notify()}get items(){return[...this._items]}get count(){return this._items.reduce((e,t)=>e+t.qty,0)}get total(){return this._items.reduce((e,t)=>e+t.price*t.qty,0)}onChange(e){return this._listeners.push(e),()=>{this._listeners=this._listeners.filter(t=>t!==e)}}_load(){try{const e=localStorage.getItem(la);this._items=e?JSON.parse(e):[]}catch{this._items=[]}}_save(){try{localStorage.setItem(la,JSON.stringify(this._items))}catch{}}_notify(){this._listeners.forEach(e=>e(this._items))}}const A=new Mo,We=p=>p?new Intl.NumberFormat("fa-IR").format(Math.round(+p))+" تومان":"رایگان",Ue=p=>String(p??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");class Ro{constructor(e){this._api=e,this._step="cart",this._overlay=null}open(){this._overlay&&this._overlay.remove(),this._overlay=document.createElement("div"),this._overlay.className="acc-cart-overlay",this._overlay.dir="rtl",document.body.appendChild(this._overlay),this._render(),this._overlay.addEventListener("click",e=>{e.target===this._overlay&&this.close()})}close(){var e;(e=this._overlay)==null||e.remove(),this._overlay=null}_render(){this._overlay&&(this._overlay.innerHTML=`<div class="acc-cart-modal">${this._body()}</div>`,this._bindEvents())}_body(){return this._step==="cart"?this._cartView():this._step==="checkout"?this._checkoutView():this._step==="paying"?this._payingView():this._step==="result"?this._resultView():""}_cartView(){const e=A.items,t=e.length?e.map(s=>`
        <div class="acc-cart-row" data-id="${s.id}">
            <div class="acc-cart-thumb">
                ${s.image?`<img src="${Ue(s.image)}" alt="">`:"<span>📦</span>"}
            </div>
            <div class="acc-cart-row-info">
                <div class="acc-cart-row-name">${Ue(s.name)}</div>
                <div class="acc-cart-row-price">${We(s.price)}</div>
            </div>
            <div class="acc-cart-qty-wrap">
                <button class="acc-qty-btn" data-action="dec" data-id="${s.id}">−</button>
                <span class="acc-qty-num">${s.qty}</span>
                <button class="acc-qty-btn" data-action="inc" data-id="${s.id}">+</button>
            </div>
            <div class="acc-cart-row-total">${We(s.price*s.qty)}</div>
            <button class="acc-cart-remove" data-action="remove" data-id="${s.id}">✕</button>
        </div>`).join(""):'<div class="acc-cart-empty">🛒<br>سبد خرید خالی است</div>';return`
        <div class="acc-cart-header">
            <h3>🛒 سبد خرید <span class="acc-cart-badge">${A.count}</span></h3>
            <button class="acc-cart-close-btn" data-action="close">✕</button>
        </div>
        <div class="acc-cart-body">${t}</div>
        ${e.length?`
        <div class="acc-cart-footer">
            <div class="acc-cart-total-line">
                <span>جمع کل:</span>
                <strong class="acc-cart-grand">${We(A.total)}</strong>
            </div>
            <button class="acc-btn acc-btn--primary acc-btn--full" data-action="checkout">
                تکمیل خرید ←
            </button>
        </div>`:""}`}_checkoutView(){return`
        <div class="acc-cart-header">
            <button class="acc-icon-btn" data-action="back-to-cart">→</button>
            <h3>📋 اطلاعات خریدار</h3>
            <button class="acc-cart-close-btn" data-action="close">✕</button>
        </div>
        <div class="acc-cart-body">
            <div class="acc-checkout-form">
                <div class="acc-form-group">
                    <label>نام و نام خانوادگی <span class="acc-req">*</span></label>
                    <input type="text" id="ck-name" class="acc-input" placeholder="علی محمدی" autocomplete="name">
                </div>
                <div class="acc-form-group">
                    <label>شماره موبایل <span class="acc-req">*</span></label>
                    <input type="tel" id="ck-phone" class="acc-input" placeholder="09123456789" dir="ltr" autocomplete="tel">
                </div>
                <div class="acc-form-group">
                    <label>ایمیل <small style="color:#94a3b8;">(اختیاری)</small></label>
                    <input type="email" id="ck-email" class="acc-input" placeholder="email@example.com" dir="ltr" autocomplete="email">
                </div>
                <div class="acc-form-group">
                    <label>آدرس تحویل <span class="acc-req">*</span></label>
                    <input type="text" id="ck-address" class="acc-input" placeholder="استان، شهر، خیابان، پلاک">
                </div>
                <div class="acc-form-row">
                    <div class="acc-form-group" style="flex:1">
                        <label>شهر <span class="acc-req">*</span></label>
                        <input type="text" id="ck-city" class="acc-input" placeholder="تهران">
                    </div>
                    <div class="acc-form-group" style="flex:1">
                        <label>کد پستی</label>
                        <input type="text" id="ck-postcode" class="acc-input" placeholder="1234567890" dir="ltr">
                    </div>
                </div>
                <div class="acc-form-group">
                    <label>توضیحات سفارش</label>
                    <textarea id="ck-note" class="acc-input" rows="2" placeholder="هر توضیحی برای ارسال..."></textarea>
                </div>
            </div>
        </div>
        <div class="acc-cart-footer">
            <div class="acc-cart-total-line">
                <span>مبلغ قابل پرداخت:</span>
                <strong class="acc-cart-grand">${We(A.total)}</strong>
            </div>
            <div id="ck-error" class="acc-checkout-error" style="display:none;"></div>
            <button class="acc-btn acc-btn--primary acc-btn--full" data-action="pay" id="ck-pay-btn">
                💳 پرداخت از درگاه
            </button>
        </div>`}_payingView(){return`
        <div class="acc-cart-header">
            <h3>💳 در حال اتصال به درگاه...</h3>
        </div>
        <div class="acc-cart-body" style="text-align:center;padding:40px 20px;">
            <div class="acc-cart-spinner"></div>
            <p style="margin-top:20px;color:#64748b;">لطفاً صبر کنید، در حال انتقال به درگاه پرداخت زرین‌پال هستید...</p>
        </div>`}_resultView(){const{success:e,ref:t,msg:s}=this._resultData||{};return`
        <div class="acc-cart-header">
            <h3>${e?"✅ پرداخت موفق":"❌ پرداخت ناموفق"}</h3>
            <button class="acc-cart-close-btn" data-action="close">✕</button>
        </div>
        <div class="acc-cart-body" style="text-align:center;padding:40px 20px;">
            <div style="font-size:56px;margin-bottom:16px;">${e?"🎉":"😔"}</div>
            ${e?`<p>سفارش شما با موفقیت ثبت شد.<br>کد پیگیری: <strong style="font-family:monospace;font-size:18px;color:#1d4ed8;">${Ue(t)}</strong></p>`:`<p style="color:#dc2626;">پرداخت انجام نشد.<br><small>${Ue(s||"لغو توسط کاربر")}</small></p>`}
        </div>
        <div class="acc-cart-footer">
            <button class="acc-btn acc-btn--${e?"primary":"secondary"} acc-btn--full" data-action="close">
                بستن
            </button>
        </div>`}_bindEvents(){if(!this._overlay)return;this._overlay.querySelector(".acc-cart-modal").addEventListener("click",t=>{var n,r;const s=t.target.closest("[data-action]");if(!s)return;const{action:a,id:i}=s.dataset;if(a==="close"){this.close();return}if(a==="back-to-cart"){this._step="cart",this._render();return}if(a==="checkout"){this._step="checkout",this._render();return}if(a==="pay"){this._submitPayment();return}if(a==="inc"){A.setQty(+i,(((n=A.items.find(o=>o.id===+i))==null?void 0:n.qty)||0)+1),this._render();return}if(a==="dec"){const o=((r=A.items.find(l=>l.id===+i))==null?void 0:r.qty)||0;A.setQty(+i,o-1),this._render();return}if(a==="remove"){A.remove(+i),this._render();return}})}async _submitPayment(){var d,h,u;const e=f=>{var m,b,v;return((v=(b=(m=this._overlay)==null?void 0:m.querySelector(f))==null?void 0:b.value)==null?void 0:v.trim())??""},t=e("#ck-name"),s=e("#ck-phone"),a=e("#ck-email"),i=e("#ck-address"),n=e("#ck-city"),r=e("#ck-note"),o=(d=this._overlay)==null?void 0:d.querySelector("#ck-error"),l=(h=this._overlay)==null?void 0:h.querySelector("#ck-pay-btn"),c=f=>{o&&(o.textContent=f,o.style.display="block")};if(!t)return c("نام الزامی است");if(!s||!/^09\d{9}$/.test(s))return c("شماره موبایل صحیح وارد کنید (مثال: 09123456789)");if(!i)return c("آدرس الزامی است");if(!n)return c("شهر الزامی است");l&&(l.disabled=!0,l.textContent="⏳ در حال ارسال...");try{const f=await this._api.post("public/orders/create",{items:A.items.map(m=>({id:m.id,qty:m.qty})),billing:{name:t,phone:s,email:a,address:i,city:n},note:r});(u=f==null?void 0:f.data)!=null&&u.payment_url?(this._step="paying",this._render(),A.clear(),setTimeout(()=>{window.location.href=f.data.payment_url},800)):(c((f==null?void 0:f.message)||"خطا در ایجاد سفارش"),l&&(l.disabled=!1,l.textContent="💳 پرداخت از درگاه"))}catch(f){c(f.message||"خطای شبکه"),l&&(l.disabled=!1,l.textContent="💳 پرداخت از درگاه")}}showResult(e,t,s){this._resultData={success:e,ref:t,msg:s},this._step="result",this._overlay?this._render():this.open()}}class qo extends x{constructor(){super(...arguments);g(this,"_products",[]);g(this,"_categories",[]);g(this,"_total",0);g(this,"_totalPages",1);g(this,"_page",1);g(this,"_perPage",24);g(this,"_search","");g(this,"_category","");g(this,"_orderby","date");g(this,"_order","DESC");g(this,"_viewMode","grid");g(this,"_cartModal",null);g(this,"_unsubCart",null)}async template(){return`
        <div class="wpp-wrap" dir="rtl">
            <!-- نوار ابزار -->
            <div class="wpp-topbar">
                <div class="wpp-search-box">
                    <span class="wpp-search-icon">🔍</span>
                    <input class="wpp-search-input" data-ref="searchInput" placeholder="جستجوی محصول..." autocomplete="off">
                </div>
                <select class="wpp-select" data-ref="catSel">
                    <option value="">همه دسته‌ها</option>
                </select>
                <select class="wpp-select" data-ref="sortSel">
                    <option value="date|DESC">جدیدترین</option>
                    <option value="date|ASC">قدیمی‌ترین</option>
                    <option value="title|ASC">نام (الف-ی)</option>
                    <option value="title|DESC">نام (ی-الف)</option>
                    <option value="price|ASC">ارزان‌ترین</option>
                    <option value="price|DESC">گران‌ترین</option>
                </select>
                <div class="wpp-view-toggle">
                    <button class="wpp-view-btn active" data-ref="gridBtn" title="شبکه‌ای">⊞</button>
                    <button class="wpp-view-btn" data-ref="listBtn" title="لیستی">☰</button>
                </div>
                <button class="wpp-cart-icon-btn" data-ref="cartIconBtn" title="سبد خرید">
                    🛒 <span class="wpp-cart-count" data-ref="cartCountBadge">0</span>
                </button>
                <span class="wpp-result-count" data-ref="countLbl"></span>
            </div>

            <!-- محتوا -->
            <div class="wpp-layout">
                <aside class="wpp-sidebar">
                    <div class="wpp-sidebar-title">📂 دسته‌بندی‌ها</div>
                    <ul class="wpp-cat-list" data-ref="catList">
                        <li class="wpp-cat-item active" data-slug="">همه محصولات</li>
                    </ul>
                </aside>
                <main class="wpp-main">
                    <div class="wpp-grid" data-ref="grid"></div>
                    <div class="wpp-pagination" data-ref="pagination"></div>
                </main>
            </div>

            <!-- Modal -->
            <div class="wpp-modal-overlay" data-ref="modal" style="display:none;">
                <div class="wpp-modal" data-ref="modalBody"></div>
            </div>
        </div>`}async afterRender(){this._cartModal=new Ro(this.api),this._unsubCart=A.onChange(()=>this._updateCartBadge()),this._updateCartBadge(),this._checkPaymentReturn(),await this._loadCategories(),await this._loadProducts(),this._bindTopbar()}_updateCartBadge(){const t=this.ref("cartCountBadge");if(!t)return;const s=A.count;t.textContent=s,t.style.display=s>0?"inline-flex":"none";const a=this.ref("cartIconBtn");a&&a.classList.toggle("has-items",s>0)}_checkPaymentReturn(){const t=new URLSearchParams(window.location.search),s=t.get("payment");if(!s)return;const a=window.location.pathname;window.history.replaceState({},"",a),s==="success"?this._cartModal.showResult(!0,t.get("ref")||""):s==="cancelled"?this._cartModal.showResult(!1,null,"پرداخت توسط شما لغو شد"):s==="failed"&&this._cartModal.showResult(!1,null,"پرداخت ناموفق بود (کد: "+(t.get("code")||"-")+")")}async _loadCategories(){try{const t=await this.api.get("wp/categories");this._categories=(t==null?void 0:t.data)??[],this._renderCatList(),this._fillCatSelect()}catch{}}async _loadProducts(){const t=this.ref("grid");t.innerHTML=this._skeletons();try{const s=await this.api.get("wp/products",{page:this._page,per_page:this._perPage,search:this._search,category:this._category,orderby:this._orderby,order:this._order});this._products=(s==null?void 0:s.data)??[],this._total=(s==null?void 0:s.total)??0,this._totalPages=(s==null?void 0:s.total_pages)??1,this._renderGrid(),this._renderPagination(),this._updateCount()}catch(s){t.innerHTML=`<div class="acc-error" style="grid-column:1/-1;">⚠️ ${this.escape(s.message)}</div>`}}_renderCatList(){const t=this.ref("catList"),s=`<li class="wpp-cat-item ${this._category?"":"active"}" data-slug="">همه محصولات <span class="wpp-cat-count">${this._total}</span></li>`,a=this._categories.map(i=>`
        <li class="wpp-cat-item ${this._category===i.slug?"active":""}" data-slug="${i.slug}">
            ${this.escape(i.name)} <span class="wpp-cat-count">${i.count}</span>
        </li>`).join("");t.innerHTML=s+a,t.querySelectorAll(".wpp-cat-item").forEach(i=>{i.addEventListener("click",()=>{this._category=i.dataset.slug,this._page=1,t.querySelectorAll(".wpp-cat-item").forEach(n=>n.classList.remove("active")),i.classList.add("active"),this.ref("catSel").value=this._category,this._loadProducts()})})}_fillCatSelect(){const t=this.ref("catSel");t.innerHTML='<option value="">همه دسته‌ها</option>'+this._categories.map(s=>`<option value="${s.slug}">${this.escape(s.name)}</option>`).join(""),t.value=this._category}_renderGrid(){const t=this.ref("grid");if(t.className=this._viewMode==="list"?"wpp-list":"wpp-grid",!this._products.length){t.innerHTML='<div class="wpp-empty" style="grid-column:1/-1;"><div class="wpp-empty-icon">🛒</div><div>محصولی یافت نشد</div></div>';return}t.innerHTML=this._products.map(s=>this._card(s)).join(""),t.querySelectorAll(".wpp-card").forEach(s=>{s.addEventListener("click",a=>{const i=a.target.closest(".wpp-cart-btn");if(i){const r=this._products.find(o=>o.id==i.dataset.id);r&&this._addToCart(r,i);return}const n=this._products.find(r=>r.id==s.dataset.id);n&&this._openModal(n)})})}_card(t){const s=t.image?`<img src="${this.escape(t.image)}" alt="${this.escape(t.name)}" loading="lazy" class="wpp-card-img">`:'<div class="wpp-card-img wpp-no-img">📦</div>',a=t.on_sale?'<span class="wpp-badge wpp-badge--sale">تخفیف</span>':t.in_stock?"":'<span class="wpp-badge wpp-badge--outstock">ناموجود</span>',i=this._stars(parseFloat(t.average_rating??0)),n=this._priceHtml(t),r=(t.categories??[]).map(o=>`<span class="wpp-card-cat">${this.escape(o.name)}</span>`).join("");return this._viewMode==="list"?`
        <div class="wpp-card wpp-card--list" data-id="${t.id}">
            <div class="wpp-card-img-wrap">${s}${a}</div>
            <div class="wpp-card-body">
                <div class="wpp-card-cats">${r}</div>
                <h3 class="wpp-card-title">${this.escape(t.name)}</h3>
                ${t.short_desc?`<p class="wpp-card-desc">${this.escape(t.short_desc.slice(0,120))}${t.short_desc.length>120?"…":""}</p>`:""}
                ${t.sku?`<div class="wpp-card-sku">SKU: ${this.escape(t.sku)}</div>`:""}
                <div class="wpp-card-footer">
                    <div class="wpp-card-price">${n}</div>
                    ${t.in_stock?`<button class="wpp-cart-btn" data-id="${t.id}">🛒 افزودن به سبد</button>`:'<span class="wpp-out-label">ناموجود</span>'}
                </div>
            </div>
        </div>`:`
        <div class="wpp-card" data-id="${t.id}">
            <div class="wpp-card-img-wrap">
                ${s}${a}
                <div class="wpp-card-overlay"><button class="wpp-quick-view">👁 مشاهده سریع</button></div>
            </div>
            <div class="wpp-card-body">
                <div class="wpp-card-cats">${r}</div>
                <h3 class="wpp-card-title">${this.escape(t.name)}</h3>
                ${i?`<div class="wpp-stars">${i} <small>(${t.rating_count})</small></div>`:""}
                <div class="wpp-card-footer">
                    <div class="wpp-card-price">${n}</div>
                    ${t.in_stock?`<button class="wpp-cart-btn" data-id="${t.id}">🛒</button>`:'<span class="wpp-out-label">ناموجود</span>'}
                </div>
            </div>
        </div>`}_renderPagination(){const t=this.ref("pagination");if(this._totalPages<=1){t.innerHTML="";return}const s=[];for(let a=1;a<=this._totalPages;a++)a===1||a===this._totalPages||a>=this._page-2&&a<=this._page+2?s.push(a):s[s.length-1]!=="…"&&s.push("…");t.innerHTML=`<button class="wpp-page-btn" data-p="${this._page-1}" ${this._page<=1?"disabled":""}>‹</button>`+s.map(a=>a==="…"?'<span class="wpp-page-dots">…</span>':`<button class="wpp-page-btn ${a===this._page?"active":""}" data-p="${a}">${a}</button>`).join("")+`<button class="wpp-page-btn" data-p="${this._page+1}" ${this._page>=this._totalPages?"disabled":""}>›</button>`,t.querySelectorAll(".wpp-page-btn:not([disabled])").forEach(a=>{a.addEventListener("click",()=>{this._page=+a.dataset.p,this._loadProducts()})})}_updateCount(){const t=this.ref("countLbl");if(!t)return;const s=(this._page-1)*this._perPage+1,a=Math.min(this._page*this._perPage,this._total);t.textContent=this._total?`نمایش ${s}–${a} از ${this._total} محصول`:"محصولی یافت نشد"}_openModal(t){var o,l,c;const s=this.ref("modal"),a=this.ref("modalBody"),i=this._priceHtml(t),n=this._stars(parseFloat(t.average_rating??0)),r=[t.image,...t.gallery??[]].filter(Boolean);a.innerHTML=`
        <button class="wpp-modal-close" data-ref="closeBtn">✕</button>
        <div class="wpp-modal-inner">
            <div class="wpp-modal-images">
                ${t.image?`<img id="wpp-main-img" src="${this.escape(t.image)}" class="wpp-modal-main-img">`:'<div class="wpp-modal-main-img wpp-no-img-lg">📦</div>'}
                ${r.length>1?`<div class="wpp-gallery">${r.map((d,h)=>`<img src="${this.escape(d)}" class="wpp-gallery-thumb ${h===0?"active":""}"
                         onclick="document.getElementById('wpp-main-img').src='${this.escape(d)}';
                         this.closest('.wpp-gallery').querySelectorAll('.wpp-gallery-thumb').forEach(t=>t.classList.remove('active'));this.classList.add('active');">`).join("")}</div>`:""}
            </div>
            <div class="wpp-modal-info">
                <div class="wpp-card-cats">${(t.categories??[]).map(d=>`<span class="wpp-card-cat">${this.escape(d.name)}</span>`).join("")}</div>
                <h2 class="wpp-modal-title">${this.escape(t.name)}</h2>
                ${n?`<div class="wpp-stars wpp-stars--lg">${n} <small>${t.rating_count} نظر</small></div>`:""}
                ${t.sku?`<div class="wpp-modal-sku">کد محصول: <strong>${this.escape(t.sku)}</strong></div>`:""}
                <div class="wpp-modal-price">${i}</div>
                <div class="wpp-stock-status ${t.in_stock?"wpp-instock":"wpp-outstock"}">
                    ${t.in_stock?`✅ موجود در انبار${t.stock_qty!=null?` (${t.stock_qty} عدد)`:""}`:"❌ ناموجود"}
                </div>
                ${t.short_desc?`<div class="wpp-modal-short-desc">${this.escape(t.short_desc)}</div>`:""}
                ${t.in_stock?`
                <div class="wpp-modal-actions">
                    <div class="wpp-qty-wrap">
                        <button class="wpp-qty-btn" data-ref="qtyMinus">−</button>
                        <input type="number" class="wpp-qty-input" data-ref="qtyInp" value="1" min="1">
                        <button class="wpp-qty-btn" data-ref="qtyPlus">+</button>
                    </div>
                    <button class="wpp-add-cart-btn">🛒 افزودن به سبد خرید</button>
                </div>`:""}
                ${(t.tags??[]).length?`<div class="wpp-modal-tags">${t.tags.map(d=>`<span class="wpp-tag">${this.escape(d)}</span>`).join("")}</div>`:""}
                ${t.permalink?`<a class="wpp-view-link" href="${this.escape(t.permalink)}" target="_blank">مشاهده در فروشگاه ↗</a>`:""}
            </div>
        </div>
        ${t.description?`<div class="wpp-modal-desc"><h4>توضیحات محصول</h4><div class="wpp-desc-text">${this.escape(t.description)}</div></div>`:""}`,this._bindRefs(),s.style.display="flex",document.body.style.overflow="hidden",this.ref("closeBtn").addEventListener("click",()=>this._closeModal()),s.addEventListener("click",d=>{d.target===s&&this._closeModal()}),(o=this.ref("qtyMinus"))==null||o.addEventListener("click",()=>{const d=this.ref("qtyInp");+d.value>1&&(d.value=+d.value-1)}),(l=this.ref("qtyPlus"))==null||l.addEventListener("click",()=>{const d=this.ref("qtyInp");d.value=+d.value+1}),(c=a.querySelector(".wpp-add-cart-btn"))==null||c.addEventListener("click",()=>{var h;const d=parseInt(((h=this.ref("qtyInp"))==null?void 0:h.value)??"1",10)||1;this._addToCart(t,null,d),this._closeModal()})}_closeModal(){this.ref("modal").style.display="none",document.body.style.overflow=""}_addToCart(t,s,a=1){if(A.add(t,a),s){const i=s.innerHTML;s.innerHTML="✓ اضافه شد",s.disabled=!0,setTimeout(()=>{s&&(s.innerHTML=i,s.disabled=!1)},1200)}}_bindTopbar(){let t;this.ref("searchInput").addEventListener("input",s=>{clearTimeout(t),t=setTimeout(()=>{this._search=s.target.value.trim(),this._page=1,this._loadProducts()},400)}),this.ref("catSel").addEventListener("change",s=>{this._category=s.target.value,this._page=1,this._renderCatList(),this._loadProducts()}),this.ref("sortSel").addEventListener("change",s=>{[this._orderby,this._order]=s.target.value.split("|"),this._page=1,this._loadProducts()}),this.ref("gridBtn").addEventListener("click",()=>{this._viewMode="grid",this.ref("gridBtn").classList.add("active"),this.ref("listBtn").classList.remove("active"),this._renderGrid()}),this.ref("listBtn").addEventListener("click",()=>{this._viewMode="list",this.ref("listBtn").classList.add("active"),this.ref("gridBtn").classList.remove("active"),this._renderGrid()}),document.addEventListener("keydown",s=>{s.key==="Escape"&&this._closeModal()}),this.ref("cartIconBtn").addEventListener("click",()=>this._cartModal.open())}_priceHtml(t){const s=a=>a?new Intl.NumberFormat("fa-IR").format(Math.round(+a))+" تومان":"";if(t.on_sale&&t.sale_price&&t.regular_price){const a=Math.round((1-t.sale_price/t.regular_price)*100);return`<span class="wpp-price-sale">${s(t.sale_price)}</span>
                    <span class="wpp-price-old">${s(t.regular_price)}</span>
                    <span class="wpp-price-pct">−${a}%</span>`}return t.price?`<span class="wpp-price-normal">${s(t.price)}</span>`:'<span class="wpp-price-contact">تماس بگیرید</span>'}_stars(t){return t?"★".repeat(Math.floor(t))+(t-Math.floor(t)>=.5?"½":"")+"☆".repeat(5-Math.floor(t)-(t-Math.floor(t)>=.5?1:0)):""}_skeletons(t=8){return Array.from({length:t},()=>`
        <div class="wpp-skeleton">
            <div class="wpp-sk-img sk-anim"></div>
            <div class="wpp-sk-line sk-anim" style="width:80%"></div>
            <div class="wpp-sk-line sk-anim" style="width:50%"></div>
        </div>`).join("")}escape(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}destroy(){var t,s,a;(t=this._unsubCart)==null||t.call(this),(s=this._cartModal)==null||s.close(),(a=super.destroy)==null||a.call(this)}}class Ho extends x{constructor(){super(...arguments);g(this,"_categories",[])}async template(){return`
        <div class="acc-section-wrap" dir="rtl">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📂 دسته‌بندی‌های محصولات</h2>
                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄 بروزرسانی</button>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){this.on(this.ref("refreshBtn"),"click",()=>this._load()),await this._load()}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const t=await this.api.get("wp/categories");this._categories=(t==null?void 0:t.data)??[],this._render()}catch(t){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(t.message)}</div>`}}_render(){const t=this.ref("wrap");if(!this._categories.length){t.innerHTML='<div class="acc-empty">دسته‌بندی‌ای یافت نشد</div>';return}t.innerHTML=`
        <div class="wpp-cat-grid">
            ${this._categories.map(s=>`
            <div class="wpp-cat-card">
                <div class="wpp-cat-card-img">
                    ${s.image?`<img src="${this.escape(s.image)}" alt="${this.escape(s.name)}">`:'<div class="wpp-cat-card-placeholder">📂</div>'}
                </div>
                <div class="wpp-cat-card-body">
                    <h3 class="wpp-cat-card-title">${this.escape(s.name)}</h3>
                    ${s.description?`<p class="wpp-cat-card-desc">${this.escape(s.description.slice(0,80))}${s.description.length>80?"…":""}</p>`:""}
                    <span class="wpp-cat-card-count">${s.count} محصول</span>
                </div>
            </div>`).join("")}
        </div>`}escape(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const zt=[{key:"shop",icon:"🛍️",title:"محصولات",Class:qo},{key:"categories",icon:"📂",title:"دسته‌بندی‌ها",Class:Ho}];class ca extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._active="shop",this._sections={}}async template(){const t=zt.map(a=>`
            <button class="wpp-sec-tab ${a.key===this._active?"wpp-sec-tab--active":""}"
                    data-section="${a.key}" type="button">
                ${a.icon} ${a.title}
            </button>
        `).join(""),s=zt.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>
        `).join("");return`
            <div class="wpp-sec-tabs" data-ref="navBar">${t}</div>
            <div class="wpp-sec-panels">${s}</div>
        `}async afterRender(){this.ref("navBar").querySelectorAll(".wpp-sec-tab").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".wpp-sec-tab").forEach(s=>s.classList.toggle("wpp-sec-tab--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=zt.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(ca,"title","🛍️ محصولات فروشگاه"),E.register("wpproducts",ca);class Bo extends x{constructor(){super(...arguments);g(this,"_rooms",[]);g(this,"_activeRoom",null);g(this,"_lastMsgId",0);g(this,"_pollTimer",null);g(this,"_filter","open");g(this,"_source","")}async template(){return`
        <div class="chat-support-wrap" dir="rtl">
            <div class="chat-support-layout">
                <!-- ستون چپ: لیست گفتگوها -->
                <aside class="chat-rooms-panel">
                    <div class="chat-rooms-header">
                        <h3>💬 Live Chat</h3>
                        <select class="acc-select acc-select--sm" data-ref="sourceSel" title="فیلتر پورتال" style="max-width:110px;">
                            <option value="">همه پورتال‌ها</option>
                            <option value="melk">🏠 اقتصاد ملک</option>
                            <option value="shop">🛒 فروشگاه</option>
                            <option value="service">🔧 خدمات</option>
                            <option value="erp">💼 ERP</option>
                            <option value="website">🌐 سایت</option>
                        </select>
                        <select class="acc-select acc-select--sm" data-ref="filterSel">
                            <option value="open">باز</option>
                            <option value="pending">در انتظار</option>
                            <option value="closed">بسته</option>
                            <option value="all">همه</option>
                        </select>
                        <button class="acc-btn acc-btn--xs acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                    </div>
                    <div class="chat-rooms-list" data-ref="roomsList">
                        <div class="acc-loading">⏳ بارگذاری...</div>
                    </div>
                </aside>

                <!-- ستون راست: پنجره گفتگو -->
                <main class="chat-conversation-panel" data-ref="convPanel">
                    <div class="chat-empty-state">
                        <div style="font-size:48px;margin-bottom:12px;">💬</div>
                        <div style="color:#94a3b8;font-size:14px;">یک گفتگو را از لیست انتخاب کنید</div>
                    </div>
                </main>
            </div>
        </div>`}async afterRender(){this.on(this.ref("refreshBtn"),"click",()=>this._loadRooms()),this.on(this.ref("filterSel"),"change",t=>{this._filter=t.target.value,this._loadRooms()}),this.on(this.ref("sourceSel"),"change",t=>{this._source=t.target.value,this._loadRooms()}),this.listen("chat:support:openRoom",async({conversationId:t})=>{if(!t)return;await this._loadRooms();let s=this._rooms.find(a=>+a.id==+t);if(!s)try{const a=await this.api.get(`chat/support/rooms/${t}`);s=a==null?void 0:a.data}catch{}s&&await this._openRoom(s)}),await this._loadRooms(),this._startPoll()}async _loadRooms(){try{const t={status:this._filter};this._source&&(t.source=this._source);const s=await this.api.get("chat/support/rooms",t);this._rooms=(s==null?void 0:s.data)??[],this._renderRooms()}catch(t){this.ref("roomsList").innerHTML=`<div class="acc-error">❌ ${this.escape(t.message)}</div>`}}_renderRooms(){const t=this.ref("roomsList");if(!this._rooms.length){t.innerHTML='<div class="acc-empty" style="padding:20px;text-align:center;color:#94a3b8;">گفتگویی وجود ندارد</div>';return}t.innerHTML=this._rooms.map(s=>{var m;const a=((m=this._activeRoom)==null?void 0:m.id)==s.id,i={open:"chat-status--open",closed:"chat-status--closed"}[s.status]??"",n=this._relTime(s.updated_at||s.created_at),r=s.visitor_name||"بازدیدکننده",o=s.tracking_code?`<span style="font-size:9px;background:#dbeafe;color:#1d4ed8;border-radius:3px;padding:1px 4px;margin-right:4px;font-family:monospace;font-weight:bold;">${this.escape(s.tracking_code)}</span>`:"",l=+s.visitor_msg_count||0,c={melk:["🏠","#0ea5e9","#f0f9ff"],shop:["🛒","#8b5cf6","#f5f3ff"],service:["🔧","#10b981","#f0fdf4"],erp:["💼","#3b82f6","#eff6ff"],website:["🌐","#6366f1","#eef2ff"]},[d,h,u]=c[s.source]||["💬","#64748b","#f1f5f9"],f=s.source?`<span style="font-size:9px;background:${u};color:${h};border-radius:10px;padding:1px 6px;font-weight:700;">${d} ${s.source}</span>`:"";return`
            <div class="chat-room-item ${a?"active":""}" data-id="${s.id}">
                <div class="chat-room-avatar" style="background:${s.status==="closed"?"#f1f5f9":"#dbeafe"};">
                    ${r.charAt(0).toUpperCase()}
                </div>
                <div class="chat-room-info">
                    <div class="chat-room-name">${o}${this.escape(r)}</div>
                    <div class="chat-room-last" style="display:flex;align-items:center;gap:4px;">${f}<span>${this.escape((s.last_body||"").slice(0,32))}</span></div>
                </div>
                <div class="chat-room-meta">
                    ${l?`<span class="chat-unread-badge">${l}</span>`:`<span class="chat-status-badge ${i}">${this._statusLabel(s.status)}</span>`}
                    <small style="color:#94a3b8;font-size:10px;">${n}</small>
                </div>
            </div>`}).join(""),t.querySelectorAll(".chat-room-item").forEach(s=>{s.addEventListener("click",()=>{const a=this._rooms.find(i=>i.id==s.dataset.id);a&&this._openRoom(a)})})}async _openRoom(t){var d,h,u;this._activeRoom=t,this._lastMsgId=0,this._renderRooms();const s=this.ref("convPanel"),a=t.visitor_name||"بازدیدکننده",i={melk:"🏠 اقتصاد ملک",shop:"🛒 فروشگاه",service:"🔧 خدمات",erp:"💼 ERP",website:"🌐 سایت"},n={melk:"#0ea5e9",shop:"#8b5cf6",service:"#10b981",erp:"#3b82f6",website:"#6366f1"},r={melk:"#f0f9ff",shop:"#f5f3ff",service:"#f0fdf4",erp:"#eff6ff",website:"#eef2ff"},o=t.source?i[t.source]||t.source:null,l=n[t.source]||"#64748b",c=r[t.source]||"#f8fafc";s.innerHTML=`
        <div class="chat-conv-header">
            <div class="chat-conv-avatar" style="background:${c};color:${l};font-weight:700;">
                ${a.charAt(0).toUpperCase()}
            </div>
            <div class="chat-conv-info">
                <strong>${this.escape(a)}</strong>
                <div style="display:flex;gap:8px;flex-wrap:wrap;margin-top:2px;">
                    ${o?`<small style="color:${l};background:${c};padding:2px 8px;border-radius:12px;font-weight:700;">${o}</small>`:""}
                    ${t.visitor_phone?`<small style="color:#166534;background:#dcfce7;padding:1px 6px;border-radius:4px;">📱 ${this.escape(t.visitor_phone)}</small>`:""}
                    ${t.visitor_email?`<small style="color:#64748b;">📧 ${this.escape(t.visitor_email)}</small>`:""}
                    ${t.tracking_code?`<small style="color:#1d4ed8;font-family:monospace;font-weight:bold;background:#dbeafe;padding:1px 6px;border-radius:4px;">🎫 ${this.escape(t.tracking_code)}</small>`:""}
                    <small style="color:#94a3b8;">🌐 ${this.escape(t.visitor_ip||"-")}</small>
                </div>
            </div>
            <div style="display:flex;gap:6px;">
                <span class="chat-status-badge ${this._statusCls(t.status)}">${this._statusLabel(t.status)}</span>
                ${t.status!=="closed"?'<button class="acc-btn acc-btn--xs acc-btn--danger" data-ref="closeRoomBtn">🔒 بستن</button>':""}
            </div>
        </div>
        <div class="chat-messages" data-ref="messages"></div>
        <div class="chat-input-area" ${t.status==="closed"?'style="display:none;"':""}>
            <textarea class="chat-textarea" data-ref="replyInput" placeholder="پیام خود را بنویسید..." rows="2"></textarea>
            <button class="chat-send-btn" data-ref="sendBtn">ارسال ➤</button>
        </div>`,this._bindRefs(),(d=this.ref("sendBtn"))==null||d.addEventListener("click",()=>this._sendReply()),(h=this.ref("replyInput"))==null||h.addEventListener("keydown",f=>{f.key==="Enter"&&!f.shiftKey&&(f.preventDefault(),this._sendReply())}),(u=this.ref("closeRoomBtn"))==null||u.addEventListener("click",()=>this._closeRoom(t.id)),await this._loadMessages()}async _loadMessages(){var t;if(this._activeRoom)try{const s=await this.api.get(`chat/support/rooms/${this._activeRoom.id}`,{last_id:this._lastMsgId}),a=((t=s==null?void 0:s.data)==null?void 0:t.messages)??[],i=this.ref("messages");if(!i)return;a.forEach(n=>{n.id>this._lastMsgId&&(this._lastMsgId=+n.id,this._appendMsg(i,n))}),i.scrollTop=i.scrollHeight}catch{}}_appendMsg(t,s){const a=s.sender_type==="agent"||s.sender_type==="user"&&s.msg_type!=="system",i=s.sender_type==="system"||s.msg_type==="system",n=new Date(s.created_at).toLocaleTimeString("fa-IR",{hour:"2-digit",minute:"2-digit"}),r=document.createElement("div");i?(r.className="chat-msg chat-msg--system",r.innerHTML=`<span>${this.escape(s.body)}</span>`):(r.className=`chat-msg ${a?"chat-msg--out":"chat-msg--in"}`,r.innerHTML=`
            <div class="chat-bubble">
                ${this.escape(s.body||s.message)}
                <span class="chat-time">${n}</span>
            </div>`),t.appendChild(r)}async _sendReply(){if(!this._activeRoom)return;const t=this.ref("replyInput"),s=t==null?void 0:t.value.trim();if(s){t.value="";try{await this.api.post(`chat/support/rooms/${this._activeRoom.id}/reply`,{body:s}),await this._loadMessages()}catch(a){alert(a.message)}}}async _closeRoom(t){confirm("این گفتگو بسته شود؟")&&(await this.api.post(`chat/support/rooms/${t}/close`,{}),await this._loadRooms(),this._activeRoom=null,this.ref("convPanel").innerHTML='<div class="chat-empty-state"><div style="font-size:48px;">✅</div><div style="color:#94a3b8;">گفتگو بسته شد</div></div>')}_startPoll(){this._pollTimer=setInterval(async()=>{await this._loadRooms(),this._activeRoom&&await this._loadMessages()},5e3)}_statusLabel(t){return{open:"باز",pending:"در انتظار",closed:"بسته"}[t]??t}_statusCls(t){return{open:"chat-status--open",pending:"chat-status--pending",closed:"chat-status--closed"}[t]??""}_relTime(t){const s=Math.floor((Date.now()-new Date(t))/1e3);return s<60?"همین الان":s<3600?`${Math.floor(s/60)} دقیقه پیش`:s<86400?`${Math.floor(s/3600)} ساعت پیش`:`${Math.floor(s/86400)} روز پیش`}escape(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}destroy(){var t;clearInterval(this._pollTimer),(t=super.destroy)==null||t.call(this)}}class zo extends x{constructor(){super(...arguments);g(this,"_rooms",[]);g(this,"_activeRoom",null);g(this,"_lastMsgId",0);g(this,"_globalLast",0);g(this,"_pollTimer",null)}async template(){return`
        <div class="chat-support-wrap" dir="rtl">
            <div class="chat-support-layout">
                <!-- لیست اتاق‌ها -->
                <aside class="chat-rooms-panel">
                    <div class="chat-rooms-header">
                        <h3>💼 چت داخلی</h3>
                        <button class="acc-btn acc-btn--xs acc-btn--primary" data-ref="newChatBtn">➕ جدید</button>
                    </div>
                    <div class="chat-rooms-list" data-ref="roomsList">
                        <div class="acc-loading">⏳ بارگذاری...</div>
                    </div>
                </aside>
                <!-- گفتگو -->
                <main class="chat-conversation-panel" data-ref="convPanel">
                    <div class="chat-empty-state">
                        <div style="font-size:48px;">💼</div>
                        <div style="color:#94a3b8;font-size:14px;">یک گفتگو را انتخاب کنید</div>
                    </div>
                </main>
            </div>

            <!-- Modal: گفتگوی جدید -->
            <div class="acc-modal-overlay" data-ref="newChatModal" style="display:none;">
                <div class="acc-modal" style="max-width:400px;">
                    <h3 style="margin:0 0 16px;font-size:15px;">💬 گفتگوی جدید</h3>
                    <label style="display:flex;flex-direction:column;gap:4px;font-size:13px;margin-bottom:10px;">نوع
                        <select class="acc-select" data-ref="roomType">
                            <option value="direct">مستقیم (یک نفر)</option>
                            <option value="group">گروهی</option>
                        </select>
                    </label>
                    <label style="display:flex;flex-direction:column;gap:4px;font-size:13px;margin-bottom:10px;">نام گروه (اختیاری)
                        <input class="acc-input" data-ref="roomName" placeholder="مثلاً: تیم فروش">
                    </label>
                    <label style="display:flex;flex-direction:column;gap:4px;font-size:13px;margin-bottom:14px;">کاربران (ID با کاما)
                        <input class="acc-input" data-ref="roomMembers" placeholder="2,5,8">
                    </label>
                    <div style="display:flex;gap:8px;">
                        <button class="acc-btn acc-btn--primary" data-ref="createRoomBtn">ساخت</button>
                        <button class="acc-btn acc-btn--secondary" data-ref="cancelNewChat">لغو</button>
                    </div>
                </div>
            </div>
        </div>`}async afterRender(){this.on(this.ref("newChatBtn"),"click",()=>{this.ref("newChatModal").style.display="flex"}),this.on(this.ref("cancelNewChat"),"click",()=>{this.ref("newChatModal").style.display="none"}),this.on(this.ref("createRoomBtn"),"click",()=>this._createRoom()),await this._loadRooms(),this._startPoll()}async _loadRooms(){try{const t=await this.api.get("chat/rooms");this._rooms=(t==null?void 0:t.data)??[],this._renderRooms()}catch{}}_renderRooms(){const t=this.ref("roomsList");if(!this._rooms.length){t.innerHTML='<div class="acc-empty" style="padding:16px;text-align:center;color:#94a3b8;font-size:13px;">گفتگویی ندارید<br><small>با دکمه ➕ شروع کنید</small></div>';return}t.innerHTML=this._rooms.map(s=>{var o;const a=((o=this._activeRoom)==null?void 0:o.id)==s.id,i=+s.unread_count||0,n=s.type==="group"?"👥":"💬",r=s.last_msg_at?this._relTime(s.last_msg_at):"";return`
            <div class="chat-room-item ${a?"active":""}" data-id="${s.id}">
                <div class="chat-room-avatar">${n}</div>
                <div class="chat-room-info">
                    <div class="chat-room-name">${this.escape(s.name||`اتاق #${s.id}`)}</div>
                    <div class="chat-room-last">${this.escape((s.last_body||"").slice(0,40))}</div>
                </div>
                <div class="chat-room-meta">
                    ${i?`<span class="chat-unread-badge">${i}</span>`:""}
                    <small style="color:#94a3b8;font-size:10px;">${r}</small>
                </div>
            </div>`}).join(""),t.querySelectorAll(".chat-room-item").forEach(s=>{s.addEventListener("click",()=>{const a=this._rooms.find(i=>i.id==s.dataset.id);a&&this._openRoom(a)})})}async _openRoom(t){this._activeRoom=t,this._lastMsgId=0,this._renderRooms();const s=this.ref("convPanel"),a=t.type==="group"?"👥":"💬";s.innerHTML=`
        <div class="chat-conv-header">
            <div class="chat-conv-avatar">${a}</div>
            <div class="chat-conv-info">
                <strong>${this.escape(t.name||`اتاق #${t.id}`)}</strong>
                <small style="color:#94a3b8;">${t.type==="group"?"گروهی":"مستقیم"}</small>
            </div>
        </div>
        <div class="chat-messages" data-ref="messages"></div>
        <div class="chat-input-area">
            <textarea class="chat-textarea" data-ref="msgInput" placeholder="پیام..." rows="2"></textarea>
            <button class="chat-send-btn" data-ref="sendBtn">ارسال ➤</button>
        </div>`,this._bindRefs(),this.on(this.ref("sendBtn"),"click",()=>this._sendMsg()),this.on(this.ref("msgInput"),"keydown",i=>{i.key==="Enter"&&!i.shiftKey&&(i.preventDefault(),this._sendMsg())}),await this._loadMessages(),this.api.post(`chat/rooms/${t.id}/read`,{}).catch(()=>{})}async _loadMessages(){if(this._activeRoom)try{const t=await this.api.get(`chat/rooms/${this._activeRoom.id}/messages`),s=(t==null?void 0:t.data)??[],a=this.ref("messages");if(!a)return;a.innerHTML="",s.forEach(i=>{this._appendMsg(a,i),this._lastMsgId=Math.max(this._lastMsgId,+i.id)}),a.scrollTop=a.scrollHeight}catch{}}_appendMsg(t,s){const a=s.sender_type==="user"&&+s.sender_id===(window.accCurrentUserId||0),i=s.msg_type==="system",n=new Date(s.created_at).toLocaleTimeString("fa-IR",{hour:"2-digit",minute:"2-digit"}),r=document.createElement("div");i?(r.className="chat-msg chat-msg--system",r.innerHTML=`<span>${this.escape(s.body)}</span>`):(r.className=`chat-msg ${a?"chat-msg--out":"chat-msg--in"}`,r.innerHTML=`
            ${a?"":`<div class="chat-sender-name">${this.escape(s.sender_name||s.user_display_name||"")}</div>`}
            <div class="chat-bubble">${this.escape(s.body)}<span class="chat-time">${n}</span></div>`),t.appendChild(r)}async _sendMsg(){if(!this._activeRoom)return;const t=this.ref("msgInput"),s=t==null?void 0:t.value.trim();if(s){t.value="";try{await this.api.post(`chat/rooms/${this._activeRoom.id}/messages`,{body:s}),await this._loadMessages()}catch(a){alert(a.message)}}}async _createRoom(){const t=this.ref("roomType").value,s=this.ref("roomName").value.trim(),a=this.ref("roomMembers").value.split(",").map(i=>+i.trim()).filter(Boolean);if(!a.length){alert("حداقل یک کاربر وارد کنید");return}try{const i=await this.api.post("chat/rooms",{type:t,name:s,members:a});this.ref("newChatModal").style.display="none",await this._loadRooms();const n=this._rooms.find(r=>{var o;return r.id==((o=i.data)==null?void 0:o.room_id)});n&&this._openRoom(n)}catch(i){alert(i.message)}}_startPoll(){this._pollTimer=setInterval(async()=>{var t;try{const s=await this.api.get("chat/poll",{last_id:this._globalLast}),a=((t=s==null?void 0:s.data)==null?void 0:t.messages)??[];if(a.length){if(this._globalLast=Math.max(...a.map(i=>+i.id)),this._activeRoom){const i=a.filter(n=>n.room_id==this._activeRoom.id);if(i.length){const n=this.ref("messages");n&&(i.forEach(r=>{+r.id>this._lastMsgId&&(this._appendMsg(n,r),this._lastMsgId=+r.id)}),n.scrollTop=n.scrollHeight)}}await this._loadRooms()}}catch{}},4e3)}_relTime(t){const s=Math.floor((Date.now()-new Date(t))/1e3);return s<60?"الان":s<3600?`${Math.floor(s/60)}د`:`${Math.floor(s/3600)}س`}escape(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}destroy(){var t;clearInterval(this._pollTimer),(t=super.destroy)==null||t.call(this)}}class jo extends x{async template(){return`
        <div class="acc-section-wrap" dir="rtl">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">⚙️ تنظیمات ویجت چت</h2>
                <button class="acc-btn acc-btn--primary" data-ref="saveBtn">💾 ذخیره</button>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._loadSettings(),this.on(this.ref("saveBtn"),"click",()=>this._save())}async _loadSettings(){try{const e=await this.api.get("chat/settings"),t=(e==null?void 0:e.data)??{};this.ref("wrap").innerHTML=`
            <div style="max-width:520px;display:flex;flex-direction:column;gap:14px;padding:8px 0;">
                ${this._field("site_name","نام سایت / پشتیبانی",t.site_name,"text","پشتیبانی آنلاین")}
                ${this._field("welcome_msg","پیام خوش‌آمدگویی",t.welcome_msg,"text","سلام! چطور می‌تونم کمکتون کنم؟")}
                ${this._field("phone","شماره تلفن",t.phone,"text","021xxxxxxxx")}
                ${this._field("whatsapp","شماره واتساپ",t.whatsapp,"text","989xxxxxxxxx")}
                ${this._field("telegram","آیدی تلگرام",t.telegram,"text","username")}
                ${this._field("instagram","آیدی اینستاگرام",t.instagram,"text","username")}
                <label style="display:flex;align-items:center;gap:8px;font-size:13px;">
                    <input type="checkbox" data-ref="enabled" ${t.enabled?"checked":""}>
                    فعال بودن ویجت چت
                </label>
                <div class="acc-alert acc-alert--info" style="font-size:12px;background:#eff6ff;border:1px solid #bfdbfe;padding:10px 12px;border-radius:8px;color:#1e40af;">
                    💡 ویجت چت به صورت خودکار در گوشه پایین‌راست همه صفحات سایت نمایش داده می‌شود.
                </div>
            </div>`,this._bindRefs()}catch(e){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(e.message)}</div>`}}_field(e,t,s,a,i){return`<label style="display:flex;flex-direction:column;gap:5px;font-size:13px;color:#475569;">
            ${t}
            <input class="acc-input" data-ref="${e}" type="${a}" value="${this.escape(s??"")}" placeholder="${this.escape(i)}">
        </label>`}async _save(){var t;const e={};["site_name","welcome_msg","phone","whatsapp","telegram","instagram"].forEach(s=>{const a=this.ref(s);a&&(e[s]=a.value)}),e.enabled=(t=this.ref("enabled"))!=null&&t.checked?1:0;try{await this.api.post("chat/settings",e),alert("✅ تنظیمات ذخیره شد")}catch(s){alert(s.message)}}escape(e){return String(e??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}const da={submitted:{label:"ثبت شده",color:"#6366f1"},assigned:{label:"تخصیص",color:"#3b82f6"},in_progress:{label:"در حال انجام",color:"#f59e0b"}};class pa extends x{constructor(e){super(e),this._rows=[],this._active=null,this._lastMsgId=0,this._pollTimer=null}getTitle(){return"🔧 صف کار من"}getHeaderHtml(){return""}async template(){return`
        <div class="acc-section-wrap">
            ${this.getHeaderHtml()}
            <div class="acc-toolbar">
                <h2 class="acc-section-title">${this.getTitle()}</h2>
                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
            </div>
            <div class="chat-support-layout" style="display:grid;grid-template-columns:minmax(220px,1fr) 1.4fr;gap:12px;min-height:460px;">
                <aside data-ref="queue" style="overflow-y:auto;max-height:520px;"><div class="acc-loading">⏳</div></aside>
                <div data-ref="chatPanel" class="acc-card" style="padding:12px;display:flex;flex-direction:column;min-height:420px;">
                    <div class="chat-empty-state" style="flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#94a3b8;text-align:center;padding:24px;">
                        <div style="font-size:40px;margin-bottom:8px;">💬</div>
                        <div>یک پرونده را از لیست انتخاب کنید</div>
                        <small style="margin-top:6px;">پاسخ شما در همان چت ویجت مشتری نمایش داده می‌شود</small>
                    </div>
                </div>
            </div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.listen("chat:technician:openRoom",async({conversationId:e,requestId:t})=>{await this._load();let s=null;t&&(s=this._rows.find(a=>+a.id==+t)),!s&&e&&(s=this._rows.find(a=>+a.conversation_id==+e)),s&&await this._openChat(s)}),this._pollTimer=setInterval(()=>{var e;(e=this._active)!=null&&e.conversation_id&&this._loadMessages()},5e3)}async _load(){this.ref("queue").innerHTML='<div class="acc-loading">⏳</div>';try{const e=await this.api.get("service/technician/my-queue");this._rows=(e==null?void 0:e.data)??[],this._renderQueue()}catch(e){this.ref("queue").innerHTML=`<div class="acc-error">❌ ${this.escape(e.message)}</div>`}}_renderQueue(){if(!this._rows.length){this.ref("queue").innerHTML=`
                <div class="acc-empty" style="padding:16px;text-align:center;">
                    <div style="font-size:32px;margin-bottom:8px;">📭</div>
                    <div>درخواست تخصیص‌یافته‌ای ندارید</div>
                    <small style="color:#94a3b8;display:block;margin-top:8px;">پس از Dispatch توسط کارشناس ارشد، پرونده اینجا ظاهر می‌شود</small>
                </div>`;return}this.ref("queue").innerHTML=this._rows.map(e=>{var n;const t=da[e.status]??{label:e.status,color:"#64748b"},s=((n=this._active)==null?void 0:n.id)==e.id,a=!!e.conversation_id,i=e.priority==="urgent";return`
            <div class="chat-room-item ${s?"active":""}" data-id="${e.id}"
                 style="cursor:pointer;margin-bottom:8px;padding:12px;border-radius:10px;border:2px solid ${s?"#3b82f6":i?"#fecaca":"#e2e8f0"};background:${s?"#eff6ff":i?"#fff1f2":"#fff"};">
                <div style="display:flex;justify-content:space-between;align-items:center;">
                    <span style="font-family:monospace;font-weight:700;color:#1d4ed8;font-size:14px;">${this.escape(e.tracking_code)}</span>
                    ${i?'<span style="font-size:10px;background:#fef2f2;color:#dc2626;padding:2px 6px;border-radius:6px;">فوری</span>':""}
                    ${a?'<span style="font-size:10px;background:#dcfce7;color:#166534;padding:2px 6px;border-radius:6px;">💬</span>':""}
                </div>
                <div style="font-size:13px;font-weight:600;margin-top:4px;">${this.escape(e.customer_name)}</div>
                <div style="font-size:11px;color:#64748b;">${this.escape(e.service_type_label)} · ${this.escape(e.site_label||"—")}</div>
                ${e.dispatch_notes?`<div style="font-size:10px;background:#fff7ed;color:#c2410c;padding:6px;border-radius:6px;margin-top:6px;">📋 ${this.escape(e.dispatch_notes)}</div>`:""}
                ${e.phone?`<div style="font-size:11px;color:#166534;margin-top:2px;" dir="ltr">📱 ${this.escape(e.phone)}</div>`:""}
                <div style="display:flex;gap:6px;margin-top:8px;flex-wrap:wrap;">
                    <button type="button" class="acc-btn acc-btn--xs acc-btn--primary" data-srd="${e.id}">📄 SRD</button>
                    ${["site_visit","troubleshooting"].includes(e.service_type)?`<button type="button" class="acc-btn acc-btn--xs" data-convert="${e.id}">🔧 پیش‌فاکتور</button>`:""}
                </div>
                <span style="display:inline-block;margin-top:6px;background:${t.color}1a;color:${t.color};padding:2px 8px;border-radius:10px;font-size:10px;font-weight:700;">${t.label}</span>
            </div>`}).join(""),this.ref("queue").querySelectorAll("[data-id]").forEach(e=>{e.addEventListener("click",t=>{if(t.target.closest("[data-srd],[data-convert]"))return;const s=this._rows.find(a=>a.id==e.dataset.id);s&&this._openChat(s)})}),this.ref("queue").querySelectorAll("[data-srd]").forEach(e=>{e.addEventListener("click",async t=>{t.stopPropagation(),await this._openOrCreateReport(+e.dataset.srd)})}),this.ref("queue").querySelectorAll("[data-convert]").forEach(e=>{e.addEventListener("click",async t=>{t.stopPropagation(),await this._convertToRepair(+e.dataset.convert)})})}async _openOrCreateReport(e){var s,a;const t=this._rows.find(i=>i.id===e);try{let i=t==null?void 0:t.draft_report_id;if(!i){const n=await this.api.post("service/reports",{request_id:e});i=(s=n==null?void 0:n.data)==null?void 0:s.id}i&&((a=this.eventBus)==null||a.emit("service:open-report",{id:i}))}catch(i){alert(i.message)}}async _convertToRepair(e){var a,i;const t=this._rows.find(n=>n.id===e),s=prompt("مبلغ پیش‌فاکتور تعمیر (ریال):","0");if(s!==null)try{let n=t==null?void 0:t.draft_report_id;if(!n){const r=await this.api.post("service/reports",{request_id:e});n=(a=r==null?void 0:r.data)==null?void 0:a.id}await this.api.post(`service/reports/${n}/convert-repair-quote`,{estimate:parseFloat(s)||0}),(i=this.eventBus)==null||i.emit("service:open-report",{id:n})}catch(n){alert(n.message)}}async _openChat(e){this._active=e,this._lastMsgId=0,this._renderQueue();const t=this.ref("chatPanel");if(!e.conversation_id){t.innerHTML='<div class="acc-empty">این درخواست هنوز گفتگوی چت ندارد</div>';return}const s=da[e.status]??{label:e.status,color:"#64748b"};t.innerHTML=`
            <div style="border-bottom:1px solid #e2e8f0;padding-bottom:10px;margin-bottom:10px;">
                <div style="display:flex;flex-wrap:wrap;gap:8px;align-items:center;">
                    <strong style="font-size:15px;">${this.escape(e.customer_name)}</strong>
                    <span style="font-family:monospace;color:#1d4ed8;background:#dbeafe;padding:2px 8px;border-radius:6px;font-weight:700;">${this.escape(e.tracking_code)}</span>
                    <span style="font-size:11px;background:${s.color}1a;color:${s.color};padding:2px 8px;border-radius:8px;">${s.label}</span>
                </div>
                <div style="font-size:12px;color:#64748b;margin-top:4px;">
                    ${e.phone?`<span dir="ltr">📱 ${this.escape(e.phone)}</span> · `:""}
                    ${this.escape(e.site_label||"")}
                </div>
                ${e.dispatch_notes?`<div style="background:#fff7ed;border:1px solid #fed7aa;padding:8px;border-radius:8px;font-size:11px;color:#c2410c;margin-top:8px;">👨‍💼 دستور ارشد: ${this.escape(e.dispatch_notes)}</div>`:""}
                <div style="display:flex;gap:8px;margin-top:8px;flex-wrap:wrap;">
                    <button type="button" class="acc-btn acc-btn--xs acc-btn--primary" data-ref="srdBtn">📄 گزارش SRD</button>
                    ${["site_visit","troubleshooting"].includes(e.service_type)?'<button type="button" class="acc-btn acc-btn--xs" data-ref="convertBtn">🔧 پیش‌فاکتور تعمیر</button>':""}
                </div>
                ${e.status!=="in_progress"?'<button class="acc-btn acc-btn--xs acc-btn--primary" data-ref="statusBtn" style="margin-top:8px;">▶ شروع کار میدانی</button>':""}
            </div>
            <div class="chat-messages" data-ref="messages" style="flex:1;overflow-y:auto;min-height:240px;max-height:360px;background:#f8fafc;border-radius:8px;padding:8px;"></div>
            <div class="chat-input-area" style="display:flex;gap:8px;margin-top:10px;align-items:flex-end;">
                <textarea class="chat-textarea acc-input" data-ref="replyInput" placeholder="پاسخ به مشتری در ویجت..." rows="2" style="flex:1;resize:vertical;"></textarea>
                <button class="acc-btn acc-btn--primary" data-ref="sendBtn">ارسال ➤</button>
            </div>`,this._bindRefs(),this.on(this.ref("sendBtn"),"click",()=>this._sendReply()),this.on(this.ref("replyInput"),"keydown",a=>{a.key==="Enter"&&!a.shiftKey&&(a.preventDefault(),this._sendReply())}),this.ref("statusBtn")&&this.on(this.ref("statusBtn"),"click",async()=>{try{await this.api.put(`service/requests/${e.id}`,{status:"in_progress"}),await this._load();const a=this._rows.find(i=>i.id==e.id);a&&await this._openChat(a)}catch(a){alert(a.message)}}),this.ref("srdBtn")&&this.on(this.ref("srdBtn"),"click",()=>this._openOrCreateReport(e.id)),this.ref("convertBtn")&&this.on(this.ref("convertBtn"),"click",()=>this._convertToRepair(e.id)),await this._loadMessages(!0)}async _loadMessages(e=!1){var t,s;if((t=this._active)!=null&&t.conversation_id)try{const a=await this.api.get(`chat/support/rooms/${this._active.conversation_id}`,{last_id:e?0:this._lastMsgId}),i=((s=a==null?void 0:a.data)==null?void 0:s.messages)??[],n=this.ref("messages");if(!n)return;e&&(n.innerHTML="",this._lastMsgId=0),i.forEach(r=>{+r.id>this._lastMsgId&&(this._lastMsgId=+r.id,this._appendMsg(n,r))}),n.scrollTop=n.scrollHeight}catch{}}_appendMsg(e,t){const s=t.sender_type==="agent"||t.sender_type==="user",a=t.sender_type==="system",i=new Date(t.created_at).toLocaleTimeString("fa-IR",{hour:"2-digit",minute:"2-digit"}),n=document.createElement("div");a?(n.className="chat-msg chat-msg--system",n.innerHTML=`<span style="font-size:11px;color:#94a3b8;">${this.escape(t.body||t.message)}</span>`):(n.className=`chat-msg ${s?"chat-msg--out":"chat-msg--in"}`,n.innerHTML=`<div class="chat-bubble">${this.escape(t.body||t.message)}<span class="chat-time">${i}</span></div>`),e.appendChild(n)}async _sendReply(){var s,a;const e=this.ref("replyInput"),t=(s=e==null?void 0:e.value)==null?void 0:s.trim();if(!(!t||!((a=this._active)!=null&&a.conversation_id))){e.value="";try{await this.api.post(`chat/support/rooms/${this._active.conversation_id}/reply`,{body:t}),await this._loadMessages()}catch(i){alert(i.message)}}}destroy(){clearInterval(this._pollTimer),super.destroy()}}class Ao extends pa{getTitle(){return"💬 چت مشتریان من"}getHeaderHtml(){return`
        <div class="acc-card" style="padding:14px 16px;margin-bottom:14px;background:linear-gradient(135deg,#eff6ff,#f0fdf4);border:1px solid #bfdbfe;border-radius:12px;">
            <div style="font-size:14px;font-weight:700;color:#1e40af;margin-bottom:8px;">👷 راهنمای ورود کارشناس به چت</div>
            <ol style="margin:0;padding-right:20px;font-size:12px;color:#334155;line-height:1.9;">
                <li><b>از ویجت سایت:</b> تب <b>👷 کارشناس</b> → ورود با حساب ERP → صف کار + چت مشتری</li>
                <li><b>از ERP:</b> منوی <b>💬 چت و پشتیبانی</b> → <b>چت مشتریان من</b></li>
                <li>پس از Dispatch، پرونده‌های تخصیص‌یافته در لیست ظاهر می‌شوند</li>
                <li>پاسخ شما در <b>همان thread ویجت مشتری</b> نمایش داده می‌شود</li>
            </ol>
            <div style="margin-top:10px;font-size:11px;color:#64748b;">
                تست: <code dir="ltr">svc_tech1_demo</code> / <code dir="ltr">Demo@2026</code>
            </div>
        </div>`}}const Fo=[{key:"technician",icon:"👷",title:"چت مشتریان من",desc:"پاسخ به مشتریان تخصیص‌یافته",roles:["technician"]},{key:"support",icon:"🎧",title:"Live Chat",desc:"همه گفتگوها (ارشد/مدیر)",roles:["admin","senior"]},{key:"internal",icon:"💼",title:"چت داخلی",desc:"گفتگوی بین کارمندان",roles:["admin","senior","technician"]},{key:"settings",icon:"⚙️",title:"تنظیمات",desc:"پیکربندی ویجت چت",roles:["admin"]}],Io={technician:Ao,support:Bo,internal:zo,settings:jo};class ha extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._active=null,this._sections={},this._role="admin",this._sectionDefs=[]}_resolveRole(t){return t!=null&&t.is_technician&&!(t!=null&&t.is_admin)&&!(t!=null&&t.is_senior)?"technician":t!=null&&t.is_senior&&!(t!=null&&t.is_admin)?"senior":(t!=null&&t.is_admin||(t==null?void 0:t.role)==="admin","admin")}_buildSections(t){return Fo.filter(s=>s.roles.includes(t)).map(s=>({...s,Class:Io[s.key]}))}async beforeRender(){var t;try{const s=await this.api.get("service/me/role");this._role=this._resolveRole(s==null?void 0:s.data)}catch{this._role="admin"}this._sectionDefs=this._buildSections(this._role),this._active=((t=this._sectionDefs[0])==null?void 0:t.key)||"support"}async template(){const t=this._sectionDefs.map(a=>`
            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"
                 data-section="${a.key}" role="button" tabindex="0">
                <span class="sp-nav-card__icon">${a.icon}</span>
                <div class="sp-nav-card__title">${a.title}</div>
                <div class="sp-nav-card__desc">${a.desc}</div>
            </div>`).join(""),s=this._sectionDefs.map(a=>`
            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"
                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>`).join("");return`
            <div class="sp-section-nav" data-ref="navBar">${t}</div>
            <div>${s}</div>`}async afterRender(){this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(t=>{this.on(t,"click",()=>this._switch(t.dataset.section))}),await this._mount(this._active),this.listen("chat:support:openRoom",()=>{this._role==="technician"&&this._sectionDefs.some(t=>t.key==="technician")&&this._switch("technician")})}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=this._sectionDefs.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(ha,"title","💬 چت و پشتیبانی"),E.register("chat",ha);const ua={submitted:{label:"ثبت شده",color:"#6366f1"},assigned:{label:"تخصیص",color:"#3b82f6"},in_progress:{label:"در حال انجام",color:"#f59e0b"},completed:{label:"تکمیل",color:"#059669"},cancelled:{label:"لغو",color:"#64748b"}};class Do extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📋 درخواست‌های خدمات</h2>
                <div style="display:flex;gap:8px;flex-wrap:wrap;">
                    <select data-ref="statusFilter" class="acc-input">
                        <option value="">همه وضعیت‌ها</option>
                        ${Object.entries(ua).map(([e,t])=>`<option value="${e}">${t.label}</option>`).join("")}
                    </select>
                    <input type="text" data-ref="search" placeholder="🔍 کد / نام / موضع" class="acc-input" style="width:200px;">
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳ بارگذاری...</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("statusFilter"),"change",()=>this._load()),this.on(this.ref("search"),"input",()=>{clearTimeout(this._t),this._t=setTimeout(()=>this._load(),300)})}async _load(){var a,i,n;const e={},t=(a=this.ref("statusFilter"))==null?void 0:a.value,s=(n=(i=this.ref("search"))==null?void 0:i.value)==null?void 0:n.trim();t&&(e.status=t),s&&(e.search=s),this.ref("wrap").innerHTML='<div class="acc-loading">⏳ بارگذاری...</div>';try{const r=await this.api.get("service/requests",e);this._rows=(r==null?void 0:r.data)??[],this._render()}catch(r){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(r.message)}</div>`}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">درخواستی یافت نشد</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>کد پیگیری</th><th>نوع</th><th>مشتری</th><th>موضع</th>
                <th>وضعیت</th><th>تاریخ</th><th>اقدام</th>
            </tr></thead>
            <tbody>
            ${this._rows.map(e=>{const t=ua[e.status]??{label:e.status,color:"#64748b"};return`<tr>
                    <td><b style="font-family:monospace;color:#1d4ed8;">${this.escape(e.tracking_code)}</b>
                        <br><small>${this.escape(e.request_no)}</small></td>
                    <td><small>${this.escape(e.service_type_label??e.service_type)}</small></td>
                    <td>${this.escape(e.customer_name)}<br><small dir="ltr">${this.escape(e.phone)}</small></td>
                    <td><small>${this.escape(e.site_label||"—")}</small></td>
                    <td><span style="background:${t.color}1a;color:${t.color};padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${t.label}</span></td>
                    <td><small>${(e.created_at||"").slice(0,16)}</small></td>
                    <td>
                        <button class="acc-btn acc-btn--sm" data-action="report" data-id="${e.id}">📄 گزارش</button>
                        <button class="acc-btn acc-btn--sm acc-btn--secondary" data-action="detail" data-id="${e.id}">👁</button>
                    </td>
                </tr>`}).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-action=report]").forEach(e=>{e.addEventListener("click",()=>this._createReport(+e.dataset.id))}),this.ref("wrap").querySelectorAll("[data-action=detail]").forEach(e=>{e.addEventListener("click",()=>this._showDetail(+e.dataset.id))})}async _createReport(e){var t,s,a;try{const i=await this.api.post("service/reports",{request_id:e}),n=(t=i==null?void 0:i.data)==null?void 0:t.id;n&&((a=(s=this.eventBus)==null?void 0:s.emit)==null||a.call(s,"service:open-report",{id:n}),alert(`گزارش ${i.data.report_no} ایجاد شد — از تب «گزارش فنی» ویرایش کنید.`))}catch(i){alert("خطا: "+(i.message||""))}}async _showDetail(e){var t;try{const s=await this.api.get(`service/requests/${e}`),a=s==null?void 0:s.data;if(!a)return;const i=(a.timeline||[]).map(o=>`
                <div class="svc-tl-item">
                    <div class="svc-tl-dot"></div>
                    <div>
                        <div class="svc-tl-label">${this.escape(o.label)}</div>
                        <div class="svc-tl-at">${this.escape((o.at||"").slice(0,16))}${o.total?` · ${Number(o.total).toLocaleString("fa-IR")} ت`:""}</div>
                    </div>
                </div>`).join(""),n=(a.reports||[]).map(o=>`
                <div style="margin:6px 0;padding:8px;background:#f0fdf4;border-radius:8px;font-size:12px;">
                    📄 ${this.escape(o.report_no)} — ${o.status==="final"?"نهایی":"پیش‌نویس"}
                    ${o.total?` · ${Number(o.total).toLocaleString("fa-IR")} ت`:""}
                    ${o.public_url?`<a href="${this.escape(o.public_url)}" target="_blank" style="margin-right:8px;">مشاهده گزارش</a>`:""}
                </div>`).join(""),r=document.createElement("div");r.className="svc-detail-overlay",r.innerHTML=`
            <div class="svc-detail-modal" dir="rtl">
                <div class="svc-detail-head">
                    <h3>📋 گزارش کامل پرونده</h3>
                    <button class="acc-btn acc-btn--sm" data-close>✕</button>
                </div>
                <div class="svc-detail-body">
                    <div class="svc-detail-grid">
                        <div><b>کد پیگیری</b><br><span style="font-family:monospace;color:#1d4ed8;font-weight:800;">${this.escape(a.tracking_code)}</span></div>
                        <div><b>نوع خدمت</b><br>${this.escape(a.service_type_label)}</div>
                        <div><b>وضعیت</b><br>${this.escape(a.status_label)}</div>
                        <div><b>مشتری</b><br>${this.escape(a.customer_name)}<br><small dir="ltr">${this.escape(a.phone)}</small></div>
                        <div><b>کارشناس</b><br>${this.escape(a.technician_name||"—")}</div>
                        <div><b>زمان‌بندی</b><br>${this.escape((a.scheduled_at||"").slice(0,16)||"—")}</div>
                    </div>
                    ${a.dispatch_notes?`<div class="svc-dispatch-note">👨‍💼 دستور ارشد: ${this.escape(a.dispatch_notes)}</div>`:""}
                    <div><b>موضع:</b> ${this.escape(a.site_label||"—")}</div>
                    <div><b>دستگاه:</b> ${this.escape(a.brand||"")} ${this.escape(a.model||"")} ${this.escape(a.serial_no||"")}</div>
                    <div><b>شرح:</b> ${this.escape(a.complaint_text||"—")}</div>
                    ${n?`<div style="margin-top:12px;"><b>گزارش‌های فنی / فاکتور</b>${n}</div>`:""}
                    <div style="margin-top:14px;"><b>⏱ تایم‌لاین مراحل</b></div>
                    <div class="svc-timeline">${i||'<div class="acc-empty">—</div>'}</div>
                </div>
            </div>`,document.body.appendChild(r),(t=r.querySelector("[data-close]"))==null||t.addEventListener("click",()=>r.remove()),r.addEventListener("click",o=>{o.target===r&&r.remove()})}catch(s){alert(s.message)}}}class Po extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">❄️ دستگاه‌ها</h2>
                <div style="display:flex;gap:8px;">
                    <input data-ref="search" class="acc-input" placeholder="🔍 سریال / برند / موضع" style="width:220px;">
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">➕ دستگاه</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._openForm()),this.on(this.ref("search"),"input",()=>{clearTimeout(this._t),this._t=setTimeout(()=>this._load(),300)})}async _load(){var t,s;const e=(s=(t=this.ref("search"))==null?void 0:t.value)==null?void 0:s.trim();this.ref("wrap").innerHTML='<div class="acc-loading">⏳</div>';try{const a=await this.api.get("service/devices",e?{search:e}:{});this._rows=(a==null?void 0:a.data)??[],this._render()}catch(a){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(a.message)}</div>`}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">دستگاهی ثبت نشده</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>موضع</th><th>نوع</th><th>برند/مدل</th><th>سریال</th><th>مشتری</th><th>ارزش تخمینی</th><th></th>
            </tr></thead>
            <tbody>
            ${this._rows.map(e=>`<tr>
                <td>${this.escape(e.site_label||"—")}</td>
                <td>${this.escape(e.device_type||"—")}</td>
                <td>${this.escape(e.brand)} ${this.escape(e.model)}</td>
                <td dir="ltr"><code>${this.escape(e.serial_no)}</code></td>
                <td>${this.escape(e.customer_name)}</td>
                <td>${Number(e.estimated_value||0).toLocaleString("fa-IR")}</td>
                <td style="white-space:nowrap;">
                    <button class="acc-btn acc-btn--sm" data-chart="${e.id}">📊 هزینه</button>
                    <button class="acc-btn acc-btn--sm" data-timeline="${e.id}">📈 سوابق</button>
                </td>
            </tr>`).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-timeline]").forEach(e=>{e.addEventListener("click",()=>this._timeline(+e.dataset.timeline))}),this.ref("wrap").querySelectorAll("[data-chart]").forEach(e=>{e.addEventListener("click",()=>this._costChart(+e.dataset.chart))})}_openModal(e,t){const s=document.createElement("div");s.className="acc-modal",s.innerHTML=`
        <div class="acc-modal__box" style="max-width:560px;">
            <div class="acc-modal__header">
                <h3>${e}</h3>
                <button class="acc-modal__close">✕</button>
            </div>
            <div style="padding:16px;">${t}</div>
        </div>`,document.body.appendChild(s);const a=()=>s.remove();return s.querySelector(".acc-modal__close").addEventListener("click",a),s.addEventListener("click",i=>{i.target===s&&a()}),s}async _timeline(e){try{const t=await this.api.get(`service/devices/${e}/timeline`),s=(t==null?void 0:t.data)??{},a=(s.requests||[]).map(n=>`<li>📋 <b>${this.escape(n.tracking_code)}</b> — ${this.escape(n.service_type)} <small>${(n.created_at||"").slice(0,10)}</small></li>`).join("")||"<li>—</li>",i=(s.reports||[]).map(n=>`<li>📄 <b>${this.escape(n.report_no)}</b> — ${Number(n.total||0).toLocaleString("fa-IR")} <small>${(n.created_at||"").slice(0,10)}</small></li>`).join("")||"<li>—</li>";this._openModal("📈 سوابق دستگاه",`
                <p><b>درخواست‌ها</b></p><ul style="margin:0 0 16px;padding-right:20px;">${a}</ul>
                <p><b>گزارش‌ها</b></p><ul style="margin:0;padding-right:20px;">${i}</ul>`)}catch(t){alert(t.message)}}async _costChart(e){try{const t=await this.api.get(`service/devices/${e}/cost-chart`),s=(t==null?void 0:t.data)??{},a=s.monthly||[],i=Math.max(...a.map(o=>Number(o.total||0)),1),n=a.map(o=>`<div style="flex:1;text-align:center;min-width:36px;">
                    <div style="height:120px;display:flex;align-items:flex-end;justify-content:center;">
                        <div style="width:28px;height:${Math.round(Number(o.total||0)/i*120)}px;background:#3b82f6;border-radius:4px 4px 0 0;" title="${o.total}"></div>
                    </div>
                    <small style="font-size:10px;color:#64748b;">${this.escape(o.month||"")}</small>
                </div>`).join("")||'<div class="acc-empty">داده‌ای برای نمودار نیست</div>',r=s.replace_suggested?`<div style="background:#fef3c7;border:1px solid #f59e0b;border-radius:8px;padding:10px;margin-bottom:12px;font-size:13px;">⚠️ ${this.escape(s.replace_message||"")}</div>`:"";this._openModal("📊 نمودار هزینه تعمیرات",`
                ${r}
                <div style="display:flex;gap:12px;margin-bottom:16px;">
                    <div style="flex:1;background:#f8fafc;padding:12px;border-radius:8px;">
                        <div style="font-size:11px;color:#64748b;">مجموع هزینه</div>
                        <div style="font-size:20px;font-weight:800;color:#1d4ed8;">${Number(s.lifetime_cost||0).toLocaleString("fa-IR")}</div>
                    </div>
                    <div style="flex:1;background:#f8fafc;padding:12px;border-radius:8px;">
                        <div style="font-size:11px;color:#64748b;">ارزش تخمینی</div>
                        <div style="font-size:20px;font-weight:800;">${Number(s.estimated_value||0).toLocaleString("fa-IR")}</div>
                    </div>
                </div>
                <div style="display:flex;gap:4px;align-items:flex-end;overflow-x:auto;padding-bottom:8px;">${n}</div>`)}catch(t){alert(t.message)}}_openForm(e=null){const t=document.createElement("div");t.className="acc-modal",t.innerHTML=`
        <div class="acc-modal__box" style="max-width:480px;">
            <div class="acc-modal__header">
                <h3>${e?"ویرایش":"➕"} دستگاه</h3>
                <button class="acc-modal__close">✕</button>
            </div>
            <form class="acc-form" style="padding:16px;display:grid;gap:10px;">
                <div class="acc-form-group"><label>موضع / سایت</label>
                    <input name="site_label" class="acc-input" value="${this.escape((e==null?void 0:e.site_label)??"")}"></div>
                <div class="acc-form-group"><label>نام مشتری</label>
                    <input name="customer_name" class="acc-input" value="${this.escape((e==null?void 0:e.customer_name)??"")}"></div>
                <div class="acc-form-group"><label>نوع دستگاه</label>
                    <input name="device_type" class="acc-input" placeholder="چیلر / سردخانه" value="${this.escape((e==null?void 0:e.device_type)??"")}"></div>
                <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
                    <div class="acc-form-group"><label>برند</label><input name="brand" class="acc-input" value="${this.escape((e==null?void 0:e.brand)??"")}"></div>
                    <div class="acc-form-group"><label>مدل</label><input name="model" class="acc-input" value="${this.escape((e==null?void 0:e.model)??"")}"></div>
                </div>
                <div class="acc-form-group"><label>شماره سریال</label>
                    <input name="serial_no" class="acc-input" dir="ltr" value="${this.escape((e==null?void 0:e.serial_no)??"")}"></div>
                <div class="acc-form-group"><label>ساعت کارکرد</label>
                    <input name="operating_hours" type="number" min="0" class="acc-input" value="${(e==null?void 0:e.operating_hours)??0}"></div>
                <div class="acc-form-group"><label>ارزش تخمینی دستگاه (تومان)</label>
                    <input name="estimated_value" type="number" min="0" class="acc-input" value="${(e==null?void 0:e.estimated_value)??0}"></div>
                <div style="display:flex;gap:8px;justify-content:flex-end;">
                    <button type="button" class="acc-btn acc-btn--secondary" data-cancel>انصراف</button>
                    <button type="submit" class="acc-btn acc-btn--primary">ذخیره</button>
                </div>
            </form>
        </div>`,document.body.appendChild(t);const s=()=>t.remove();t.querySelector(".acc-modal__close").addEventListener("click",s),t.querySelector("[data-cancel]").addEventListener("click",s),t.addEventListener("click",a=>{a.target===t&&s()}),t.querySelector("form").addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries());i.estimated_value=Number(i.estimated_value||0);try{e?await this.api.put(`service/devices/${e.id}`,i):await this.api.post("service/devices",i),s(),await this._load()}catch(n){alert(n.message)}})}}const ve=[{id:1,title:"نوع خدمت"},{id:2,title:"مشتری"},{id:3,title:"دستگاه"},{id:4,title:"شرح درخواست"},{id:5,title:"گزارش کارشناسی"},{id:6,title:"خدمات انجام‌شده"},{id:7,title:"قطعات"},{id:8,title:"مواد مصرفی"},{id:9,title:"هزینه جانبی"},{id:10,title:"پیشنهاد فنی"},{id:11,title:"قرارداد PM"},{id:12,title:"جمع مالی"},{id:13,title:"تأیید نهایی"}],Oo={phone_consult:"📞",online_consult:"💻",site_visit:"🔍",troubleshooting:"⚡",repair:"🛠",pm:"📅",overhaul:"⚙️",install:"🏗",parts_supply:"🔩",equipment_purchase:"🏭",contract_support:"📋"};class No extends x{constructor(e){super(e),this._meta=null,this._wizard=null}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📄 گزارش فنی (SRD)</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="newBtn">➕ گزارش جدید</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳</div></div>
        </div>`}async afterRender(){try{this._meta=await this.api.get("service/meta")??{}}catch{this._meta={}}await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("newBtn"),"click",()=>this._openWizard())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳</div>';try{const e=await this.api.get("service/reports");this._rows=(e==null?void 0:e.data)??[],this._renderList()}catch(e){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(e.message)}</div>`}}_renderList(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">گزارشی ثبت نشده — «گزارش جدید» بزنید</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>شماره</th><th>مشتری</th><th>موضع</th><th>وضعیت</th><th>مبلغ</th><th>حسابداری</th><th></th>
            </tr></thead>
            <tbody>
            ${this._rows.map(e=>`<tr>
                <td><b>${this.escape(e.report_no)}</b></td>
                <td>${this.escape(e.customer_name)}</td>
                <td><small>${this.escape(e.site_label||"—")}</small></td>
                <td>${e.status==="final"?'<span style="color:#059669;font-weight:700;">✅ نهایی</span>':'<span style="color:#f59e0b;">📝 پیش‌نویس</span>'}
                    ${e.senior_review_status==="pending"?'<br><small style="color:#f59e0b;">⏳ بازبینی ارشد</small>':""}
                    ${e.senior_review_status==="rejected"?'<br><small style="color:#dc2626;">❌ رد ارشد</small>':""}</td>
                <td>${Number(e.total||0).toLocaleString("fa-IR")}</td>
                <td>${e.acc_revenue_event_id?`<span class="acc-link-badge" title="سند حسابداری">🔗 #${e.acc_revenue_event_id}</span>
                       ${e.acc_workflow_state==="posted"?'<br><small style="color:#059669;">✅ صادر</small>':e.acc_workflow_state?`<br><small style="color:#f59e0b;">⏳ ${this.escape(e.acc_workflow_state)}</small>`:""}`:e.status==="final"?'<small style="color:#f59e0b;">⏳ صف حسابدار</small>':"—"}</td>
                <td>
                    <button class="acc-btn acc-btn--sm" data-edit="${e.id}">✏️</button>
                    ${e.status!=="final"&&e.request_id?`<button class="acc-btn acc-btn--sm" data-cost="${e.id}" title="درخواست تأیید هزینه">💰</button>`:""}
                    ${e.status==="final"?`<button class="acc-btn acc-btn--sm" data-view="${e.id}">👁</button>`:`<button class="acc-btn acc-btn--sm acc-btn--primary" data-finalize="${e.id}">✅</button>`}
                </td>
            </tr>`).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-edit]").forEach(e=>e.addEventListener("click",()=>this._openWizard(+e.dataset.edit))),this.ref("wrap").querySelectorAll("[data-cost]").forEach(e=>e.addEventListener("click",()=>this._requestCostApproval(+e.dataset.cost))),this.ref("wrap").querySelectorAll("[data-finalize]").forEach(e=>e.addEventListener("click",()=>this._finalize(+e.dataset.finalize))),this.ref("wrap").querySelectorAll("[data-view]").forEach(e=>e.addEventListener("click",()=>this._viewReport(+e.dataset.view)))}async _viewReport(e){var t;try{const s=await this.api.get(`service/reports/${e}`),a=(t=s==null?void 0:s.data)==null?void 0:t.public_url;a?window.open(a,"_blank"):alert("لینک عمومی موجود نیست — گزارش را نهایی کنید.")}catch(s){alert(s.message)}}async _openWizard(e=null){var s,a,i;let t={service_type:"repair",service_lines:[],part_lines:[],material_lines:[],extra_costs:[],recommendations:[],pm_offer:{},technical_readings:{},complaint_tags:[],discount:0,tax:0,paid:0};if(e){const n=await this.api.get(`service/reports/${e}`);t={...t,...(n==null?void 0:n.data)??{},id:e}}else{const n=await this.api.post("service/reports",{});t.id=(s=n==null?void 0:n.data)==null?void 0:s.id,t.report_no=(a=n==null?void 0:n.data)==null?void 0:a.report_no,t.public_token=(i=n==null?void 0:n.data)==null?void 0:i.public_token}this._wizard={step:1,data:t,visited:new Set([1])},this._renderWizardModal()}_renderWizardModal(){var f,m,b;const e=this._wizard;if(!e)return;let t=document.getElementById("svc-wizard-modal");t&&t.remove();const s=this._meta.service_types??{},a=this._meta.complaint_tags??[],i=this._meta.pm_options??{},n=e.data,r=e.step,o=e.visited||new Set([r]);o.add(r);const l=`
            <div class="svc-srd-stepper">
                <div class="svc-srd-step-meta">
                    <span class="svc-srd-step-badge">مرحله ${r} از ${ve.length}</span>
                    <strong class="svc-srd-step-name">${ve[r-1].title}</strong>
                </div>
                <div class="svc-srd-progress"><div class="svc-srd-progress-bar" style="width:${Math.round(r/ve.length*100)}%"></div></div>
                <div class="svc-srd-dots" role="tablist">
                    ${ve.map(v=>`
                        <button type="button" class="svc-srd-dot ${v.id===r?"is-active":""} ${o.has(v.id)&&v.id!==r?"is-done":""}"
                            data-goto-step="${v.id}" title="${this.escape(v.title)}">
                            <span class="svc-srd-dot-num">${o.has(v.id)&&v.id!==r?"✓":v.id}</span>
                        </button>`).join("")}
                </div>
            </div>`;let c="";if(r===1)c=`<div class="svc-srd-type-grid">
                ${Object.entries(s).map(([v,y])=>`
                <label class="svc-srd-type-card ${n.service_type===v?"is-selected":""}">
                    <input type="radio" name="service_type" value="${v}" ${n.service_type===v?"checked":""}>
                    <span class="svc-srd-type-icon">${Oo[v]||"🔧"}</span>
                    <span class="svc-srd-type-label">${this.escape(y)}</span>
                </label>`).join("")}
            </div>`;else if(r===2){const v=n.report_date||new Date().toISOString().slice(0,10);c=`
                <div class="acc-form-group"><label>شماره گزارش</label><input class="acc-input" value="${this.escape(n.report_no)}" disabled></div>
                <div class="acc-form-group"><label>تاریخ</label><input name="report_date" type="date" class="acc-input" value="${this.escape(v)}"></div>
                <div class="acc-form-group"><label>نام مشتری</label><input name="customer_name" class="acc-input" value="${this.escape(n.customer_name??"")}"></div>
                <div class="acc-form-group"><label>شرکت</label><input name="company" class="acc-input" value="${this.escape(n.company??"")}"></div>
                <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
                    <div class="acc-form-group"><label>تلفن</label><input name="phone" class="acc-input" dir="ltr" value="${this.escape(n.phone??"")}"></div>
                    <div class="acc-form-group"><label>ایمیل</label><input name="email" class="acc-input" dir="ltr" value="${this.escape(n.email??"")}"></div>
                </div>
                <div class="acc-form-group"><label>آدرس</label><textarea name="address" class="acc-input" rows="2">${this.escape(n.address??"")}</textarea></div>
                <div class="acc-form-group"><label>شناسه پرونده</label><input name="case_no" class="acc-input" value="${this.escape(n.case_no??"")}"></div>
                <div class="acc-form-group"><label>موضع / سایت</label><input name="site_label" class="acc-input" value="${this.escape(n.site_label??"")}"></div>`}else if(r===3){const v=n.device_snapshot??{};c=`
                <div class="acc-form-group"><label>نوع</label><input name="device_type" class="acc-input" value="${this.escape(v.device_type??"")}"></div>
                <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
                    <div class="acc-form-group"><label>برند</label><input name="brand" class="acc-input" value="${this.escape(v.brand??"")}"></div>
                    <div class="acc-form-group"><label>مدل</label><input name="model" class="acc-input" value="${this.escape(v.model??"")}"></div>
                </div>
                <div class="acc-form-group"><label>سریال</label><input name="serial_no" class="acc-input" dir="ltr" value="${this.escape(v.serial_no??"")}"></div>
                <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
                    <div class="acc-form-group"><label>ظرفیت</label><input name="capacity" class="acc-input" value="${this.escape(v.capacity??"")}"></div>
                    <div class="acc-form-group"><label>مبرد</label><input name="refrigerant" class="acc-input" value="${this.escape(v.refrigerant??"")}"></div>
                </div>
                <div class="acc-form-group"><label>محل نصب</label><input name="install_location" class="acc-input" value="${this.escape(v.install_location??"")}"></div>
                <div style="display:grid;grid-template-columns:1fr 1fr;gap:8px;">
                    <div class="acc-form-group"><label>ساعات کارکرد</label><input name="operating_hours" type="number" class="acc-input" value="${v.operating_hours??0}"></div>
                    <div class="acc-form-group"><label>آخرین سرویس</label><input name="last_service_date" type="date" class="acc-input" value="${this.escape(v.last_service_date??"")}"></div>
                </div>`}else if(r===4)c=`
                <div style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px;">
                    ${a.map(v=>{const y=(n.complaint_tags||[]).includes(v);return`<label style="font-size:12px;padding:4px 10px;border:1px solid ${y?"#1d4ed8":"#e2e8f0"};border-radius:20px;cursor:pointer;">
                            <input type="checkbox" name="tag" value="${this.escape(v)}" ${y?"checked":""} style="margin-left:4px;">${this.escape(v)}
                        </label>`}).join("")}
                </div>
                <div class="acc-form-group"><label>شرح درخواست</label>
                    <textarea name="complaint_text" class="acc-input" rows="4">${this.escape(n.complaint_text??"")}</textarea></div>`;else if(r===5){const v=n.technical_readings??{};c=[["suction_pressure","فشار مکش"],["discharge_pressure","فشار دهش"],["superheat","سوپرهیت"],["subcool","سابکول"],["compressor_amps","آمپر"],["voltage","ولتاژ"],["ambient_temp","دمای محیط"],["inlet_temp","دمای ورود"],["outlet_temp","دمای خروج"],["oil_status","روغن"],["filter_status","فیلتر"]].map(([$,w])=>`
                <div class="acc-form-group"><label>${w}</label>
                    <input name="${$}" class="acc-input" value="${this.escape(v[$]??"")}"></div>
            `).join("")+`<div class="acc-form-group"><label>نتیجه عیب‌یابی</label>
                <textarea name="diagnosis_result" class="acc-input" rows="3">${this.escape(n.diagnosis_result??"")}</textarea></div>
                <div class="acc-form-group"><label>📷 عکس قبل از کار</label>
                    <input type="file" accept="image/*" multiple data-photo="before" class="acc-input">
                    <div data-photo-preview="before" style="display:flex;flex-wrap:wrap;gap:6px;margin-top:6px;">
                        ${(n.photos_before||[]).map(($,w)=>`<img src="${this.escape($)}" style="width:60px;height:60px;object-fit:cover;border-radius:6px;" data-rm-before="${w}">`).join("")}
                    </div></div>
                <div class="acc-form-group"><label>📷 عکس بعد از کار</label>
                    <input type="file" accept="image/*" multiple data-photo="after" class="acc-input">
                    <div data-photo-preview="after" style="display:flex;flex-wrap:wrap;gap:6px;margin-top:6px;">
                        ${(n.photos_after||[]).map(($,w)=>`<img src="${this.escape($)}" style="width:60px;height:60px;object-fit:cover;border-radius:6px;" data-rm-after="${w}">`).join("")}
                    </div></div>`}else if(r===6)c=this._lineEditor("service_lines",n.service_lines,[{key:"desc",label:"شرح",w:"2fr"},{key:"qty",label:"تعداد",w:"80px"},{key:"unit",label:"واحد",w:"80px"},{key:"unit_price",label:"قیمت واحد",w:"100px"}]);else if(r===7)c=`
                <div class="acc-form-group">
                    <label>🔍 جستجوی قطعه از انبار</label>
                    <input class="acc-input" id="svc-part-search" placeholder="نام یا کد قطعه...">
                    <div id="svc-part-results"></div>
                </div>`+this._lineEditor("part_lines",n.part_lines,[{key:"name",label:"قطعه",w:"2fr"},{key:"part_no",label:"شماره فنی",w:"100px"},{key:"qty",label:"تعداد",w:"70px"},{key:"unit_price",label:"قیمت",w:"90px"}]);else if(r===8)c=this._lineEditor("material_lines",n.material_lines,[{key:"desc",label:"شرح",w:"2fr"},{key:"qty",label:"مقدار",w:"70px"},{key:"unit",label:"واحد",w:"70px"},{key:"unit_price",label:"قیمت",w:"90px"}]);else if(r===9){const v=this._meta.extra_cost_presets||[];c=(v.length?`<div style="display:flex;flex-wrap:wrap;gap:6px;margin-bottom:10px;">
                ${v.map(y=>`<button type="button" class="acc-btn acc-btn--sm" data-preset-cost data-desc="${this.escape(y.desc)}" data-amount="${y.amount}">+ ${this.escape(y.desc)}</button>`).join("")}
            </div>`:"")+this._lineEditor("extra_costs",n.extra_costs,[{key:"desc",label:"شرح هزینه",w:"2fr"},{key:"amount",label:"مبلغ",w:"120px"}],!0)}else if(r===10)c=["تعویض فیلتر درایر","شستشوی کندانسور","تعویض فن","اورهال کمپرسور","تعویض کنترلر","سرویس ماه آینده"].map(y=>{const $=(n.recommendations||[]).includes(y);return`<label style="display:block;padding:8px;border-bottom:1px solid #f1f5f9;">
                    <input type="checkbox" name="rec" value="${this.escape(y)}" ${$?"checked":""}> ${this.escape(y)}
                </label>`}).join("");else if(r===11){const v=this._meta.pm_prices||{};c=Object.entries(i).map(([y,$])=>{var k;const w=((k=n.pm_offer)==null?void 0:k.plan)===y,_=v[y]||0;return`<label style="display:block;padding:10px;margin:4px 0;border:1px solid #e2e8f0;border-radius:8px;">
                    <input type="radio" name="pm_plan" value="${y}" ${w?"checked":""}> ☑ ${this.escape($)}
                    <span style="font-size:11px;color:#1d4ed8;margin-right:8px;">${Number(_).toLocaleString("fa-IR")} ریال</span>
                </label>`}).join("")+'<p style="font-size:11px;color:#64748b;margin-top:8px;">با نهایی‌سازی، پیش‌فاکتور PM به‌صورت خودکار صادر می‌شود.</p>'}else if(r===12)c=`
                <div style="background:#f8fafc;padding:14px;border-radius:10px;line-height:2;">
                    <div>جمع خدمات: <b>${this._fmt(n.subtotal_services)}</b></div>
                    <div>جمع قطعات: <b>${this._fmt(n.subtotal_parts)}</b></div>
                    <div>جمع مواد: <b>${this._fmt(n.subtotal_materials)}</b></div>
                    <div>جمع جانبی: <b>${this._fmt(n.subtotal_extra)}</b></div>
                    <hr style="border:none;border-top:1px solid #e2e8f0;">
                    <div class="acc-form-group"><label>تخفیف</label><input name="discount" type="number" class="acc-input" value="${n.discount??0}"></div>
                    <div class="acc-form-group"><label>مالیات</label><input name="tax" type="number" class="acc-input" value="${n.tax??0}"></div>
                    <div class="acc-form-group"><label>پرداخت‌شده</label><input name="paid" type="number" class="acc-input" value="${n.paid??0}"></div>
                    <div style="font-size:18px;color:#1d4ed8;font-weight:800;">مبلغ نهایی: ${this._fmt(n.total)}</div>
                    <div>مانده: <b style="color:#dc2626;">${this._fmt(n.balance)}</b></div>
                    ${n.request_id?'<button type="button" class="acc-btn acc-btn--secondary" data-request-cost style="margin-top:10px;width:100%;">📨 ارسال تأیید هزینه به مشتری</button>':""}
                    ${n.cost_approval_status==="pending"?'<p style="color:#f59e0b;font-size:12px;">⏳ در انتظار تأیید مشتری</p>':""}
                </div>`;else if(r===13){const v=location.origin+(location.pathname.includes("/app")?location.pathname.replace(/\/app.*/,""):""),y=n.public_token?`${v}/service-report.php?token=${n.public_token}`:"";c=`
                <div class="acc-form-group"><label>امضای کارشناس</label><input name="tech_signature" class="acc-input" value="${this.escape(n.tech_signature??"")}"></div>
                <div class="acc-form-group"><label>امضای مشتری</label><input name="customer_signature" class="acc-input" value="${this.escape(n.customer_signature??"")}"></div>
                <div class="acc-form-group"><label>مهر شرکت</label><input name="company_stamp" class="acc-input" value="${this.escape(n.company_stamp??this._meta.company_stamp_default??"")}"></div>
                ${y?`<div style="background:#eff6ff;padding:12px;border-radius:8px;font-size:12px;word-break:break-all;">
                    🔗 لینک آنلاین (QR):<br><a href="${y}" target="_blank">${this.escape(y)}</a>
                </div>`:""}
                <p style="font-size:12px;color:#64748b;">پس از «نهایی‌سازی» گزارش برای مشتری قابل مشاهده می‌شود.</p>`}const d=document.createElement("div");d.id="svc-wizard-modal",d.className="svc-srd-overlay",d.innerHTML=`
        <div class="svc-srd-modal" role="dialog" aria-modal="true">
            <div class="svc-srd-modal-head">
                <div>
                    <h3>📄 گزارش فنی SRD</h3>
                    <small>${this.escape(n.report_no||"پیش‌نویس جدید")}</small>
                </div>
                <button type="button" class="svc-srd-close" aria-label="بستن">✕</button>
            </div>
            ${l}
            <form data-ref="wizardForm" class="svc-srd-body">${c}</form>
            <div class="svc-srd-footer">
                <button type="button" class="acc-btn acc-btn--secondary" data-prev ${r<=1?"disabled":""}>◀ قبلی</button>
                <span class="svc-srd-footer-hint">${ve[r-1].title}</span>
                <button type="button" class="acc-btn acc-btn--primary" data-next>${r>=13?"💾 ذخیره":"بعدی ▶"}</button>
            </div>
        </div>`,document.body.appendChild(d),document.body.classList.add("svc-srd-open");const h=()=>{d.remove(),document.body.classList.remove("svc-srd-open"),this._wizard=null,this._load()};d.querySelector(".svc-srd-close").addEventListener("click",h),d.addEventListener("click",v=>{v.target===d&&h()}),d.querySelectorAll(".svc-srd-type-card input").forEach(v=>{v.addEventListener("change",()=>{var y;d.querySelectorAll(".svc-srd-type-card").forEach($=>$.classList.remove("is-selected")),(y=v.closest(".svc-srd-type-card"))==null||y.classList.add("is-selected")})}),d.querySelectorAll("[data-goto-step]").forEach(v=>{v.addEventListener("click",async()=>{const y=+v.dataset.gotoStep;!y||y===e.step||(await this._saveStep(r,d),e.visited=e.visited||new Set,e.visited.add(r),e.visited.add(y),e.step=y,this._renderWizardModal())})}),(f=d.querySelector("[data-prev]"))==null||f.addEventListener("click",async()=>{await this._saveStep(r,d),e.step>1&&(e.visited=e.visited||new Set,e.visited.add(e.step),e.step--,e.visited.add(e.step),this._renderWizardModal())}),(m=d.querySelector("[data-next]"))==null||m.addEventListener("click",async()=>{await this._saveStep(r,d),e.step<13?(e.visited=e.visited||new Set,e.visited.add(e.step),e.step++,e.visited.add(e.step),this._renderWizardModal()):h()}),d.querySelectorAll("[data-add-line]").forEach(v=>{v.addEventListener("click",()=>this._addLineRow(d,v.dataset.addLine))});const u=d.querySelector("#svc-part-search");u&&u.addEventListener("input",()=>{clearTimeout(this._partT),this._partT=setTimeout(()=>this._searchParts(d,u.value.trim()),300)}),d.querySelectorAll("[data-preset-cost]").forEach(v=>{v.addEventListener("click",()=>this._addLineRow(d,"extra_costs",{desc:v.dataset.desc,amount:v.dataset.amount}))}),d.querySelectorAll("[data-photo]").forEach(v=>{v.addEventListener("change",()=>this._handlePhotoPick(d,v.dataset.photo,v.files))}),(b=d.querySelector("[data-request-cost]"))==null||b.addEventListener("click",async()=>{await this._saveStep(r,d),await this._requestCostApproval(e.data.id)})}async _handlePhotoPick(e,t,s){var n;if(!(s!=null&&s.length)||!((n=this._wizard)!=null&&n.data))return;const a=t==="before"?"photos_before":"photos_after",i=[...this._wizard.data[a]||[]];for(const r of s){const o=await new Promise((l,c)=>{const d=new FileReader;d.onload=()=>l(d.result),d.onerror=c,d.readAsDataURL(r)});i.length<6&&i.push(o)}this._wizard.data[a]=i,this._renderWizardModal()}async _requestCostApproval(e){var t;if(confirm("برآورد هزینه برای تأیید مشتری ارسال شود؟"))try{const s=await this.api.post(`service/reports/${e}/request-cost-approval`,{});alert(`ارسال شد — مبلغ: ${Number(((t=s==null?void 0:s.data)==null?void 0:t.estimate)||0).toLocaleString("fa-IR")} ریال
مشتری از تب پیگیری ویجت تأیید می‌کند.`),await this._load()}catch(s){alert(s.message)}}async _searchParts(e,t){const s=e.querySelector("#svc-part-results");if(!s||t.length<2){s&&(s.innerHTML="");return}try{const a=await this.api.get("service/parts/search",{q:t}),i=(a==null?void 0:a.data)??[];if(!i.length){s.innerHTML='<small style="color:#94a3b8;">یافت نشد</small>';return}s.innerHTML=i.map(n=>`
                <div class="svc-part-pick" data-pid="${n.id}" data-name="${this.escape(n.name)}"
                     data-code="${this.escape(n.code)}" style="padding:6px 8px;border-bottom:1px solid #f1f5f9;cursor:pointer;font-size:11px;">
                    ${this.escape(n.name)} <small style="color:#64748b;">(${this.escape(n.code)}) · موجودی: ${n.stock_qty}</small>
                </div>
            `).join(""),s.querySelectorAll(".svc-part-pick").forEach(n=>{n.addEventListener("click",()=>this._addPartLine(e,{product_id:+n.dataset.pid,name:n.dataset.name,part_no:n.dataset.code,qty:1,unit_price:0}))})}catch{s.innerHTML=""}}_addPartLine(e,t){const s=e.querySelector('[data-line-body="part_lines"]');if(!s)return;const a=s.querySelectorAll("tr").length,i=document.createElement("tr");i.dataset.idx=a,i.innerHTML=`
            <td><input name="part_lines_name_${a}" class="acc-input" style="padding:4px;font-size:12px;" value="${this.escape(t.name)}">
                <input type="hidden" name="part_lines_product_id_${a}" value="${t.product_id}"></td>
            <td><input name="part_lines_part_no_${a}" class="acc-input" style="padding:4px;font-size:12px;" value="${this.escape(t.part_no)}"></td>
            <td><input name="part_lines_qty_${a}" class="acc-input" style="padding:4px;font-size:12px;" value="${t.qty}"></td>
            <td><input name="part_lines_unit_price_${a}" class="acc-input" style="padding:4px;font-size:12px;" value="${t.unit_price}"></td>
            <td><button type="button" data-rm-line>🗑</button></td>`,s.appendChild(i)}_lineEditor(e,t,s,a=!1){t=t||[];const i=s.map(r=>`<th style="width:${r.w}">${r.label}</th>`).join(""),n=t.map((r,o)=>this._lineRow(e,s,r,o,a)).join("");return`
            <table class="acc-table" style="font-size:12px;" data-lines="${e}">
                <thead><tr>${i}<th></th></tr></thead>
                <tbody data-line-body="${e}">${n}</tbody>
            </table>
            <button type="button" class="acc-btn acc-btn--sm" data-add-line="${e}" style="margin-top:8px;">➕ ردیف</button>`}_lineRow(e,t,s,a,i){const n=t.map(r=>`<td><input name="${e}_${r.key}_${a}" class="acc-input" style="padding:4px;font-size:12px;" value="${this.escape(s[r.key]??"")}"></td>`).join("");return`<tr data-idx="${a}">${n}<td><button type="button" data-rm-line>🗑</button></td></tr>`}_addLineRow(e,t,s=null){const a=e.querySelector(`[data-line-body="${t}"]`),i=a.querySelectorAll("tr").length,n=t==="extra_costs"?[{key:"desc",w:"2fr"},{key:"amount",w:"120px"}]:t==="part_lines"?[{key:"name"},{key:"part_no"},{key:"qty"},{key:"unit_price"}]:t==="material_lines"?[{key:"desc"},{key:"qty"},{key:"unit"},{key:"unit_price"}]:[{key:"desc"},{key:"qty"},{key:"unit"},{key:"unit_price"}],r=document.createElement("tr");r.dataset.idx=i,r.innerHTML=n.map(o=>`<td><input name="${t}_${o.key}_${i}" class="acc-input" style="padding:4px;font-size:12px;" value="${s&&o.key in s?this.escape(String(s[o.key])):""}"></td>`).join("")+'<td><button type="button" data-rm-line>🗑</button></td>',a.appendChild(r)}async _saveStep(e,t){var r,o,l;const s=this._wizard;if(!((r=s==null?void 0:s.data)!=null&&r.id))return;const a=t.querySelector("[data-ref=wizardForm]"),i=new FormData(a),n={};if(e===1)n.service_type=((o=a.querySelector('input[name="service_type"]:checked'))==null?void 0:o.value)??s.data.service_type;else if(e===2)["customer_name","company","phone","email","address","case_no","site_label","report_date"].forEach(c=>{i.has(c)&&(n[c]=i.get(c))});else if(e===3)n.device_snapshot={device_type:i.get("device_type")??"",brand:i.get("brand")??"",model:i.get("model")??"",serial_no:i.get("serial_no")??"",capacity:i.get("capacity")??"",refrigerant:i.get("refrigerant")??"",install_location:i.get("install_location")??"",operating_hours:parseInt(i.get("operating_hours")||"0",10),last_service_date:i.get("last_service_date")??""};else if(e===4)n.complaint_tags=[...a.querySelectorAll('input[name="tag"]:checked')].map(c=>c.value),n.complaint_text=i.get("complaint_text")??"";else if(e===5){const c={};a.querySelectorAll("input[name]").forEach(d=>{["diagnosis_result"].includes(d.name)||(c[d.name]=d.value)}),n.technical_readings=c,n.diagnosis_result=i.get("diagnosis_result")??"",n.photos_before=s.data.photos_before||[],n.photos_after=s.data.photos_after||[]}else if([6,7,8,9].includes(e)){const d={6:"service_lines",7:"part_lines",8:"material_lines",9:"extra_costs"}[e];n[d]=this._collectLines(a,d)}else if(e===10)n.recommendations=[...a.querySelectorAll('input[name="rec"]:checked')].map(c=>c.value);else if(e===11){const c=(l=a.querySelector('input[name="pm_plan"]:checked'))==null?void 0:l.value,d=this._meta.pm_prices||{};n.pm_offer=c?{plan:c,selected:!0,estimated_price:d[c]||0}:{}}else e===12?(n.discount=parseFloat(i.get("discount")??0),n.tax=parseFloat(i.get("tax")??0),n.paid=parseFloat(i.get("paid")??0)):e===13&&(n.tech_signature=i.get("tech_signature")??"",n.customer_signature=i.get("customer_signature")??"",n.company_stamp=i.get("company_stamp")??"");try{const c=await this.api.put(`service/reports/${s.data.id}`,n);s.data={...s.data,...(c==null?void 0:c.data)??n}}catch(c){console.error(c)}}_collectLines(e,t){const s=[],a=new Set;return e.querySelectorAll(`[name^="${t}_"]`).forEach(i=>{const n=i.name.match(new RegExp(`${t}_(\\w+)_(\\d+)`));n&&a.add(+n[2])}),[...a].sort((i,n)=>i-n).forEach(i=>{var r;const n=o=>{var l;return((l=e.querySelector(`[name="${t}_${o}_${i}"]`))==null?void 0:l.value)??""};if(t==="extra_costs"){const o=parseFloat(n("amount"))||0;(n("desc")||o)&&s.push({desc:n("desc"),amount:o})}else if(t==="part_lines"){const o=parseFloat(n("qty"))||0,l=parseFloat(n("unit_price"))||0,c=parseInt(((r=e.querySelector(`[name="${t}_product_id_${i}"]`))==null?void 0:r.value)??"0",10)||null;s.push({name:n("name"),part_no:n("part_no"),qty:o,unit_price:l,total:o*l,product_id:c})}else{const o=parseFloat(n("qty"))||0,l=parseFloat(n("unit_price"))||0;s.push({desc:n("desc")||n("name"),qty:o,unit:n("unit"),unit_price:l,total:o*l})}}),s}async _finalize(e){var s;if(!confirm("گزارش نهایی شود؟ پس از نهایی‌سازی قابل ویرایش نیست."))return;const t=prompt("شناسه انبار برای کسر قطعات (اختیاری — Enter برای رد کردن):","");try{const a=await this.api.post(`service/reports/${e}/finalize`,{warehouse_id:t&&t.trim()?parseInt(t,10):0}),i=(s=a==null?void 0:a.data)==null?void 0:s.public_url;i&&confirm("گزارش نهایی شد. صفحه چاپ/PDF باز شود؟")&&window.open(i,"_blank"),await this._load()}catch(a){alert(a.message)}}_fmt(e){return Number(e||0).toLocaleString("fa-IR")+" ریال"}}const fa={submitted:{label:"ثبت شده",color:"#6366f1"},assigned:{label:"تخصیص",color:"#3b82f6"},in_progress:{label:"در حال انجام",color:"#f59e0b"}};class Vo extends x{constructor(e){super(e),this._techs=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">🚐 Dispatch</h2>
                <div style="display:flex;gap:8px;">
                    <select data-ref="statusFilter" class="acc-input">
                        <option value="">همه فعال</option>
                        ${Object.entries(fa).map(([e,t])=>`<option value="${e}">${t.label}</option>`).join("")}
                    </select>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳</div></div>
        </div>`}async afterRender(){try{const e=await this.api.get("service/technicians");this._techs=(e==null?void 0:e.data)??[]}catch{this._techs=[]}await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("statusFilter"),"change",()=>this._load())}async _load(){var s;const e=(s=this.ref("statusFilter"))==null?void 0:s.value,t=e?{status:e}:{};this.ref("wrap").innerHTML='<div class="acc-loading">⏳</div>';try{const a=await this.api.get("service/dispatch/queue",t);this._rows=(a==null?void 0:a.data)??[],this._render()}catch(a){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(a.message)}</div>`}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">صف خالی است</div>';return}const e='<option value="">— کارشناس —</option>'+this._techs.map(t=>`<option value="${t.id}">${this.escape(t.name)}</option>`).join("");this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>کد</th><th>اولویت</th><th>خدمت</th><th>موضع</th><th>مشتری</th>
                <th>وضعیت</th><th>زمان اعزام</th><th>کارشناس</th><th>توضیح ارشد</th><th>چت</th><th></th>
            </tr></thead>
            <tbody>
            ${this._rows.map(t=>{const s=fa[t.status]??{label:t.status,color:"#64748b"},a=(t.scheduled_at||"").slice(0,16).replace("T"," "),i=t.priority==="urgent",n=i?'<span style="background:#fef2f2;color:#dc2626;padding:2px 6px;border-radius:8px;font-size:10px;font-weight:700;">فوری</span>':'<span style="color:#94a3b8;font-size:10px;">عادی</span>',r=t.has_priority_dispatch?'<span title="جایزه اولویت اعزام" style="margin-right:4px;">🎁</span>':"";return`<tr data-id="${t.id}" style="${i?"background:#fff1f2;":""}">
                    <td>${r}<b style="font-family:monospace;color:#1d4ed8;">${this.escape(t.tracking_code)}</b></td>
                    <td>${n}</td>
                    <td><small>${this.escape(t.service_type_label)}</small></td>
                    <td>${this.escape(t.site_label||"—")}</td>
                    <td>${this.escape(t.customer_name)}<br><small dir="ltr">${this.escape(t.phone)}</small></td>
                    <td><span style="background:${s.color}1a;color:${s.color};padding:2px 8px;border-radius:10px;font-size:11px;font-weight:700;">${s.label}</span></td>
                    <td><input type="datetime-local" class="acc-input" data-sched style="font-size:11px;width:150px;" value="${a?a.replace(" ","T"):""}"></td>
                    <td><select class="acc-input" data-tech style="font-size:11px;min-width:120px;">${e}</select></td>
                    <td><textarea class="acc-input" data-notes placeholder="توضیح ارشد برای کارشناس..." style="font-size:11px;width:140px;min-height:48px;">${this.escape(t.dispatch_notes||"")}</textarea></td>
                    <td>${t.conversation_id?'<button class="acc-btn acc-btn--sm acc-btn--secondary" data-chat title="باز کردن چت">💬</button>':"—"}</td>
                    <td><button class="acc-btn acc-btn--sm acc-btn--primary" data-save>💾</button></td>
                </tr>`}).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("tr[data-id]").forEach(t=>{var r;const s=+t.dataset.id,a=this._rows.find(o=>o.id==s),i=t.querySelector("[data-tech]"),n=t.querySelector("[data-sched]");a!=null&&a.assigned_technician_id&&(i.value=a.assigned_technician_id),(r=t.querySelector("[data-chat]"))==null||r.addEventListener("click",()=>{var o;a!=null&&a.conversation_id&&((o=this.eventBus)==null||o.emit("tab:open",{key:"chat"}),setTimeout(()=>{var l,c;(l=this.eventBus)==null||l.emit("chat:support:openRoom",{conversationId:+a.conversation_id}),(c=this.eventBus)==null||c.emit("chat:technician:openRoom",{conversationId:+a.conversation_id,requestId:+a.id})},400))}),t.querySelector("[data-save]").addEventListener("click",async()=>{var l;const o={technician_id:i.value?+i.value:0,scheduled_at:n.value?n.value.replace("T"," "):"",dispatch_notes:((l=t.querySelector("[data-notes]"))==null?void 0:l.value)||"",status:i.value?"assigned":"submitted"};try{await this.api.post(`service/requests/${s}/assign`,o),await this._load()}catch(c){alert(c.message)}})})}}class Wo extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📊 داشبورد خدمات</h2>
                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳</div>';try{const e=await this.api.get("service/dashboard"),t=(e==null?void 0:e.data)??{};this.ref("wrap").innerHTML=`
            <div style="display:grid;grid-template-columns:repeat(auto-fill,minmax(160px,1fr));gap:12px;">
                ${this._card("📋 باز",t.open_requests,"#6366f1")}
                ${this._card("📅 امروز",t.today_requests,"#3b82f6")}
                ${this._card("✅ ماه",t.completed_month,"#059669")}
                ${this._card("💰 درآمد ماه",Number(t.revenue_month||0).toLocaleString("fa-IR"),"#1d4ed8")}
                ${this._card("📝 پیش‌نویس",t.draft_reports,"#f59e0b")}
                ${this._card("📅 PM فعال",t.pm_contracts,"#8b5cf6")}
            </div>`}catch(e){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(e.message)}</div>`}}_card(e,t,s){return`
        <div style="background:#fff;border:1px solid #e2e8f0;border-radius:12px;padding:16px;border-top:3px solid ${s};">
            <div style="font-size:11px;color:#64748b;">${e}</div>
            <div style="font-size:22px;font-weight:800;color:${s};margin-top:4px;">${t??0}</div>
        </div>`}}const Uo={monthly:"ماهانه",quarterly:"سه‌ماهه",semi_annual:"شش‌ماهه",annual:"سالانه"},ma={active:"فعال",paused:"متوقف",cancelled:"لغو"};class Go extends x{async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">📅 قراردادهای PM</h2>
                <div style="display:flex;gap:8px;">
                    <button class="acc-btn acc-btn--primary" data-ref="runBtn">🔔 اجرای یادآوری</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
                </div>
            </div>
            <div data-ref="wrap"><div class="acc-loading">⏳</div></div>
        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("runBtn"),"click",()=>this._runReminders())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳</div>';try{const e=await this.api.get("service/pm/contracts");this._rows=(e==null?void 0:e.data)??[],this._render()}catch(e){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(e.message)}</div>`}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">قرارداد PM فعالی ثبت نشده — هنگام نهایی‌سازی گزارش با پیشنهاد PM ایجاد می‌شود.</div>';return}const e=new Date().toISOString().slice(0,10);this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>مشتری</th><th>موضع</th><th>برنامه</th><th>ویزیت بعدی</th><th>وضعیت</th><th>آخرین یادآوری</th><th></th>
            </tr></thead>
            <tbody>
            ${this._rows.map(t=>{const s=t.next_visit_date&&t.next_visit_date<=e&&t.status==="active",a=(()=>{try{return typeof t.visit_result=="string"?JSON.parse(t.visit_result||"{}"):t.visit_result||{}}catch{return{}}})();return`<tr style="${s?"background:#fff7ed;":""}">
                    <td>${this.escape(t.customer_name||"—")}<br><small dir="ltr">${this.escape(t.phone||"")}</small></td>
                    <td>${this.escape(t.site_label||"—")}</td>
                    <td>${Uo[t.plan]||t.plan}</td>
                    <td>${this.escape(t.next_visit_date||"—")}${s?" ⚠️":""}</td>
                    <td>${ma[t.status]||t.status}</td>
                    <td><small>${this.escape((t.last_reminder_at||"—").slice(0,16))}</small>
                        ${a.notes?`<br><small style="color:#059669;">✓ ${this.escape((a.notes||"").slice(0,40))}</small>`:""}
                    </td>
                    <td style="white-space:nowrap;">
                        <button class="acc-btn acc-btn--sm" data-visit="${t.id}">📝 بازدید</button>
                        <select class="acc-input" style="width:auto;font-size:12px;" data-pm-status="${t.id}">
                            ${Object.entries(ma).map(([i,n])=>`<option value="${i}" ${t.status===i?"selected":""}>${n}</option>`).join("")}
                        </select>
                    </td>
                </tr>`}).join("")}
            </tbody>
        </table>
        <p style="font-size:12px;color:#64748b;margin-top:12px;">یادآوری روزانه به‌صورت خودکار درخواست PM ایجاد می‌کند. cron: <code>run-svc-pm-cron.php</code></p>`,this.ref("wrap").querySelectorAll("[data-pm-status]").forEach(t=>{t.addEventListener("change",async()=>{const s=+t.dataset.pmStatus;try{await this.api.put(`service/pm/contracts/${s}`,{status:t.value}),await this._load()}catch(a){alert(a.message)}})}),this.ref("wrap").querySelectorAll("[data-visit]").forEach(t=>{t.addEventListener("click",()=>this._openVisitModal(+t.dataset.visit))})}_openVisitModal(e){const t=this._rows.find(n=>n.id===e);if(!t)return;let s=document.getElementById("svc-pm-visit-modal");s&&s.remove();const a=document.createElement("div");a.id="svc-pm-visit-modal",a.className="acc-modal",a.innerHTML=`
        <div class="acc-modal__box" style="max-width:480px;">
            <div class="acc-modal__header"><h3>📝 ثبت نتیجه بازدید PM</h3>
                <button class="acc-modal__close">✕</button></div>
            <form data-ref="visitForm" style="padding:16px;">
                <div class="acc-form-group"><label>ساعت کارکرد دستگاه</label>
                    <input name="operating_hours" type="number" class="acc-input" value="${t.operating_hours||0}"></div>
                <div class="acc-form-group"><label>وضعیت فیلتر</label>
                    <select name="filter_ok" class="acc-input"><option value="1">سالم</option><option value="0">نیاز تعویض</option></select></div>
                <div class="acc-form-group"><label>فشار مبرد</label><input name="pressure_ok" class="acc-input" placeholder="مثلاً نرمال"></div>
                <div class="acc-form-group"><label>یادداشت</label>
                    <textarea name="notes" class="acc-input" rows="3" placeholder="اقدامات انجام‌شده..."></textarea></div>
                <button type="submit" class="acc-btn acc-btn--primary" style="width:100%;">ثبت بازدید</button>
            </form>
        </div>`,document.body.appendChild(a);const i=()=>a.remove();a.querySelector(".acc-modal__close").addEventListener("click",i),a.querySelector("[data-ref=visitForm]").addEventListener("submit",async n=>{n.preventDefault();const r=new FormData(n.target);try{await this.api.post(`service/pm/contracts/${e}/visit`,{operating_hours:parseInt(r.get("operating_hours")||"0",10),visit_result:{filter_ok:r.get("filter_ok")==="1",pressure_ok:r.get("pressure_ok")||"",notes:r.get("notes")||"",visited_at:new Date().toISOString()}}),i(),await this._load()}catch(o){alert(o.message)}})}async _runReminders(){const e=this.ref("runBtn");e.disabled=!0;try{const t=await this.api.post("service/pm/run-reminders",{}),s=(t==null?void 0:t.data)??{};alert(`بررسی: ${s.checked??0} · درخواست جدید: ${s.created??0}`),await this._load()}catch(t){alert(t.message)}finally{e.disabled=!1}}}const Ko={supplier_pending:"در انتظار تأمین",ready:"آماده ارسال",shipped:"ارسال شده",delivered:"تحویل شده",cancelled:"لغو"};class Jo extends x{async template(){return`

        <div class="acc-section-wrap">

            <div class="acc-toolbar">

                <h2 class="acc-section-title">📦 سفارش قطعات</h2>

                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>

            </div>

            <div data-ref="wrap"><div class="acc-loading">⏳</div></div>

        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳</div>';try{const e=await this.api.get("service/parts/orders");this._rows=(e==null?void 0:e.data)??[],this._render()}catch(e){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(e.message)}</div>`}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">سفارش قطعه‌ای ثبت نشده — از ویجت «تأمین قطعات» ثبت کنید.</div>';return}this.ref("wrap").innerHTML=`

        <table class="acc-table">

            <thead><tr>

                <th>کد</th><th>قطعه</th><th>مشتری</th><th>قیمت</th><th>ETA</th><th>وضعیت</th><th></th>

            </tr></thead>

            <tbody>

            ${this._rows.map(e=>`<tr data-id="${e.id}">

                <td><b dir="ltr">${this.escape(e.tracking_code||"—")}</b></td>

                <td>${this.escape(e.part_number)} × ${e.part_qty}${e.in_stock?" ✅":""}</td>

                <td>${this.escape(e.customer_name)}<br><small dir="ltr">${this.escape(e.phone)}</small></td>

                <td>${Number(e.quote_price||0).toLocaleString("fa-IR")}</td>

                <td>${e.eta_days} روز</td>

                <td>

                    <select class="acc-input" data-status style="font-size:12px;width:auto;">

                        ${Object.entries(Ko).map(([t,s])=>`<option value="${t}" ${e.status===t?"selected":""}>${s}</option>`).join("")}

                    </select>

                </td>

                <td><button class="acc-btn acc-btn--sm acc-btn--primary" data-save>💾</button></td>

            </tr>`).join("")}

            </tbody>

        </table>

        <p style="font-size:12px;color:#64748b;margin-top:10px;">تغییر وضعیت به «تحویل شده» امتیاز تأمین‌کننده را فعال می‌کند.</p>`,this.ref("wrap").querySelectorAll("tr[data-id]").forEach(e=>{e.querySelector("[data-save]").addEventListener("click",async()=>{const t=+e.dataset.id,s=e.querySelector("[data-status]").value;try{await this.api.put(`service/parts/orders/${t}`,{status:s}),await this._load()}catch(a){alert(a.message)}})})}}const Yo={inquiry:"استعلام",quoted:"پیشنهاد داده شد",selected:"گزینه انتخاب شد",installed:"نصب/تحویل",cancelled:"لغو"};class Qo extends x{async template(){return`

        <div class="acc-section-wrap">

            <div class="acc-toolbar">

                <h2 class="acc-section-title">🏭 خرید تجهیزات</h2>

                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>

            </div>

            <div data-ref="wrap"><div class="acc-loading">⏳</div></div>

        </div>`}async afterRender(){await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load())}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳</div>';try{const e=await this.api.get("service/equipment/inquiries");this._rows=(e==null?void 0:e.data)??[],this._render()}catch(e){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(e.message)}</div>`}}_render(){if(!this._rows.length){this.ref("wrap").innerHTML='<div class="acc-empty">استعلام تجهیزاتی ثبت نشده.</div>';return}this.ref("wrap").innerHTML=this._rows.map(e=>this._cardHtml(e)).join(""),this.ref("wrap").querySelectorAll("[data-eq-save]").forEach(e=>{e.addEventListener("click",()=>this._save(+e.dataset.eqSave))})}_cardHtml(e){const t=e.quote_options||[];return`

        <div class="acc-card" style="margin-bottom:12px;padding:14px;border:1px solid #e2e8f0;border-radius:10px;" data-eq="${e.id}">

            <div style="display:flex;justify-content:space-between;align-items:flex-start;">

                <div>

                    <b dir="ltr">${this.escape(e.tracking_code)}</b> — ${this.escape(e.customer_name)}

                    <div style="font-size:12px;color:#64748b;">${this.escape(e.project_city)} · ${this.escape(e.application)} · ظرفیت: ${this.escape(e.required_capacity||"—")}</div>

                </div>

                <select class="acc-input" data-eq-status style="font-size:12px;width:auto;">

                    ${Object.entries(Yo).map(([s,a])=>`<option value="${s}" ${e.status===s?"selected":""}>${a}</option>`).join("")}

                </select>

            </div>

            <div style="margin-top:10px;display:grid;gap:8px;">

                ${t.map((s,a)=>`

                <div style="display:grid;grid-template-columns:1fr 120px;gap:8px;align-items:center;">

                    <input class="acc-input" data-opt-label="${a}" value="${this.escape(s.label||"")}" placeholder="عنوان گزینه">

                    <input class="acc-input" data-opt-price="${a}" type="number" value="${s.price||0}" placeholder="قیمت">

                </div>`).join("")}

            </div>

            <div style="margin-top:8px;display:flex;gap:8px;align-items:center;">

                <label style="font-size:12px;">گزینه انتخابی:</label>

                <select class="acc-input" data-selected style="font-size:12px;width:auto;">

                    <option value="">—</option>

                    ${t.map(s=>`<option value="${this.escape(s.key)}" ${e.selected_option===s.key?"selected":""}>${this.escape(s.label)}</option>`).join("")}

                </select>

                <button class="acc-btn acc-btn--primary acc-btn--sm" data-eq-save="${e.id}">💾 ذخیره پیشنهاد</button>

            </div>

        </div>`}async _save(e){var o,l;const t=this.ref("wrap").querySelector(`[data-eq="${e}"]`);if(!t)return;const s=[];let a=0;for(;t.querySelector(`[data-opt-label="${a}"]`);)s.push({key:["economy","standard","premium"][a]||`opt_${a}`,label:t.querySelector(`[data-opt-label="${a}"]`).value,price:parseFloat(t.querySelector(`[data-opt-price="${a}"]`).value)||0}),a++;const i=t.querySelector("[data-selected]").value,n=t.querySelector("[data-eq-status]").value,r=((o=s.find(c=>c.key===i))==null?void 0:o.price)||((l=s[0])==null?void 0:l.price)||0;try{await this.api.put(`service/equipment/inquiries/${e}`,{quote_options:s,selected_option:i,status:n,order_value:r}),await this._load()}catch(c){alert(c.message)}}}class Zo extends x{constructor(e){super(e),this._dash=null,this._team=[],this._users=[],this._pending=[]}async template(){return`
        <div class="acc-section-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">👨‍💼 پنل کارشناس ارشد</h2>
                <button class="acc-btn acc-btn--secondary" data-ref="refreshBtn">🔄</button>
            </div>
            <div data-ref="stats" class="acc-stats-row" style="display:flex;gap:12px;margin-bottom:16px;flex-wrap:wrap;"></div>
            <div class="acc-card" style="margin-bottom:16px;padding:16px;">
                <h3 style="margin:0 0 12px;font-size:14px;">➕ افزودن کارشناس به تیم</h3>
                <div style="display:flex;gap:8px;flex-wrap:wrap;align-items:center;">
                    <select class="acc-input" data-ref="userSel" style="min-width:220px;">
                        <option value="">— انتخاب کاربر —</option>
                    </select>
                    <button class="acc-btn acc-btn--primary" data-ref="addBtn">افزودن</button>
                </div>
            </div>
            <div data-ref="pending" style="margin-bottom:16px;"></div>
            <div data-ref="wrap"><div class="acc-loading">⏳</div></div>
        </div>`}async afterRender(){await this._loadUsers(),await this._load(),this.on(this.ref("refreshBtn"),"click",()=>this._load()),this.on(this.ref("addBtn"),"click",()=>this._addMember())}async _loadUsers(){try{const e=await this.api.get("acl/users");this._users=((e==null?void 0:e.data)??[]).filter(a=>a.user_id);const t=this.ref("userSel");if(!t)return;const s=new Set(this._team.map(a=>+a.technician_user_id));t.innerHTML='<option value="">— انتخاب کاربر —</option>'+this._users.filter(a=>!s.has(+a.user_id)).map(a=>`<option value="${a.user_id}">${this.escape(a.display_name||a.user_login)}</option>`).join("")}catch{this._users=[]}}async _load(){this.ref("wrap").innerHTML='<div class="acc-loading">⏳</div>',this.ref("pending")&&(this.ref("pending").innerHTML="");try{const[e,t,s]=await Promise.all([this.api.get("service/senior/dashboard"),this.api.get("service/senior/team"),this.api.get("service/reports/pending-review").catch(()=>({data:[]}))]);this._dash=(e==null?void 0:e.data)??{},this._team=(t==null?void 0:t.data)??[],this._pending=(s==null?void 0:s.data)??[],this._renderStats(),this._renderPending(),this._renderTeam(),await this._loadUsers()}catch(e){this.ref("wrap").innerHTML=`<div class="acc-error">❌ ${this.escape(e.message)}</div>`}}_renderPending(){var t;const e=this.ref("pending");if(e){if(!((t=this._pending)!=null&&t.length)){e.innerHTML="";return}e.innerHTML=`
        <div class="acc-card" style="padding:16px;">
            <h3 style="margin:0 0 12px;font-size:14px;">📝 گزارش‌های در انتظار بازبینی (${this._pending.length})</h3>
            <table class="acc-table" style="font-size:12px;">
                <thead><tr><th>شماره</th><th>مشتری</th><th>مبلغ</th><th>تاریخ</th><th>یادداشت</th><th></th></tr></thead>
                <tbody>
                ${this._pending.map(s=>`<tr data-rid="${s.id}">
                    <td><b>${this.escape(s.report_no)}</b></td>
                    <td>${this.escape(s.customer_name)}</td>
                    <td>${Number(s.total||0).toLocaleString("fa-IR")}</td>
                    <td><small>${(s.finalized_at||"").slice(0,16)}</small></td>
                    <td><input class="acc-input" data-note style="font-size:11px;width:120px;" placeholder="توضیح"></td>
                    <td style="white-space:nowrap;">
                        <button class="acc-btn acc-btn--sm acc-btn--primary" data-approve>✅</button>
                        <button class="acc-btn acc-btn--sm" data-reject>❌</button>
                    </td>
                </tr>`).join("")}
                </tbody>
            </table>
        </div>`,e.querySelectorAll("[data-approve]").forEach(s=>{s.addEventListener("click",async()=>{var i;const a=s.closest("tr");await this._review(+a.dataset.rid,"approved",(i=a.querySelector("[data-note]"))==null?void 0:i.value)})}),e.querySelectorAll("[data-reject]").forEach(s=>{s.addEventListener("click",async()=>{var i;const a=s.closest("tr");await this._review(+a.dataset.rid,"rejected",(i=a.querySelector("[data-note]"))==null?void 0:i.value)})})}}async _review(e,t,s){try{await this.api.post(`service/reports/${e}/senior-review`,{status:t,note:s}),await this._load()}catch(a){alert(a.message)}}_renderStats(){const e=this._dash||{};this.ref("stats").innerHTML=[{label:"اعضای تیم",val:e.team_size??0,color:"#3b82f6"},{label:"درخواست باز",val:e.open??0,color:"#f59e0b"},{label:"تخصیص فعال",val:e.assigned??0,color:"#10b981"}].map(t=>`
            <div style="background:${t.color}12;border:1px solid ${t.color}33;border-radius:10px;padding:12px 20px;min-width:120px;">
                <div style="font-size:22px;font-weight:700;color:${t.color};">${t.val}</div>
                <div style="font-size:12px;color:#64748b;">${t.label}</div>
            </div>`).join("")}_renderTeam(){if(!this._team.length){this.ref("wrap").innerHTML='<div class="acc-empty">هنوز کارشناسی به تیم اضافه نشده</div>';return}this.ref("wrap").innerHTML=`
        <table class="acc-table">
            <thead><tr>
                <th>کارشناس</th><th>ایمیل</th><th>وضعیت</th><th></th>
            </tr></thead>
            <tbody>
            ${this._team.map(e=>`
                <tr>
                    <td>${this.escape(e.technician_name)}</td>
                    <td dir="ltr">${this.escape(e.technician_email||"—")}</td>
                    <td><span style="color:${e.status==="active"?"#10b981":"#94a3b8"};">${e.status==="active"?"فعال":"غیرفعال"}</span></td>
                    <td>
                        ${e.status==="active"?`<button class="acc-btn acc-btn--sm acc-btn--danger" data-rm="${e.technician_user_id}">حذف</button>`:""}
                    </td>
                </tr>`).join("")}
            </tbody>
        </table>`,this.ref("wrap").querySelectorAll("[data-rm]").forEach(e=>{e.addEventListener("click",async()=>{if(confirm("این کارشناس از تیم حذف شود؟"))try{await this.api.delete(`service/senior/team/${e.dataset.rm}`),await this._load()}catch(t){alert(t.message)}})})}async _addMember(){var t;const e=+(((t=this.ref("userSel"))==null?void 0:t.value)||0);if(!e){alert("کاربر را انتخاب کنید");return}try{await this.api.post("service/senior/team",{technician_user_id:e}),await this._load()}catch(s){alert(s.message)}}}class Xo extends pa{getTitle(){return"🔧 صف کار من"}}const jt=[{key:"tech_service_pct",label:"سهم کارشناس از خدمات (%)",group:"کارشناس"},{key:"tech_parts_pct",label:"سهم کارشناس از قطعات (%)",group:"کارشناس"},{key:"senior_service_pct",label:"سهم کارشناس ارشد از خدمات (%)",group:"کارشناس ارشد"},{key:"senior_team_override_pct",label:"پاداش ارشد از کل فاکتور (%)",group:"کارشناس ارشد"},{key:"parts_cogs_pct",label:"بهای تمام‌شده قطعات (%)",group:"بهای تمام‌شده"},{key:"supplier_margin_pct",label:"حاشیه تأمین‌کننده (%)",group:"تأمین‌کننده"},{key:"discount_company_pct",label:"سهم شرکت از تخفیف (%)",group:"تخفیف/پاداش"},{key:"reward_expense_per_point",label:"هزینه هر امتیاز پاداش (ریال)",group:"تخفیف/پاداش",step:1},{key:"overhead_energy_pct",label:"سربار انرژی (%)",group:"سربار"},{key:"overhead_repair_pct",label:"سربار تعمیرگاه (%)",group:"سربار"}];class el extends x{async template(){return`
        <div class="acc-section-wrap svc-acc-wrap">
            <div class="acc-toolbar">
                <h2 class="acc-section-title">💰 صدور سند خدمات (حسابدار)</h2>
                <div style="display:flex;gap:8px;flex-wrap:wrap;">
                    <button class="acc-btn acc-btn--secondary" data-ref="tabQueue" data-tab="queue">📋 صف صدور</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="tabPortal" data-tab="portal">🏢 هویت شعبه</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="tabConfig" data-tab="config">⚙️ تنظیم سهم‌ها</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="tabCost" data-tab="cost">📊 بهای تمام‌شده</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="tabGraph" data-tab="graph">🕸 گراف فعالیت</button>
                    <button class="acc-btn acc-btn--secondary" data-ref="tabPreview" data-tab="preview">🔍 پیش‌نمایش</button>
                </div>
            </div>
            <div data-ref="officeBanner" class="svc-acc-office-banner"></div>
            <div data-ref="panel"></div>
        </div>`}async afterRender(){this._tab="queue",this._serviceTypes={},this._config={},this._portal={},this._canPost=!1,this._canConfig=!1,await this._loadMeta(),this._renderOfficeBanner(),this._bindTabs(),await this._renderTab()}_renderOfficeBanner(){var t;const e=this.ref("officeBanner");!e||!((t=this._portal)!=null&&t.office_name)||(e.innerHTML=`
        <div class="svc-acc-office">
            <span class="svc-acc-office__tag">${this.escape(this._portal.ledger_tag||"SERVICE")}</span>
            <strong>${this.escape(this._portal.subsystem_label||"پورتال خدمات")}</strong>
            <span>— شعبه: <b>${this.escape(this._portal.office_name)}</b> (${this.escape(this._portal.office_code)})</span>
            <small>همه اسناد با برچسب [${this.escape(this._portal.ledger_tag)}|${this.escape(this._portal.office_name)}] در ERP ثبت می‌شوند</small>
        </div>`)}_bindTabs(){var e;this.root.querySelectorAll("[data-tab]").forEach(t=>{t.addEventListener("click",async()=>{this._tab=t.dataset.tab,this.root.querySelectorAll("[data-tab]").forEach(s=>s.classList.toggle("acc-btn--primary",s.dataset.tab===this._tab)),await this._renderTab()})}),(e=this.root.querySelector('[data-tab="queue"]'))==null||e.classList.add("acc-btn--primary")}async _loadMeta(){try{const e=await this.api.get("service/accounting/config"),t=(e==null?void 0:e.data)??e??{};this._config=t.config??{},this._serviceTypes=t.service_types??{},this._defaults=t.defaults??{},this._portal=t.portal??{},this._canPost=!!t.can_post,this._canConfig=!!t.can_config}catch{this._config={},this._serviceTypes={},this._portal={}}}async _renderTab(){const e=this.ref("panel");e&&(this._tab==="queue"?await this._renderQueue(e):this._tab==="portal"?await this._renderPortal(e):this._tab==="config"?await this._renderConfig(e):this._tab==="cost"?await this._renderCost(e):this._tab==="graph"?await this._renderGraph(e):await this._renderPreview(e))}async _renderQueue(e){e.innerHTML='<div class="acc-loading">⏳</div>';try{const t=await this.api.get("service/accounting/pending"),s=(t==null?void 0:t.data)??{},a=s.invoices??[],i=s.other??[],n=s.counts??{};e.innerHTML=`
            <div class="svc-acc-queue">
                <div class="svc-acc-queue-stats">
                    <span>📋 ${n.total??0} مورد در صف</span>
                    <span>فاکتور: ${n.invoices??0}</span>
                    <span>سایر: ${n.other??0}</span>
                </div>
                <h4>فاکتورهای خدمات (SERVICE_INVOICE)</h4>
                <table class="acc-table">
                    <thead><tr>
                        <th>SRD</th><th>مشتری</th><th>مبلغ</th><th>رویداد</th><th>وضعیت</th><th></th>
                    </tr></thead>
                    <tbody>${a.length?a.map(r=>`
                        <tr>
                            <td><b>${this.escape(r.report_no||r.id)}</b></td>
                            <td>${this.escape(r.customer_name||"—")}</td>
                            <td>${Number(r.total||0).toLocaleString("fa-IR")}</td>
                            <td>${r.event_id?`#${r.event_id}`:"—"}</td>
                            <td>${this._stateBadge(r.workflow_state)}</td>
                            <td>
                                <button class="acc-btn acc-btn--sm" data-preview-report="${r.id}">👁</button>
                                ${this._canPost?`<button class="acc-btn acc-btn--sm acc-btn--success" data-post-report="${r.id}">✅ صدور سند</button>`:""}
                            </td>
                        </tr>`).join(""):'<tr><td colspan="6">صف خالی — SRD نهایی‌شده‌ای بدون سند نیست</td></tr>'}
                    </tbody>
                </table>
                ${i.length?`
                <h4 style="margin-top:20px;">دریافت / تأمین‌کننده</h4>
                <table class="acc-table">
                    <thead><tr><th>نوع</th><th>رویداد</th><th>مبلغ</th><th>وضعیت</th><th></th></tr></thead>
                    <tbody>${i.map(r=>`
                        <tr>
                            <td>${this.escape(r.event_type)}</td>
                            <td>#${r.acc_event_id}</td>
                            <td>${Number(r.amount||0).toLocaleString("fa-IR")}</td>
                            <td>${this._stateBadge(r.workflow_state)}</td>
                            <td>${this._canPost?`<button class="acc-btn acc-btn--sm acc-btn--success" data-post-event="${r.acc_event_id}">✅ صدور</button>`:""}</td>
                        </tr>`).join("")}
                    </tbody>
                </table>`:""}
                <div data-ref="queuePreview" style="margin-top:16px;"></div>
            </div>`,e.querySelectorAll("[data-post-report]").forEach(r=>{r.addEventListener("click",()=>this._postReport(+r.dataset.postReport,r))}),e.querySelectorAll("[data-post-event]").forEach(r=>{r.addEventListener("click",()=>this._postEvent(+r.dataset.postEvent,r))}),e.querySelectorAll("[data-preview-report]").forEach(r=>{r.addEventListener("click",()=>this._previewInQueue(+r.dataset.previewReport))})}catch(t){e.innerHTML=`<div class="acc-error">❌ ${this.escape(t.message)}</div>`}}_stateBadge(e){return e==="posted"?'<span style="color:#059669;">✅ صادر شده</span>':e==="failed"?'<span style="color:#dc2626;">❌ خطا</span>':e==="pending"||!e?'<span style="color:#f59e0b;">⏳ در انتظار صدور</span>':this.escape(e||"—")}async _postReport(e,t){if(confirm("صدور سند حسابداری ERP برای این فاکتور خدمات؟")){t.disabled=!0,t.textContent="...";try{const s=await this.api.post(`service/accounting/post/${e}`);alert((s==null?void 0:s.message)||(s!=null&&s.success?"سند صادر شد":"خطا")),await this._renderQueue(this.ref("panel"))}catch(s){alert("خطا: "+s.message),t.disabled=!1,t.textContent="✅ صدور سند"}}}async _postEvent(e,t){if(confirm(`صدور سند ERP برای رویداد #${e}؟`)){t.disabled=!0;try{const s=await this.api.post(`service/accounting/post-event/${e}`);alert((s==null?void 0:s.message)||(s!=null&&s.success?"سند صادر شد":"خطا")),await this._renderQueue(this.ref("panel"))}catch(s){alert("خطا: "+s.message),t.disabled=!1}}}async _previewInQueue(e){const t=this.ref("queuePreview");if(t){t.innerHTML='<div class="acc-loading">⏳</div>';try{const s=await this.api.get(`service/accounting/preview/${e}`);t.innerHTML=this._splitsHtml((s==null?void 0:s.data)??{})}catch(s){t.innerHTML=`<div class="acc-error">${this.escape(s.message)}</div>`}}}async _renderPortal(e){var s;const t=this._portal;e.innerHTML=`
        <div class="svc-acc-portal">
            <p class="svc-acc-hint">برای تفکیک چند دفتر/شعبه خدماتی، هویت این پورتال را مشخص کنید. در اسناد ERP و ابعاد <strong>BRANCH</strong> ثبت می‌شود.</p>
            <form data-ref="portalForm" class="svc-acc-grid" style="max-width:520px;">
                <label class="acc-form-group"><span>کد شعبه</span>
                    <input name="office_code" value="${this.escape(t.office_code||"")}" ${this._canConfig?"":"readonly"}></label>
                <label class="acc-form-group"><span>نام شعبه / دفتر خدمات</span>
                    <input name="office_name" value="${this.escape(t.office_name||"")}" ${this._canConfig?"":"readonly"}></label>
                <label class="acc-form-group"><span>عنوان سیستم</span>
                    <input name="subsystem_label" value="${this.escape(t.subsystem_label||"")}" ${this._canConfig?"":"readonly"}></label>
                <label class="acc-form-group"><span>برچسب دفتر (ledger)</span>
                    <input name="ledger_tag" value="${this.escape(t.ledger_tag||"SERVICE")}" ${this._canConfig?"":"readonly"}></label>
                ${this._canConfig?'<button type="submit" class="acc-btn acc-btn--primary">💾 ذخیره هویت شعبه</button>':'<p style="color:#94a3b8;">فقط مدیر می‌تواند ویرایش کند</p>'}
            </form>
        </div>`,this._canConfig&&((s=e.querySelector('[data-ref="portalForm"]'))==null||s.addEventListener("submit",async a=>{a.preventDefault();const i=Object.fromEntries(new FormData(a.target).entries());await this.api.put("service/accounting/portal",i),this._portal=i,this._renderOfficeBanner(),this._toast("✅ هویت شعبه ذخیره شد")}))}async _renderConfig(e){var n;if(!this._canConfig){e.innerHTML='<div class="acc-empty">تنظیم درصد سهم‌ها فقط برای مدیر سیستم است.</div>';return}const t='<option value="_default">پیش‌فرض (همه خدمات)</option>'+Object.entries(this._serviceTypes).map(([r,o])=>`<option value="${this.escape(r)}">${this.escape(o)}</option>`).join(""),a=[...new Set(jt.map(r=>r.group))].map(r=>`
            <div class="svc-acc-group">
                <h4>${this.escape(r)}</h4>
                <div class="svc-acc-grid">
                    ${jt.filter(o=>o.group===r).map(o=>{var l;return`
                        <label class="acc-form-group">
                            <span>${this.escape(o.label)}</span>
                            <input type="number" name="${o.key}" step="${o.step||.1}" min="0"
                                   value="${this._config[o.key]??((l=this._defaults)==null?void 0:l[o.key])??0}">
                        </label>`}).join("")}
                </div>
            </div>`).join("");e.innerHTML=`
        <div class="svc-acc-config">
            <div class="acc-form-row" style="margin-bottom:16px;">
                <label class="acc-form-group">
                    <span>نوع خدمت</span>
                    <select data-ref="serviceTypeSel">${t}</select>
                </label>
                <label class="acc-form-group svc-acc-check">
                    <input type="checkbox" name="auto_post" ${this._config.auto_post?"checked":""}>
                    صدور خودکار (پیشنهاد: خاموش — حسابدار صادر کند)
                </label>
                <label class="acc-form-group svc-acc-check">
                    <input type="checkbox" name="use_dimensions" ${this._config.use_dimensions!==!1?"checked":""}>
                    ابعاد: مشتری / کارشناس / شعبه / نوع خدمت
                </label>
            </div>
            <form data-ref="configForm">${a}
                <div style="margin-top:16px;display:flex;gap:8px;">
                    <button type="submit" class="acc-btn acc-btn--primary">💾 ذخیره</button>
                </div>
            </form>
        </div>`;const i=e.querySelector('[data-ref="serviceTypeSel"]');i==null||i.addEventListener("change",async()=>{var c;const r=i.value==="_default"?"":i.value,o=r?`?service_type=${encodeURIComponent(r)}`:"",l=await this.api.get(`service/accounting/config${o}`);this._config=((c=l==null?void 0:l.data)==null?void 0:c.config)??{},await this._renderConfig(e)}),(n=e.querySelector('[data-ref="configForm"]'))==null||n.addEventListener("submit",async r=>{var c,d;r.preventDefault();const o=new FormData(r.target),l=Object.fromEntries(o.entries());l.auto_post=!!((c=e.querySelector('[name="auto_post"]'))!=null&&c.checked),l.use_dimensions=!!((d=e.querySelector('[name="use_dimensions"]'))!=null&&d.checked),jt.forEach(h=>{l[h.key]=parseFloat(l[h.key])||0}),await this.api.put("service/accounting/config",{service_type:(i==null?void 0:i.value)||"_default",config:l}),this._toast("✅ ذخیره شد")})}async _renderCost(e){e.innerHTML='<div class="acc-loading">⏳</div>';try{const t=await this.api.get("service/accounting/cost-report"),s=(t==null?void 0:t.data)??{},a=s.totals??{},i=s.by_entity??[];e.innerHTML=`
            <div class="svc-acc-cost">
                <div class="svc-acc-kpis">
                    ${this._kpi("درآمد",a.revenue,"#1d4ed8")}
                    ${this._kpi("حق‌الزحمه کارشناس",a.tech_fee,"#00A1E4")}
                    ${this._kpi("سهم ارشد",a.senior_fee,"#0077B6")}
                    ${this._kpi("COGS",a.parts_cogs,"#dc2626")}
                    ${this._kpi("سربار",a.overhead,"#64748b")}
                    ${this._kpi("حاشیه",a.margin,"#059669")}
                </div>
                <h4 style="margin:20px 0 10px;">سهم موجودیت‌ها (نفر / شرکت / مشتری)</h4>
                <div class="svc-table-wrap">
                    <table class="acc-table">
                        <thead><tr><th>نوع</th><th>نام</th><th>سهم درآمد</th><th>بهای تمام‌شده</th><th>کارمزد/حاشیه</th></tr></thead>
                        <tbody>
                            ${i.length?i.map(n=>`<tr>
                                <td>${this.escape(n.entity_type)}</td>
                                <td>${this.escape(n.entity_label||"—")}</td>
                                <td>${Number(n.revenue||0).toLocaleString("fa-IR")}</td>
                                <td>${Number(n.cost||0).toLocaleString("fa-IR")}</td>
                                <td>${Number(n.margin||0).toLocaleString("fa-IR")}</td>
                            </tr>`).join(""):'<tr><td colspan="5">داده‌ای نیست</td></tr>'}
                        </tbody>
                    </table>
                </div>
                <p class="svc-acc-hint">برای گراف فعالیت و سهم هر نفر از هر سفارش، تب «گراف فعالیت» را باز کنید.</p>
            </div>`}catch(t){e.innerHTML=`<div class="acc-error">❌ ${this.escape(t.message)}</div>`}}async _renderGraph(e){var t,s,a,i,n;e.innerHTML='<div class="acc-loading">⏳ در حال ساخت گراف بهای فعالیت…</div>';try{const[r,o]=await Promise.all([this.api.get("service/accounting/cost-graph"),this.api.get("service/accounting/activities?all=1")]),l=(r==null?void 0:r.data)??{},c=(o==null?void 0:o.data)??[];this._roles=((t=r==null?void 0:r.data)==null?void 0:t.role_labels)||(o==null?void 0:o.roles)||{};const d=l.nodes||[],h=l.edges||[],u=l.person_shares||[],f=l.orders||[];e.innerHTML=`
            <div class="svc-abc">
                <div class="svc-abc__intro">
                    <h3>حسابداری صنعتی — بهای تمام‌شده فعالیت‌ها (ABC) + گراف تخصیص</h3>
                    <p>هر سفارش به فعالیت‌های میدانی شکسته می‌شود؛ سپس سهم هر نفر از هر فعالیت مشخص می‌گردد.</p>
                </div>
                <div class="svc-abc__toolbar">
                    <label>شناسه SRD
                        <input type="number" min="1" data-ref="abcReportId" placeholder="مثلاً ۱۲">
                    </label>
                    <button class="acc-btn acc-btn--primary" data-ref="abcLoadOne">نمایش گراف سفارش</button>
                    <button class="acc-btn" data-ref="abcReload">بازه جاری</button>
                    <button class="acc-btn" data-ref="abcAlloc">محاسبه و ذخیره تخصیص</button>
                </div>
                <div class="svc-abc__layout">
                    <div class="svc-abc__graph-wrap">
                        <svg data-ref="abcSvg" class="svc-abc__svg" viewBox="0 0 900 520" role="img" aria-label="گراف بهای فعالیت"></svg>
                        <div class="svc-abc__legend">
                            <span><i class="c-order"></i> سفارش</span>
                            <span><i class="c-act"></i> فعالیت</span>
                            <span><i class="c-person"></i> نفر</span>
                        </div>
                    </div>
                    <div class="svc-abc__side">
                        <h4>سهم نفرها</h4>
                        <div class="svc-table-wrap">
                            <table class="acc-table">
                                <thead><tr><th>نفر</th><th>مبلغ</th><th>سفارش‌ها</th></tr></thead>
                                <tbody data-ref="abcPersons">
                                    ${u.length?u.map(m=>`<tr>
                                        <td>${this.escape(m.name)}</td>
                                        <td>${Number(m.amount||0).toLocaleString("fa-IR")}</td>
                                        <td>${Number(m.orders||0).toLocaleString("fa-IR")}</td>
                                    </tr>`).join(""):'<tr><td colspan="3">هنوز تخصیصی نیست — یک SRD را محاسبه کنید</td></tr>'}
                                </tbody>
                            </table>
                        </div>
                        <h4 style="margin-top:16px;">سفارش‌ها</h4>
                        <div class="svc-table-wrap">
                            <table class="acc-table">
                                <thead><tr><th>کد</th><th>مشتری</th><th>درآمد</th><th>بهای فعالیت</th><th>نفر</th></tr></thead>
                                <tbody>
                                    ${f.length?f.map(m=>`<tr data-rid="${m.report_id}" class="svc-abc__order-row">
                                        <td><button type="button" class="acc-btn acc-btn--secondary" data-open-rid="${m.report_id}">${this.escape(m.tracking||m.report_id)}</button></td>
                                        <td>${this.escape(m.customer||"—")}</td>
                                        <td>${Number(m.revenue||0).toLocaleString("fa-IR")}</td>
                                        <td>${Number(m.cost||0).toLocaleString("fa-IR")}</td>
                                        <td>${Number(m.persons||0).toLocaleString("fa-IR")}</td>
                                    </tr>`).join(""):'<tr><td colspan="5">سفارش نهایی در بازه نیست</td></tr>'}
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
                <div data-ref="abcDetail" class="svc-abc__detail"></div>
                <details class="svc-abc__acts">
                    <summary>کاتالوگ فعالیت‌ها (${c.length})</summary>
                    <div class="svc-table-wrap">
                        <table class="acc-table">
                            <thead><tr><th>کد</th><th>نام</th><th>استخر</th><th>وزن</th><th>محرک</th><th>نقش‌ها</th></tr></thead>
                            <tbody>
                                ${c.map(m=>`<tr>
                                    <td><code>${this.escape(m.code)}</code></td>
                                    <td>${this.escape(m.name)}</td>
                                    <td>${this.escape(m.pool)}</td>
                                    <td>${m.weight}</td>
                                    <td>${this.escape(m.driver)}</td>
                                    <td>${this.escape((m.roles||[]).join("، "))}</td>
                                </tr>`).join("")}
                            </tbody>
                        </table>
                    </div>
                </details>
                <div class="svc-abc__crew">
                    <h4>خدمه سفارش (چندنفره)</h4>
                    <div class="acc-form-row">
                        <label>شناسه درخواست (request_id)
                            <input type="number" min="1" data-ref="crewReqId">
                        </label>
                        <button class="acc-btn" data-ref="crewLoad">بارگذاری خدمه</button>
                    </div>
                    <div data-ref="crewBox"></div>
                </div>
            </div>`,this._paintAbcGraph(e.querySelector('[data-ref="abcSvg"]'),d,h),(s=e.querySelector('[data-ref="abcReload"]'))==null||s.addEventListener("click",()=>this._renderGraph(e)),(a=e.querySelector('[data-ref="abcLoadOne"]'))==null||a.addEventListener("click",async()=>{var b;const m=(b=e.querySelector('[data-ref="abcReportId"]'))==null?void 0:b.value;m&&await this._loadGraphReport(e,m)}),(i=e.querySelector('[data-ref="abcAlloc"]'))==null||i.addEventListener("click",async()=>{var b;const m=(b=e.querySelector('[data-ref="abcReportId"]'))==null?void 0:b.value;if(!m){this._toast("شناسه SRD را وارد کنید");return}await this.api.post(`service/accounting/allocate/${m}`,{}),this._toast("✅ تخصیص ذخیره شد"),await this._loadGraphReport(e,m)}),e.querySelectorAll("[data-open-rid]").forEach(m=>{m.addEventListener("click",async()=>{const b=m.getAttribute("data-open-rid");e.querySelector('[data-ref="abcReportId"]').value=b,await this._loadGraphReport(e,b)})}),(n=e.querySelector('[data-ref="crewLoad"]'))==null||n.addEventListener("click",()=>this._loadCrewEditor(e))}catch(r){e.innerHTML=`<div class="acc-error">❌ ${this.escape(r.message)}</div>`}}async _loadGraphReport(e,t){const s=e.querySelector('[data-ref="abcDetail"]');s&&(s.innerHTML='<div class="acc-loading">⏳</div>');try{const[a,i]=await Promise.all([this.api.get(`service/accounting/cost-graph?report_id=${t}`),this.api.get(`service/accounting/activity-cost/${t}`)]),n=(a==null?void 0:a.data)??{};this._paintAbcGraph(e.querySelector('[data-ref="abcSvg"]'),n.nodes||[],n.edges||[]);const r=e.querySelector('[data-ref="abcPersons"]');if(r){const d=n.person_shares||[];r.innerHTML=d.length?d.map(h=>`<tr>
                    <td>${this.escape(h.name)}</td>
                    <td>${Number(h.amount||0).toLocaleString("fa-IR")}</td>
                    <td>${Number(h.orders||1).toLocaleString("fa-IR")}</td>
                </tr>`).join(""):'<tr><td colspan="3">—</td></tr>'}const o=(i==null?void 0:i.data)??{},l=o.lines||[],c=o.person_shares||[];if(s&&(s.innerHTML=`
                <h4>جزئیات تخصیص سفارش #${this.escape(String(t))}</h4>
                <div class="svc-abc__pools">
                    ${Object.entries(o.pools||{}).map(([d,h])=>`<div class="svc-acc-kpi"><span>${this.escape(d)}</span><b>${Number(h).toLocaleString("fa-IR")}</b></div>`).join("")}
                </div>
                <div class="svc-table-wrap" style="margin-top:12px;">
                    <table class="acc-table">
                        <thead><tr><th>فعالیت</th><th>نفر</th><th>نقش</th><th>محرک</th><th>سهم٪</th><th>مبلغ</th></tr></thead>
                        <tbody>
                            ${l.map(d=>`<tr>
                                <td>${this.escape(d.activity_name)}</td>
                                <td>${this.escape(d.person_label)}</td>
                                <td>${this.escape(d.role_code)}</td>
                                <td>${Number(d.driver_qty||0).toLocaleString("fa-IR")}</td>
                                <td>${Number(d.share_pct||0).toLocaleString("fa-IR")}</td>
                                <td><strong>${Number(d.amount||0).toLocaleString("fa-IR")}</strong></td>
                            </tr>`).join("")}
                        </tbody>
                    </table>
                </div>
                <h4 style="margin-top:14px;">جمع سهم هر نفر از این سفارش</h4>
                <div class="svc-table-wrap">
                    <table class="acc-table">
                        <thead><tr><th>نفر</th><th>نقش</th><th>بهای فعالیت</th><th>سهم درآمد خدمات</th></tr></thead>
                        <tbody>
                            ${c.map(d=>`<tr>
                                <td>${this.escape(d.name)}</td>
                                <td>${this.escape(d.role||"")}</td>
                                <td>${Number(d.amount||0).toLocaleString("fa-IR")}</td>
                                <td>${Number(d.revenue_share||0).toLocaleString("fa-IR")}</td>
                            </tr>`).join("")||'<tr><td colspan="4">—</td></tr>'}
                        </tbody>
                    </table>
                </div>`),o.request_id){const d=e.querySelector('[data-ref="crewReqId"]');d&&(d.value=o.request_id)}}catch(a){s&&(s.innerHTML=`<div class="acc-error">${this.escape(a.message)}</div>`)}}async _loadCrewEditor(e){var a,i,n;const t=e.querySelector('[data-ref="crewBox"]'),s=(a=e.querySelector('[data-ref="crewReqId"]'))==null?void 0:a.value;if(!(!t||!s)){t.innerHTML='<div class="acc-loading">⏳</div>';try{const r=await this.api.get(`service/accounting/crew/${s}`),o=(r==null?void 0:r.data)??[],l=(r==null?void 0:r.roles)||this._roles||{};this._roleMap=l,t.innerHTML=`
            <p class="svc-acc-hint">وزن و ساعت هر نفر مبنای تخصیص فعالیت‌هاست. پس از ذخیره، «محاسبه و ذخیره تخصیص» را بزنید.</p>
            <div data-ref="crewRows">
                ${o.map((c,d)=>this._crewRowHtml(c,d)).join("")||this._crewRowHtml({},0)}
            </div>
            <div style="display:flex;gap:8px;margin-top:10px;">
                <button type="button" class="acc-btn" data-ref="crewAdd">+ نفر</button>
                <button type="button" class="acc-btn acc-btn--primary" data-ref="crewSave">💾 ذخیره خدمه</button>
            </div>`,(i=t.querySelector('[data-ref="crewAdd"]'))==null||i.addEventListener("click",()=>{const c=t.querySelector('[data-ref="crewRows"]'),d=c.children.length;c.insertAdjacentHTML("beforeend",this._crewRowHtml({},d))}),(n=t.querySelector('[data-ref="crewSave"]'))==null||n.addEventListener("click",async()=>{const c=[...t.querySelectorAll("[data-crew-row]")].map(d=>{var h,u,f,m,b;return{user_id:+((h=d.querySelector("[name=user_id]"))==null?void 0:h.value)||0,role:((u=d.querySelector("[name=role]"))==null?void 0:u.value)||"lead",weight:parseFloat((f=d.querySelector("[name=weight]"))==null?void 0:f.value)||1,hours:parseFloat((m=d.querySelector("[name=hours]"))==null?void 0:m.value)||0,note:((b=d.querySelector("[name=note]"))==null?void 0:b.value)||""}}).filter(d=>d.user_id>0);await this.api.put(`service/accounting/crew/${s}`,{crew:c}),this._toast("✅ خدمه ذخیره شد")})}catch(r){t.innerHTML=`<div class="acc-error">${this.escape(r.message)}</div>`}}}_crewRowHtml(e={},t=0){const s=e.role||"lead",a=this._roleMap||{lead:"کارشناس مسئول",assistant:"کمک‌کارشناس",senior:"کارشناس ارشد",helper:"کمک میدانی"},i=Object.entries(a).filter(([n])=>n!=="company").map(([n,r])=>`<option value="${n}" ${n===s?"selected":""}>${this.escape(r)}</option>`).join("");return`<div class="svc-abc__crew-row" data-crew-row="${t}">
            <input name="user_id" type="number" min="1" placeholder="user_id" value="${e.user_id||""}">
            <select name="role">${i}</select>
            <input name="weight" type="number" step="0.1" min="0.1" placeholder="وزن" value="${e.weight??1}">
            <input name="hours" type="number" step="0.5" min="0" placeholder="ساعت" value="${e.hours??0}">
            <input name="note" type="text" placeholder="یادداشت" value="${this.escape(e.note||e.name||"")}">
        </div>`}_paintAbcGraph(e,t,s){if(!e)return;const a=900,i=520,n={order:{x:a*.18,y:i*.5},activity:{x:a*.5,y:i*.5},person:{x:a*.82,y:i*.5}},r={order:"#00A1E4",activity:"#F2994A",person:"#27AE60"},o=t.map((u,f)=>{const m=n[u.type]||{x:a/2,y:i/2},b=f%7*28-70;return{...u,x:m.x+(Math.random()-.5)*40,y:Math.max(40,Math.min(i-40,m.y+b+(Math.random()-.5)*30)),vx:0,vy:0}}),l=Object.fromEntries(o.map(u=>[u.id,u]));for(let u=0;u<90;u++){o.forEach(f=>{f.fx=0,f.fy=0});for(let f=0;f<o.length;f++)for(let m=f+1;m<o.length;m++){const b=o[f],v=o[m],y=v.x-b.x,$=v.y-b.y,w=y*y+$*$+.01,_=2800/w,k=Math.sqrt(w);b.fx-=_*y/k,b.fy-=_*$/k,v.fx+=_*y/k,v.fy+=_*$/k}s.forEach(f=>{const m=l[f.from],b=l[f.to];if(!m||!b)return;const v=b.x-m.x,y=b.y-m.y,$=Math.sqrt(v*v+y*y)+.01,w=($-120)*.06;m.fx+=w*v/$,m.fy+=w*y/$,b.fx-=w*v/$,b.fy-=w*y/$}),o.forEach(f=>{const m=n[f.type]||{x:a/2,y:i/2};f.vx=(f.vx+f.fx)*.8-(f.x-m.x)*.02,f.vy=(f.vy+f.fy)*.8-(f.y-m.y)*.02,f.x=Math.max(60,Math.min(a-60,f.x+f.vx)),f.y=Math.max(40,Math.min(i-40,f.y+f.vy))})}const c=Math.max(1,...s.map(u=>Number(u.amount||0))),d=s.map(u=>{const f=l[u.from],m=l[u.to];if(!f||!m)return"";const b=1+4*(Number(u.amount||0)/c);return`<line x1="${f.x}" y1="${f.y}" x2="${m.x}" y2="${m.y}" stroke="#94a3b8" stroke-width="${b}" opacity=".55"/>
                <text x="${(f.x+m.x)/2}" y="${(f.y+m.y)/2-6}" font-size="10" fill="#64748b" text-anchor="middle">${Number(u.amount||0).toLocaleString("fa-IR")}</text>`}).join(""),h=o.map(u=>{const f=u.type==="order"?22:u.type==="activity"?18:16,m=r[u.type]||"#64748b",b=(u.label||"").slice(0,22);return`<g>
                <circle cx="${u.x}" cy="${u.y}" r="${f}" fill="${m}" opacity=".92"/>
                <text x="${u.x}" y="${u.y+f+14}" font-size="11" fill="#1e293b" text-anchor="middle">${this.escape(b)}</text>
            </g>`}).join("");e.innerHTML=`<rect width="${a}" height="${i}" fill="#f8fafc"/>${d}${h}`}async _renderPreview(e){var t;e.innerHTML=`
        <div class="svc-acc-preview">
            <div class="acc-form-row">
                <label class="acc-form-group"><span>شناسه SRD</span>
                    <input type="number" data-ref="reportIdInp" min="1"></label>
                <button class="acc-btn acc-btn--primary" data-ref="previewBtn">محاسبه</button>
            </div>
            <div data-ref="previewOut"></div>
        </div>`,(t=e.querySelector('[data-ref="previewBtn"]'))==null||t.addEventListener("click",async()=>{var n;const s=(n=e.querySelector('[data-ref="reportIdInp"]'))==null?void 0:n.value;if(!s)return;const a=e.querySelector('[data-ref="previewOut"]');a.innerHTML='<div class="acc-loading">⏳</div>';const i=await this.api.get(`service/accounting/preview/${s}`);a.innerHTML=this._splitsHtml((i==null?void 0:i.data)??{})})}_splitsHtml(e){var i;const t=e.amounts||{},s=e.costs||{},a=((i=e.activity_cost)==null?void 0:i.person_shares)||[];return`<div class="svc-acc-split-box">
            <div class="svc-acc-grid">${[["جمع",t.total],["کارشناس",s.tech_fee],["ارشد",s.senior_fee],["COGS",s.parts_cogs],["سربار",s.overhead_total]].map(([n,r])=>`<div><span>${n}</span><b>${Number(r||0).toLocaleString("fa-IR")}</b></div>`).join("")}</div>
            ${a.length?`<h4 style="margin:14px 0 8px;">سهم نفرها از فعالیت‌ها</h4>
            <ul style="margin:0;padding-right:18px;font-size:.9rem;">
                ${a.map(n=>`<li>${this.escape(n.name)} — ${Number(n.amount||0).toLocaleString("fa-IR")}</li>`).join("")}
            </ul>`:""}
        </div>`}_kpi(e,t,s){return`<div class="svc-acc-kpi" style="border-top-color:${s}">
            <span>${e}</span><b>${Number(t||0).toLocaleString("fa-IR")}</b></div>`}_toast(e){const t=document.createElement("div");t.textContent=e,t.style.cssText="position:fixed;bottom:20px;left:50%;transform:translateX(-50%);background:#166534;color:#fff;padding:10px 20px;border-radius:8px;z-index:9999;",document.body.appendChild(t),setTimeout(()=>t.remove(),3e3)}}const tl=[{key:"dashboard",icon:"📊",title:"داشبورد",desc:"آمار کلی",roles:["admin","senior"]},{key:"accounting",icon:"💰",title:"صدور سند",desc:"حسابدار — صف سند",roles:["admin","accountant"]},{key:"senior",icon:"👨‍💼",title:"کارشناس ارشد",desc:"مدیریت تیم",roles:["admin","senior"]},{key:"technician",icon:"🔧",title:"صف کار من",desc:"کارشناس میدانی",roles:["admin","technician"]},{key:"dispatch",icon:"🚐",title:"Dispatch",desc:"تخصیص کارشناس",roles:["admin","senior"]},{key:"requests",icon:"📋",title:"درخواست‌ها",desc:"صف درخواست",roles:["admin","senior"]},{key:"reports",icon:"📄",title:"گزارش فنی",desc:"SRD + فاکتور",roles:["admin","senior","technician","accountant"]},{key:"pm",icon:"📅",title:"PM",desc:"سرویس دوره‌ای",roles:["admin","senior"]},{key:"parts",icon:"📦",title:"قطعات",desc:"سفارش تأمین",roles:["admin","senior"]},{key:"equipment",icon:"🏭",title:"تجهیزات",desc:"استعلام خرید",roles:["admin","senior"]},{key:"devices",icon:"❄️",title:"دستگاه‌ها",desc:"پرونده تجهیز",roles:["admin","senior"]}],sl={dashboard:Wo,accounting:el,senior:Zo,technician:Xo,dispatch:Vo,requests:Do,reports:No,pm:Go,parts:Jo,equipment:Qo,devices:Po};class va extends C{constructor(t={}){super(t);g(this,"useContextBadge",!0);this.api=t.api,this._active=null,this._sections={},this._role="admin",this._sectionDefs=[]}_resolveRole(t){return t!=null&&t.is_admin?"admin":t!=null&&t.is_accountant?"accountant":t!=null&&t.is_senior?"senior":t!=null&&t.is_technician?"technician":(t==null?void 0:t.role)||"admin"}_buildSections(t){return tl.filter(s=>s.roles.includes(t)).map(s=>({...s,Class:sl[s.key]}))}async template(){const t=this._sectionDefs.map(a=>`

            <div class="sp-nav-card ${a.key===this._active?"sp-nav-card--active":""}"

                 data-section="${a.key}" role="button" tabindex="0">

                <span class="sp-nav-card__icon">${a.icon}</span>

                <div class="sp-nav-card__title">${a.title}</div>

                <div class="sp-nav-card__desc">${a.desc}</div>

            </div>

        `).join(""),s=this._sectionDefs.map(a=>`

            <div class="acc-section ${a.key===this._active?"acc-section--active":""}"

                 data-panel="${a.key}" data-ref="panel-${a.key}"></div>

        `).join("");return`

            <div class="sp-section-nav" data-ref="navBar">${t}</div>

            <div>${s}</div>

        `}async beforeRender(){var t,s,a;try{const i=await this.api.get("service/me/role");this._role=this._resolveRole(i==null?void 0:i.data)}catch{this._role="admin"}this._sectionDefs=this._buildSections(this._role),this._active=this._role==="accountant"?((t=this._sectionDefs.find(i=>i.key==="accounting"))==null?void 0:t.key)||((s=this._sectionDefs[0])==null?void 0:s.key):((a=this._sectionDefs[0])==null?void 0:a.key)||"dashboard"}async afterRender(){var t,s;this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(a=>{this.on(a,"click",()=>this._switch(a.dataset.section))}),(s=(t=this.eventBus)==null?void 0:t.on)==null||s.call(t,"service:open-report",async({id:a})=>{var i,n;await this._switch("reports"),this._sections.reports||await this._mount("reports"),await((n=(i=this._sections.reports)==null?void 0:i._openWizard)==null?void 0:n.call(i,a))}),await this._mount(this._active)}async _switch(t){t!==this._active&&(this.ref("navBar").querySelectorAll(".sp-nav-card").forEach(s=>s.classList.toggle("sp-nav-card--active",s.dataset.section===t)),this.container.querySelectorAll(".acc-section").forEach(s=>s.classList.toggle("acc-section--active",s.dataset.panel===t)),this._active=t,await this._mount(t))}async _mount(t){if(this._sections[t])return;const s=this._sectionDefs.find(n=>n.key===t),a=this.ref(`panel-${t}`);if(!s||!a)return;const i=new s.Class({eventBus:this.eventBus,store:this.store,tab:this.tab,api:this.api});await i.render(a),this._sections[t]=i}destroy(){Object.values(this._sections).forEach(t=>{var s;return(s=t==null?void 0:t.destroy)==null?void 0:s.call(t)}),super.destroy()}}g(va,"title","خدمات میدانی"),E.register("service",va);const ba="acc_re_v3",At=[{key:"prospect",label:"بالقوه",color:"#94a3b8"},{key:"active",label:"فعال",color:"#22c55e"},{key:"completed",label:"تکمیل",color:"#6366f1"},{key:"suspended",label:"متوقف",color:"#f59e0b"},{key:"cancelled",label:"لغو",color:"#ef4444"}],U=[{key:"cnt_building",label:"ساختمان",icon:"dashicons-building",color:"#6366f1",bg:"#eef2ff"},{key:"cnt_apartment",label:"آپارتمان",icon:"dashicons-admin-home",color:"#0ea5e9",bg:"#e0f2fe"},{key:"cnt_shop",label:"مغازه",icon:"dashicons-cart",color:"#f59e0b",bg:"#fef3c7"},{key:"cnt_land_only",label:"زمین",icon:"dashicons-admin-site",color:"#10b981",bg:"#d1fae5"}];class ga extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._data=[],this._summary={},this._landUses=[],this._sortCol="total_blocks",this._sortDir="desc",this._search="",this._filters=this._loadFilters(),this._showFilter=!1,this._level="district",this._path=[],this._started=!1,this._layers=[]}async template(){return`<div class="red-wrap" dir="rtl">

            <!-- ── هدر با KPI ── -->
            <div class="red-hero">
                <div class="red-hero-title">
                    <span class="red-hero-icon">🏘️</span>
                    <div>
                        <div class="red-hero-name">داشبورد تحلیل املاک</div>
                        <div class="red-hero-sub">آمار به تفکیک محله و ناحیه</div>
                    </div>
                </div>
                <div class="red-kpis">
                    <div class="red-kpi">
                        <div class="red-kpi-val" data-ref="kTotal">—</div>
                        <div class="red-kpi-lbl">کل ملک</div>
                    </div>
                    <div class="red-kpi red-kpi--bldg">
                        <div class="red-kpi-val" data-ref="kBldg">—</div>
                        <div class="red-kpi-lbl">ساختمان</div>
                    </div>
                    <div class="red-kpi red-kpi--apt">
                        <div class="red-kpi-val" data-ref="kApt">—</div>
                        <div class="red-kpi-lbl">آپارتمان</div>
                    </div>
                    <div class="red-kpi red-kpi--shop">
                        <div class="red-kpi-val" data-ref="kShop">—</div>
                        <div class="red-kpi-lbl">مغازه</div>
                    </div>
                    <div class="red-kpi red-kpi--land">
                        <div class="red-kpi-val" data-ref="kLand">—</div>
                        <div class="red-kpi-lbl">زمین</div>
                    </div>
                    <div class="red-kpi red-kpi--area">
                        <div class="red-kpi-val" data-ref="kArea">—</div>
                        <div class="red-kpi-lbl">متوسط م²</div>
                    </div>
                </div>
            </div>

            <!-- ── نوار کنترل ── -->
            <div class="red-toolbar">
                <div class="red-search-wrap">
                    <span class="red-search-icon">🔍</span>
                    <input class="red-search" data-ref="searchInput" placeholder="جستجوی محله یا ناحیه...">
                </div>
                <div class="red-toolbar-right">
                    <select class="red-sel" data-ref="sortSel">
                        <option value="total_parcels">تعداد کل</option>
                        <option value="cnt_building">ساختمان</option>
                        <option value="cnt_apartment">آپارتمان</option>
                        <option value="cnt_shop">مغازه</option>
                        <option value="cnt_land_only">زمین</option>
                        <option value="avg_area">متوسط مساحت</option>
                    </select>
                    <button class="red-btn red-btn--icon" data-ref="sortDirBtn" title="تغییر جهت">↓</button>
                    <button class="red-btn red-btn--filter" data-ref="filterBtn">
                        ⚙️ فیلتر
                        <span class="red-filter-dot" data-ref="filterDot" style="display:none"></span>
                    </button>
                    <span class="red-count" data-ref="rowCount"></span>
                </div>
            </div>

            <!-- ── نوار مسیر (breadcrumb) ── -->
            <div class="red-crumbs" data-ref="crumbs" style="display:none;align-items:center;gap:6px;flex-wrap:wrap;padding:6px 12px;font-size:13px;"></div>

            <!-- ── بدنه اصلی ── -->
            <div class="red-body">

                <!-- پنل فیلتر (اسلاید) -->
                <aside class="red-filter-panel" data-ref="filterPanel">
                    <div class="red-fp-header">
                        <span>⚙️ فیلترها</span>
                        <button class="red-fp-close" data-ref="filterClose">✕</button>
                    </div>

                    <div class="red-fp-section">
                        <div class="red-fp-title">✏️ تعریف «نو ملک»</div>
                        <div class="red-fp-hint">عدد = حداقل تعداد لازم (۰ = بدون فیلتر)</div>
                        <div class="red-def-row">
                            <div class="red-def-box">
                                <div class="red-def-lbl" style="color:#6366f1">🏗️ ساختمان</div>
                                <input type="number" class="red-num-input" data-ref="defBuilding"
                                       value="${this._filters.def_building??0}" min="0">
                            </div>
                            <div class="red-def-box">
                                <div class="red-def-lbl" style="color:#0ea5e9">🏢 آپارتمان</div>
                                <input type="number" class="red-num-input" data-ref="defUnits"
                                       value="${this._filters.def_units??0}" min="0">
                            </div>
                            <div class="red-def-box">
                                <div class="red-def-lbl" style="color:#f59e0b">🏪 مغازه</div>
                                <input type="number" class="red-num-input" data-ref="defShops"
                                       value="${this._filters.def_shops??0}" min="0">
                            </div>
                        </div>
                        <div class="red-def-preview" data-ref="defPreview">همه ملک‌ها</div>
                    </div>

                    <div class="red-fp-section">
                        <div class="red-fp-title">وضعیت</div>
                        <div class="red-checks" data-ref="statusChecks">
                            ${At.map(t=>`
                            <label class="red-check-item">
                                <input type="checkbox" value="${t.key}"
                                    ${(this._filters.statuses||[]).includes(t.key)?"checked":""}>
                                <span class="red-check-dot" style="background:${t.color}"></span>
                                ${t.label}
                            </label>`).join("")}
                        </div>
                    </div>

                    <div class="red-fp-section">
                        <div class="red-fp-title">لایه (LayerID)</div>
                        <select class="red-fp-sel" data-ref="layerSel">
                            <option value="">همه لایه‌ها</option>
                        </select>
                    </div>

                    <div class="red-fp-section">
                        <div class="red-fp-title">کاربری</div>
                        <select class="red-fp-sel" data-ref="landUseSel">
                            <option value="">همه</option>
                        </select>
                    </div>

                    <div class="red-fp-section">
                        <div class="red-fp-title">بازه مساحت زمین (م²)</div>
                        <div class="red-range-row">
                            <input type="number" class="red-fp-inp" data-ref="areaMin"
                                   value="${this._filters.area_min??""}" placeholder="از">
                            <span class="red-range-sep">—</span>
                            <input type="number" class="red-fp-inp" data-ref="areaMax"
                                   value="${this._filters.area_max??""}" placeholder="تا">
                        </div>
                    </div>

                    <div class="red-fp-footer">
                        <button class="red-btn red-btn--primary" data-ref="applyBtn">↻ اعمال</button>
                        <button class="red-btn red-btn--ghost"   data-ref="resetBtn">پاک کردن</button>
                    </div>
                </aside>

                <!-- گرید کارت‌ها -->
                <main class="red-main" data-ref="cardsWrap">
                    <div class="red-empty" style="text-align:center;padding:60px 20px;color:#64748b;">
                        <div style="font-size:40px;margin-bottom:12px;">🗺️</div>
                        <div style="font-size:15px;font-weight:700;margin-bottom:6px;">برای شروع، شرایط را تعریف کنید</div>
                        <div style="font-size:13px;">فیلترها را تنظیم و دکمه «اعمال» را بزنید تا گزارش مناطق نمایش داده شود.</div>
                    </div>
                </main>
            </div>

            <!-- ── overlay جزئیات ── -->
            <div class="red-detail-overlay" data-ref="detailOverlay" style="display:none">
                <div class="red-detail-modal" data-ref="detailModal"></div>
            </div>
        </div>`}async afterRender(){this._updateDefPreview(),await this._loadLandUses(),await this._loadLayers(),this._bindEvents()}async _loadLayers(){try{const t=await this.api.get("gis/layers-list"),s=this.ref("layerSel");if(this._layers=(t==null?void 0:t.data)??[],!s)return;this._layers.forEach(a=>{const i=document.createElement("option");i.value=a.layer_id,i.textContent=`${a.layer_id} (${(+a.parcel_count||0).toLocaleString("fa-IR")})`,this._filters.layer_id===a.layer_id&&(i.selected=!0),s.appendChild(i)})}catch{}}async _loadLandUses(){try{const t=await this.api.get("gis/dashboard/land-uses"),s=this.ref("landUseSel");if(!s)return;((t==null?void 0:t.data)??[]).forEach(a=>{const i=document.createElement("option");i.value=a.value,i.textContent=`${a.value} (${a.count})`,this._filters.land_use===a.value&&(i.selected=!0),s.appendChild(i)})}catch{}}async _load(){if(!this._started){this._renderEmpty();return}const t=this.ref("cardsWrap");t&&(t.innerHTML='<div class="red-loading">⏳ در حال بارگذاری...</div>');try{const s=await this.api.get("gis/drilldown",this._buildParams());this._data=(s==null?void 0:s.data)??[],this._level=(s==null?void 0:s.level)??this._level,this._renderCrumbs(),this._updateKPIs(),this._renderCards()}catch(s){t&&(t.innerHTML=`<div class="red-error">❌ ${this.esc(s.message)}</div>`)}}_buildParams(){var l;const t=this._filters,s={level:this._level},a=this._path.find(c=>c.level==="district"),i=this._path.find(c=>c.level==="neighborhood");a&&(s.district=a.key_id),i&&(s.neighborhood=i.key_id);const n=+t.def_building||0,r=+t.def_units||0,o=+t.def_shops||0;return t._def_applied&&(n>0||r>0||o>0)&&(s.def_building=n,s.def_units=r,s.def_shops=o),(l=t.statuses)!=null&&l.length&&(s.statuses=t.statuses.join(",")),t.land_use&&(s.land_use=t.land_use),t.area_min&&(s.area_min=t.area_min),t.area_max&&(s.area_max=t.area_max),t.layer_id&&(s.layer_id=t.layer_id),s}_renderEmpty(){const t=this.ref("cardsWrap");t&&(t.innerHTML=`
            <div class="red-empty" style="text-align:center;padding:60px 20px;color:#64748b;">
                <div style="font-size:40px;margin-bottom:12px;">🗺️</div>
                <div style="font-size:15px;font-weight:700;margin-bottom:6px;">برای شروع، شرایط را تعریف کنید</div>
                <div style="font-size:13px;">فیلترها را تنظیم و دکمه «اعمال» را بزنید تا گزارش مناطق نمایش داده شود.</div>
            </div>`);const s=this.ref("crumbs");s&&(s.style.display="none")}_drillInto(t){if(this._level==="district")this._path=[{level:"district",key_id:t.key_id,label:t.label||"منطقه "+t.key_id}],this._level="neighborhood";else if(this._level==="neighborhood")this._path.push({level:"neighborhood",key_id:t.key_id,label:t.label||"—"}),this._level="block";else{this._openBlockOnMap(t);return}this._load()}_goToCrumb(t){if(t<0)this._path=[],this._level="district";else{this._path=this._path.slice(0,t+1);const s=this._path[this._path.length-1];this._level=s.level==="district"?"neighborhood":"block"}this._load()}_renderCrumbs(){const t=this.ref("crumbs");if(!t)return;t.style.display="flex";const s='<span style="color:#cbd5e1;">‹</span>',a=(r,o,l)=>l?`<span style="font-weight:800;color:#1e293b;">${this.esc(r)}</span>`:`<a data-crumb="${o}" style="color:#3b82f6;cursor:pointer;text-decoration:none;">${this.esc(r)}</a>`,i=[a("🗺️ مناطق",-1,this._level==="district")];this._path.forEach((r,o)=>{o===this._path.length-1&&this._level==="block"||this._path.length-1,i.push(s,a(r.label,o,!1))});const n=this._level==="district"?"":this._level==="neighborhood"?" — محلات":" — بلوک‌ها";t.innerHTML=i.join(" ")+`<span style="margin-right:6px;color:#94a3b8;font-size:12px;">${n}</span>`,t.querySelectorAll("[data-crumb]").forEach(r=>r.addEventListener("click",()=>this._goToCrumb(parseInt(r.dataset.crumb))))}_openBlockOnMap(t){var i;const s=this._filters,a={block:t.key_id,filters:{land_use:s.land_use||"",area_min:s.area_min||null,area_max:s.area_max||null,statuses:s.statuses||[],def_building:+s.def_building>0?+s.def_building:-1,def_units:+s.def_units>0?+s.def_units:-1,def_shops:+s.def_shops>0?+s.def_shops:-1,layer_id:s.layer_id||""}};try{sessionStorage.setItem("acc_gis_focus_block",JSON.stringify(a))}catch{}(i=this.eventBus)==null||i.emit("tab:open",{key:"gis",params:{focusBlock:t.key_id}})}_updateKPIs(){const t=this._data||[],s=i=>t.reduce((n,r)=>n+(+r[i]||0),0),a=i=>(+i||0).toLocaleString("fa-IR");this._setRef("kTotal",a(s("total_parcels"))),this._setRef("kBldg",a(s("cnt_building"))),this._setRef("kApt",a(s("cnt_apartment"))),this._setRef("kShop",a(s("cnt_shop"))),this._setRef("kLand",a(s("cnt_land_only"))),this._setRef("kArea",this._level==="block"?a(t.length):a(s("total_blocks")))}_renderCards(){const t=this.ref("cardsWrap");if(!t)return;const s=this._search.toLowerCase();let a=this._data.filter(o=>!s||String(o.label??"").toLowerCase().includes(s));const i="total_parcels";a.sort((o,l)=>{const c=parseFloat(o[i]??0),d=parseFloat(l[i]??0);return this._sortDir==="desc"?d-c:c-d});const n=this._level==="district"?"منطقه":this._level==="neighborhood"?"محله":"بلوک",r=this.ref("rowCount");if(r&&(r.textContent=`${a.length.toLocaleString("fa-IR")} ${n}`),!a.length){t.innerHTML='<div class="red-empty">📭 داده‌ای با این شرایط یافت نشد</div>';return}t.innerHTML=`<div class="red-grid">${a.map((o,l)=>this._cardHtml(o,l)).join("")}</div>`,t.querySelectorAll(".red-card").forEach(o=>{o.addEventListener("click",()=>{const l=a[parseInt(o.dataset.idx)];l&&this._drillInto(l)})})}_cardHtml(t,s){const a=$=>(+$||0).toLocaleString("fa-IR"),i=this._level==="block",n=+t.total_parcels||0,r="ملک",o=+t.cnt_building||0,l=+t.cnt_apartment||0,c=+t.cnt_shop||0,d=+t.cnt_land_only||0;let h="#10b981",u="زمین غالب";o>=l&&o>=c&&o>=d?(h="#6366f1",u="ساختمان غالب"):l>=c&&l>=d?(h="#0ea5e9",u="آپارتمان غالب"):c>=d&&(h="#f59e0b",u="مغازه غالب");const f=+t.total_parcels||1,m=Math.round(o/f*100);let b,v;if(this._level==="district")b=t.label||`منطقه ${t.key_id}`,v=`منطقه ${t.key_id}`;else if(this._level==="neighborhood"){const $=this._path.find(w=>w.level==="district");b=t.label||"—",v=$?$.label:"محله"}else b=`بلوک ${t.label}`,v="🗺️ نقشه";const y=i?'<span class="red-accent-tag" style="background:#3b82f620;color:#3b82f6">🗺️ نمایش روی نقشه</span>':`<span class="red-accent-tag" style="background:${h}20;color:${h}">${u}</span>
               <span class="red-avg">${a(+t.total_blocks||0)} بلوک · کلیک برای ${this._level==="district"?"محلات":"بلوک‌ها"}</span>`;return`
        <div class="red-card" data-idx="${s}" style="border-top:3px solid ${h};cursor:pointer">
            <div class="red-card-head">
                <div class="red-card-name">
                    <span class="red-card-title">${this.esc(b)}</span>
                    <span class="red-card-dist">${this.esc(v)}</span>
                </div>
                <div class="red-card-total">
                    <span class="red-total-n">${a(n)}</span>
                    <span class="red-total-u">${r}</span>
                </div>
            </div>

            <div class="red-stats">
                <div class="red-stat" style="--sc:${U[0].color};--sb:${U[0].bg}">
                    <span class="red-stat-n">${a(o)}</span><span class="red-stat-l">ساختمان</span>
                </div>
                <div class="red-stat" style="--sc:${U[1].color};--sb:${U[1].bg}">
                    <span class="red-stat-n">${a(l)}</span><span class="red-stat-l">آپارتمان</span>
                </div>
                <div class="red-stat" style="--sc:${U[2].color};--sb:${U[2].bg}">
                    <span class="red-stat-n">${a(c)}</span><span class="red-stat-l">مغازه</span>
                </div>
                <div class="red-stat" style="--sc:${U[3].color};--sb:${U[3].bg}">
                    <span class="red-stat-n">${a(d)}</span><span class="red-stat-l">زمین</span>
                </div>
            </div>

            <div class="red-bbar-wrap">
                <div class="red-bbar">
                    <div class="red-bbar-fill" style="width:${m}%;background:${h}"></div>
                </div>
                <span class="red-bbar-pct" style="color:${h}">${m}٪</span>
            </div>

            <div class="red-card-foot">${y}</div>
        </div>`}_showDetail(t){var o;const s=this.ref("detailOverlay"),a=this.ref("detailModal");if(!s||!a)return;const i=l=>(+l||0).toLocaleString("fa-IR"),n=+t.total_parcels||1,r=At.map(l=>{const c=+(t[`status_${l.key}`]??0);if(!c)return"";const d=Math.round(c/n*100);return`<div class="red-dm-row">
                <span style="display:flex;align-items:center;gap:6px">
                    <span style="width:10px;height:10px;border-radius:50%;background:${l.color};display:inline-block"></span>
                    ${l.label}
                </span>
                <span><b>${i(c)}</b> <small>(${d}٪)</small></span>
            </div>`}).join("");a.innerHTML=`
        <div class="red-dm-hdr">
            <div>
                <h3 class="red-dm-title">${this.esc(t.neighborhood_name||"—")}</h3>
                <span class="red-dm-sub">${this.esc(t.district_name||"")}</span>
            </div>
            <button class="red-dm-close" data-ref="detailClose">✕</button>
        </div>
        <div class="red-dm-body">
            <div class="red-dm-bigstats">
                <div class="red-dm-bs">
                    <div class="red-dm-bsv">${i(t.total_parcels)}</div>
                    <div class="red-dm-bsl">کل ملک</div>
                </div>
                <div class="red-dm-bs" style="border-color:#6366f1;background:#eef2ff">
                    <div class="red-dm-bsv" style="color:#6366f1">${i(t.cnt_building)}</div>
                    <div class="red-dm-bsl">🏗️ ساختمان</div>
                </div>
                <div class="red-dm-bs" style="border-color:#0ea5e9;background:#e0f2fe">
                    <div class="red-dm-bsv" style="color:#0ea5e9">${i(t.cnt_apartment)}</div>
                    <div class="red-dm-bsl">🏢 آپارتمان</div>
                </div>
                <div class="red-dm-bs" style="border-color:#f59e0b;background:#fef3c7">
                    <div class="red-dm-bsv" style="color:#f59e0b">${i(t.cnt_shop)}</div>
                    <div class="red-dm-bsl">🏪 مغازه</div>
                </div>
                <div class="red-dm-bs" style="border-color:#10b981;background:#d1fae5">
                    <div class="red-dm-bsv" style="color:#10b981">${i(t.cnt_land_only)}</div>
                    <div class="red-dm-bsl">🌿 زمین</div>
                </div>
            </div>

            <div class="red-dm-section">مساحت</div>
            <div class="red-dm-row">
                <span>متوسط زمین</span>
                <b>${t.avg_area?Math.round(+t.avg_area).toLocaleString("fa-IR"):"—"} م²</b>
            </div>
            <div class="red-dm-row">
                <span>مساحت کل</span>
                <b>${t.total_area?Math.round(+t.total_area/1e4).toLocaleString("fa-IR"):"—"} هکتار</b>
            </div>

            <div class="red-dm-section">توزیع وضعیت</div>
            ${r}
            <div class="red-sbar" style="height:10px;border-radius:5px;margin-top:10px">
                ${At.map(l=>{const c=+(t[`status_${l.key}`]??0),d=Math.round(c/n*100);return d?`<div style="width:${d}%;background:${l.color};height:100%" title="${l.label}"></div>`:""}).join("")}
            </div>
        </div>`,s.style.display="flex",(o=a.querySelector('[data-ref="detailClose"]'))==null||o.addEventListener("click",()=>{s.style.display="none"})}_updateDefPreview(){var n,r,o;const t=parseInt((n=this.ref("defBuilding"))==null?void 0:n.value)||0,s=parseInt((r=this.ref("defUnits"))==null?void 0:r.value)||0,a=parseInt((o=this.ref("defShops"))==null?void 0:o.value)||0,i=this.ref("defPreview");if(i)if(t===0&&s===0&&a===0)i.textContent="🌿 همه ملک‌ها",i.style.color="#10b981";else{const l=[];t&&l.push(`${t}+ ساختمان`),s&&l.push(`${s}+ آپارتمان`),a&&l.push(`${a}+ مغازه`),i.textContent="🔍 "+l.join(" | "),i.style.color="#6366f1"}}_bindEvents(){var t,s,a,i,n,r,o,l;(t=this.ref("searchInput"))==null||t.addEventListener("input",c=>{this._search=c.target.value,this._renderCards()}),(s=this.ref("sortSel"))==null||s.addEventListener("change",c=>{this._sortCol=c.target.value,this._renderCards()}),(a=this.ref("sortDirBtn"))==null||a.addEventListener("click",()=>{this._sortDir=this._sortDir==="desc"?"asc":"desc",this.ref("sortDirBtn").textContent=this._sortDir==="desc"?"↓":"↑",this._renderCards()}),(i=this.ref("filterBtn"))==null||i.addEventListener("click",()=>this._toggleFilter(!0)),(n=this.ref("filterClose"))==null||n.addEventListener("click",()=>this._toggleFilter(!1)),(r=this.ref("applyBtn"))==null||r.addEventListener("click",()=>this._applyFilters()),(o=this.ref("resetBtn"))==null||o.addEventListener("click",()=>this._resetFilters()),["defBuilding","defUnits","defShops"].forEach(c=>{var d;return(d=this.ref(c))==null?void 0:d.addEventListener("input",()=>this._updateDefPreview())}),(l=this.ref("detailOverlay"))==null||l.addEventListener("click",c=>{c.target===this.ref("detailOverlay")&&(this.ref("detailOverlay").style.display="none")})}_toggleFilter(t){const s=this.ref("filterPanel");s&&s.classList.toggle("red-filter-panel--open",t)}_applyFilters(){var a,i,n,r,o,l,c,d;const t=[...((a=this.ref("statusChecks"))==null?void 0:a.querySelectorAll("input:checked"))??[]].map(h=>h.value);this._filters={def_building:parseInt((i=this.ref("defBuilding"))==null?void 0:i.value)||0,def_units:parseInt((n=this.ref("defUnits"))==null?void 0:n.value)||0,def_shops:parseInt((r=this.ref("defShops"))==null?void 0:r.value)||0,_def_applied:!0,statuses:t,land_use:((o=this.ref("landUseSel"))==null?void 0:o.value)||"",area_min:parseFloat((l=this.ref("areaMin"))==null?void 0:l.value)||null,area_max:parseFloat((c=this.ref("areaMax"))==null?void 0:c.value)||null},this._filters.layer_id=((d=this.ref("layerSel"))==null?void 0:d.value)||"";const s=this.ref("filterDot");s&&(s.style.display=this._hasActiveFilter()?"inline-block":"none"),this._saveFilters(),this._toggleFilter(!1),this._started=!0,this._path=[],this._level="district",this._load()}_resetFilters(){this._filters={def_building:0,def_units:0,def_shops:0,statuses:[],land_use:"",area_min:null,area_max:null,layer_id:""},this._saveFilters(),this.render(this.container)}_hasActiveFilter(){var s;const t=this._filters;return t._def_applied||((s=t.statuses)==null?void 0:s.length)||t.land_use||t.area_min||t.area_max||t.layer_id}_loadFilters(){try{return JSON.parse(localStorage.getItem(ba))||{}}catch{return{}}}_saveFilters(){try{localStorage.setItem(ba,JSON.stringify(this._filters))}catch{}}_setRef(t,s){const a=this.ref(t);a&&(a.textContent=s)}esc(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}destroy(){var t;(t=super.destroy)==null||t.call(this)}}g(ga,"title","🏘️ داشبورد املاک"),E.register("realestate",ga);const ya="acc_usedash_v1",_a=[{key:"prospect",label:"بالقوه",color:"#94a3b8"},{key:"under_review",label:"بررسی",color:"#f59e0b"},{key:"purchased",label:"خریداری",color:"#22c55e"},{key:"active",label:"فعال",color:"#10b981"},{key:"completed",label:"تکمیل",color:"#6366f1"}],G={bldg:{color:"#6366f1",bg:"#eef2ff"},apt:{color:"#0ea5e9",bg:"#e0f2fe"},shop:{color:"#f59e0b",bg:"#fef3c7"},land:{color:"#10b981",bg:"#d1fae5"}};class xa extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._data=[],this._uses=[],this._use="",this._search="",this._sortDir="desc",this._filters=this._loadFilters(),this._level="district",this._path=[],this._started=!1,this._layers=[],this._useTotal=null}async template(){return`<div class="red-wrap ud-wrap" dir="rtl">

            <!-- هدر + KPI -->
            <div class="red-hero">
                <div class="red-hero-title">
                    <span class="red-hero-icon">🧭</span>
                    <div>
                        <div class="red-hero-name">داشبورد کاربری</div>
                        <div class="red-hero-sub">تحلیل به تفکیک نوع کاربری → منطقه، محله، بلوک، پارسل</div>
                    </div>
                </div>
                <div class="red-kpis">
                    <div class="red-kpi">
                        <div class="red-kpi-val" data-ref="kTotal">—</div>
                        <div class="red-kpi-lbl">کل ملک</div>
                    </div>
                    <div class="red-kpi red-kpi--bldg">
                        <div class="red-kpi-val" data-ref="kBldg">—</div>
                        <div class="red-kpi-lbl">ساختمان</div>
                    </div>
                    <div class="red-kpi red-kpi--apt">
                        <div class="red-kpi-val" data-ref="kApt">—</div>
                        <div class="red-kpi-lbl">آپارتمان</div>
                    </div>
                    <div class="red-kpi red-kpi--shop">
                        <div class="red-kpi-val" data-ref="kShop">—</div>
                        <div class="red-kpi-lbl">مغازه</div>
                    </div>
                    <div class="red-kpi red-kpi--land">
                        <div class="red-kpi-val" data-ref="kLand">—</div>
                        <div class="red-kpi-lbl">زمین</div>
                    </div>
                </div>
            </div>

            <!-- نوار انتخاب کاربری (گیت شروع) -->
            <div class="ud-usebar">
                <span class="ud-usebar-lbl">🏷️ کاربری:</span>
                <select class="red-sel ud-use-sel" data-ref="useSel">
                    <option value="">— یک کاربری انتخاب کنید —</option>
                </select>
                <button class="red-btn red-btn--primary" data-ref="goBtn">↻ نمایش</button>
                <span class="ud-use-chip" data-ref="useChip" style="display:none"></span>
            </div>

            <!-- نوار کنترل -->
            <div class="red-toolbar">
                <div class="red-search-wrap">
                    <span class="red-search-icon">🔍</span>
                    <input class="red-search" data-ref="searchInput" placeholder="جستجو...">
                </div>
                <div class="red-toolbar-right">
                    <button class="red-btn red-btn--icon" data-ref="sortDirBtn" title="تغییر جهت">↓</button>
                    <button class="red-btn red-btn--filter" data-ref="filterBtn">
                        ⚙️ فیلتر
                        <span class="red-filter-dot" data-ref="filterDot" style="display:none"></span>
                    </button>
                    <span class="red-count" data-ref="rowCount"></span>
                </div>
            </div>

            <!-- breadcrumb -->
            <div class="red-crumbs" data-ref="crumbs" style="display:none;align-items:center;gap:6px;flex-wrap:wrap;padding:6px 12px;font-size:13px;"></div>

            <div class="red-body">

                <!-- پنل فیلتر -->
                <aside class="red-filter-panel" data-ref="filterPanel">
                    <div class="red-fp-header">
                        <span>⚙️ فیلترها</span>
                        <button class="red-fp-close" data-ref="filterClose">✕</button>
                    </div>

                    <div class="red-fp-section">
                        <div class="red-fp-title">وضعیت</div>
                        <div class="red-checks" data-ref="statusChecks">
                            ${_a.map(t=>`
                            <label class="red-check-item">
                                <input type="checkbox" value="${t.key}"
                                    ${(this._filters.statuses||[]).includes(t.key)?"checked":""}>
                                <span class="red-check-dot" style="background:${t.color}"></span>
                                ${t.label}
                            </label>`).join("")}
                        </div>
                    </div>

                    <div class="red-fp-section">
                        <div class="red-fp-title">لایه (LayerID)</div>
                        <select class="red-fp-sel" data-ref="layerSel">
                            <option value="">همه لایه‌ها</option>
                        </select>
                    </div>

                    <div class="red-fp-section">
                        <div class="red-fp-title">بازه مساحت زمین (م²)</div>
                        <div class="red-range-row">
                            <input type="number" class="red-fp-inp" data-ref="areaMin"
                                   value="${this._filters.area_min??""}" placeholder="از">
                            <span class="red-range-sep">—</span>
                            <input type="number" class="red-fp-inp" data-ref="areaMax"
                                   value="${this._filters.area_max??""}" placeholder="تا">
                        </div>
                    </div>

                    <div class="red-fp-footer">
                        <button class="red-btn red-btn--primary" data-ref="applyBtn">↻ اعمال</button>
                        <button class="red-btn red-btn--ghost"   data-ref="resetBtn">پاک کردن</button>
                    </div>
                </aside>

                <!-- بدنه -->
                <main class="red-main" data-ref="cardsWrap">
                    <div class="red-empty" style="text-align:center;padding:60px 20px;color:#64748b;">
                        <div style="font-size:40px;margin-bottom:12px;">🏷️</div>
                        <div style="font-size:15px;font-weight:700;margin-bottom:6px;">برای شروع، یک کاربری انتخاب کنید</div>
                        <div style="font-size:13px;">از نوار بالا یک نوع کاربری برگزینید و «نمایش» را بزنید.</div>
                    </div>
                </main>
            </div>

            <!-- overlay جزئیات پارسل -->
            <div class="red-detail-overlay" data-ref="detailOverlay" style="display:none">
                <div class="red-detail-modal" data-ref="detailModal"></div>
            </div>
        </div>`}async afterRender(){await this._loadUses(),await this._loadLayers(),this._bindEvents()}async _loadUses(){try{const t=await this.api.get("gis/dashboard/land-uses");this._uses=(t==null?void 0:t.data)??[];const s=this.ref("useSel");if(!s)return;this._uses.forEach(a=>{const i=document.createElement("option");i.value=a.value,i.textContent=`${a.value} (${(+a.count||0).toLocaleString("fa-IR")})`,this._use===a.value&&(i.selected=!0),s.appendChild(i)})}catch{}}async _loadLayers(){try{const t=await this.api.get("gis/layers-list");this._layers=(t==null?void 0:t.data)??[];const s=this.ref("layerSel");if(!s)return;this._layers.forEach(a=>{const i=document.createElement("option");i.value=a.layer_id,i.textContent=`${a.layer_id} (${(+a.parcel_count||0).toLocaleString("fa-IR")})`,this._filters.layer_id===a.layer_id&&(i.selected=!0),s.appendChild(i)})}catch{}}async _load(){if(!this._started||!this._use){this._renderEmpty();return}const t=this.ref("cardsWrap");t&&(t.innerHTML='<div class="red-loading">⏳ در حال بارگذاری...</div>');try{if(this._level==="parcel"){const s=await this.api.get("gis/parcels",this._parcelParams());this._data=(s==null?void 0:s.data)??[]}else{const s=await this.api.get("gis/drilldown",this._drillParams());this._data=(s==null?void 0:s.data)??[],this._level=(s==null?void 0:s.level)??this._level}this._renderCrumbs(),this._updateKPIs(),this._render()}catch(s){t&&(t.innerHTML=`<div class="red-error">❌ ${this.esc(s.message)}</div>`)}}_drillParams(){var n;const t=this._filters,s={level:this._level,land_use:this._use},a=this._path.find(r=>r.level==="district"),i=this._path.find(r=>r.level==="neighborhood");return a&&(s.district=a.key_id),i&&(s.neighborhood=i.key_id),(n=t.statuses)!=null&&n.length&&(s.statuses=t.statuses.join(",")),t.area_min&&(s.area_min=t.area_min),t.area_max&&(s.area_max=t.area_max),t.layer_id&&(s.layer_id=t.layer_id),s}_parcelParams(){var i;const t=this._filters,s=this._path.find(n=>n.level==="block"),a={current_use:this._use,per_page:2e3};return s&&(a.block=s.key_id),((i=t.statuses)==null?void 0:i.length)===1&&(a.status=t.statuses[0]),t.area_min&&(a.area_min=t.area_min),t.area_max&&(a.area_max=t.area_max),t.layer_id&&(a.layer_id=t.layer_id),a}_renderEmpty(){const t=this.ref("cardsWrap");t&&(t.innerHTML=`
            <div class="red-empty" style="text-align:center;padding:60px 20px;color:#64748b;">
                <div style="font-size:40px;margin-bottom:12px;">🏷️</div>
                <div style="font-size:15px;font-weight:700;margin-bottom:6px;">برای شروع، یک کاربری انتخاب کنید</div>
                <div style="font-size:13px;">از نوار بالا یک نوع کاربری برگزینید و «نمایش» را بزنید.</div>
            </div>`);const s=this.ref("crumbs");s&&(s.style.display="none")}_drillInto(t){if(this._level==="district")this._path=[{level:"district",key_id:t.key_id,label:t.label||"منطقه "+t.key_id}],this._level="neighborhood";else if(this._level==="neighborhood")this._path.push({level:"neighborhood",key_id:t.key_id,label:t.label||"—"}),this._level="block";else if(this._level==="block")this._path.push({level:"block",key_id:t.key_id,label:t.label||"—"}),this._level="parcel";else return;this._load()}_goToCrumb(t){if(t<0)this._path=[],this._level="district";else{this._path=this._path.slice(0,t+1);const s=this._path[this._path.length-1];this._level=s.level==="district"?"neighborhood":s.level==="neighborhood"?"block":"parcel"}this._load()}_renderCrumbs(){const t=this.ref("crumbs");if(!t)return;t.style.display="flex";const s='<span style="color:#cbd5e1;">‹</span>',a=(r,o)=>`<a data-crumb="${o}" style="color:#3b82f6;cursor:pointer;text-decoration:none;">${this.esc(r)}</a>`,i=[`<span class="ud-crumb-use">🏷️ ${this.esc(this._use)}</span>`,s,a("🗺️ مناطق",-1)];this._path.forEach((r,o)=>i.push(s,a(r.label,o)));const n=this._level==="district"?"مناطق":this._level==="neighborhood"?"محلات":this._level==="block"?"بلوک‌ها":"پارسل‌ها";t.innerHTML=i.join(" ")+`<span style="margin-right:6px;color:#94a3b8;font-size:12px;">— ${n}</span>`,t.querySelectorAll("[data-crumb]").forEach(r=>r.addEventListener("click",()=>this._goToCrumb(parseInt(r.dataset.crumb))))}_updateKPIs(){const t=this._data||[],s=a=>(+a||0).toLocaleString("fa-IR");if(this._level==="parcel"){const a=i=>t.filter(i).length;this._setRef("kTotal",s(t.length)),this._setRef("kBldg",s(a(i=>+i.bld_count>0))),this._setRef("kApt",s(a(i=>+i.apt_count>0))),this._setRef("kShop",s(a(i=>+i.shop_count>0))),this._setRef("kLand",s(a(i=>!+i.bld_count&&!+i.apt_count&&!+i.shop_count)))}else{const a=i=>t.reduce((n,r)=>n+(+r[i]||0),0);this._setRef("kTotal",s(a("total_parcels"))),this._setRef("kBldg",s(a("cnt_building"))),this._setRef("kApt",s(a("cnt_apartment"))),this._setRef("kShop",s(a("cnt_shop"))),this._setRef("kLand",s(a("cnt_land_only"))),this._level==="district"&&(this._useTotal=a("total_parcels"),this._updateUseChip())}}_render(){this._level==="parcel"?this._renderParcels():this._renderCards()}_renderCards(){const t=this.ref("cardsWrap");if(!t)return;const s=this._search.toLowerCase();let a=this._data.filter(r=>!s||String(r.label??"").toLowerCase().includes(s));a.sort((r,o)=>{const l=parseFloat(r.total_parcels??0),c=parseFloat(o.total_parcels??0);return this._sortDir==="desc"?c-l:l-c});const i=this._level==="district"?"منطقه":this._level==="neighborhood"?"محله":"بلوک",n=this.ref("rowCount");if(n&&(n.textContent=`${a.length.toLocaleString("fa-IR")} ${i}`),!a.length){t.innerHTML='<div class="red-empty">📭 داده‌ای با این شرایط یافت نشد</div>';return}t.innerHTML=`<div class="red-grid">${a.map((r,o)=>this._cardHtml(r,o)).join("")}</div>`,t.querySelectorAll(".red-card").forEach(r=>{r.addEventListener("click",()=>{const o=a[parseInt(r.dataset.idx)];o&&this._drillInto(o)})})}_cardHtml(t,s){const a=$=>(+$||0).toLocaleString("fa-IR"),i=+t.total_parcels||0,n=+t.cnt_building||0,r=+t.cnt_apartment||0,o=+t.cnt_shop||0,l=+t.cnt_land_only||0;let c="#10b981",d="زمین غالب";n>=r&&n>=o&&n>=l?(c="#6366f1",d="ساختمان غالب"):r>=o&&r>=l?(c="#0ea5e9",d="آپارتمان غالب"):o>=l&&(c="#f59e0b",d="مغازه غالب");const h=+t.total_parcels||1,u=Math.round(n/h*100);let f,m;if(this._level==="district")f=t.label||`منطقه ${t.key_id}`,m=`منطقه ${t.key_id}`;else if(this._level==="neighborhood"){const $=this._path.find(w=>w.level==="district");f=t.label||"—",m=$?$.label:"محله"}else f=`بلوک ${t.label}`,m="🏘️ بلوک";const b=this._level==="district"?"محلات":this._level==="neighborhood"?"بلوک‌ها":"پارسل‌ها",v=this._level==="block"?`کلیک برای ${b}`:`${a(+t.total_blocks||0)} بلوک · کلیک برای ${b}`,y=`<span class="red-accent-tag" style="background:${c}20;color:${c}">${d}</span>
            <span class="red-avg">${v}</span>`;return`
        <div class="red-card" data-idx="${s}" style="border-top:3px solid ${c};cursor:pointer">
            <div class="red-card-head">
                <div class="red-card-name">
                    <span class="red-card-title">${this.esc(f)}</span>
                    <span class="red-card-dist">${this.esc(m)}</span>
                </div>
                <div class="red-card-total">
                    <span class="red-total-n">${a(i)}</span>
                    <span class="red-total-u">ملک</span>
                </div>
            </div>
            <div class="red-stats">
                <div class="red-stat" style="--sc:${G.bldg.color};--sb:${G.bldg.bg}">
                    <span class="red-stat-n">${a(n)}</span><span class="red-stat-l">ساختمان</span></div>
                <div class="red-stat" style="--sc:${G.apt.color};--sb:${G.apt.bg}">
                    <span class="red-stat-n">${a(r)}</span><span class="red-stat-l">آپارتمان</span></div>
                <div class="red-stat" style="--sc:${G.shop.color};--sb:${G.shop.bg}">
                    <span class="red-stat-n">${a(o)}</span><span class="red-stat-l">مغازه</span></div>
                <div class="red-stat" style="--sc:${G.land.color};--sb:${G.land.bg}">
                    <span class="red-stat-n">${a(l)}</span><span class="red-stat-l">زمین</span></div>
            </div>
            <div class="red-bbar-wrap">
                <div class="red-bbar"><div class="red-bbar-fill" style="width:${u}%;background:${c}"></div></div>
                <span class="red-bbar-pct" style="color:${c}">${u}٪</span>
            </div>
            <div class="red-card-foot">${y}</div>
        </div>`}_renderParcels(){const t=this.ref("cardsWrap");if(!t)return;const s=this._search.toLowerCase();let a=this._data.filter(l=>!s||String(l.code??"").toLowerCase().includes(s)||String(l.address??"").toLowerCase().includes(s));const i=this.ref("rowCount");if(i&&(i.textContent=`${a.length.toLocaleString("fa-IR")} پارسل`),!a.length){t.innerHTML='<div class="red-empty">📭 پارسلی با این شرایط یافت نشد</div>';return}const n=l=>(+l||0).toLocaleString("fa-IR"),r=l=>_a.find(c=>c.key===l),o=a.map((l,c)=>{const d=r(l.status),h=d?`<span class="ud-st" style="background:${d.color}20;color:${d.color}">${d.label}</span>`:`<span class="ud-st" style="background:#e2e8f0;color:#64748b">${this.esc(l.status||"—")}</span>`;return`<tr data-idx="${c}">
                <td class="ud-c-code">${this.esc(l.code||"—")}</td>
                <td>${this.esc(l.block_code||"—")}</td>
                <td class="ud-c-addr" title="${this.esc(l.address||"")}">${this.esc(l.address||"—")}</td>
                <td class="ud-c-num">${l.area_sqm?n(Math.round(+l.area_sqm)):"—"}</td>
                <td class="ud-c-num">${n(l.bld_count)}</td>
                <td class="ud-c-num">${n(l.apt_count)}</td>
                <td class="ud-c-num">${n(l.shop_count)}</td>
                <td>${this.esc(l.assigned_user_name||"—")}</td>
                <td>${h}</td>
            </tr>`}).join("");t.innerHTML=`
        <div class="ud-table-wrap">
            <table class="ud-table">
                <thead><tr>
                    <th>کد</th><th>بلوک</th><th>آدرس</th><th>مساحت م²</th>
                    <th>ساخت.</th><th>آپ.</th><th>مغازه</th><th>کاربر</th><th>وضعیت</th>
                </tr></thead>
                <tbody>${o}</tbody>
            </table>
        </div>`,t.querySelectorAll("tbody tr").forEach(l=>{l.addEventListener("click",()=>{const c=a[parseInt(l.dataset.idx)];c&&this._showParcel(c)})})}_showParcel(t){var r,o;const s=this.ref("detailOverlay"),a=this.ref("detailModal");if(!s||!a)return;const i=l=>(+l||0).toLocaleString("fa-IR"),n=(l,c)=>`<div class="red-dm-row"><span>${l}</span><b>${c}</b></div>`;a.innerHTML=`
        <div class="red-dm-hdr">
            <div>
                <h3 class="red-dm-title">${this.esc(t.code||"پارسل")}</h3>
                <span class="red-dm-sub">🏷️ ${this.esc(t.current_use||this._use)} · بلوک ${this.esc(t.block_code||"—")}</span>
            </div>
            <button class="red-dm-close" data-ref="detailClose">✕</button>
        </div>
        <div class="red-dm-body">
            <div class="red-dm-bigstats">
                <div class="red-dm-bs" style="border-color:#6366f1;background:#eef2ff">
                    <div class="red-dm-bsv" style="color:#6366f1">${i(t.bld_count)}</div>
                    <div class="red-dm-bsl">🏗️ ساختمان</div></div>
                <div class="red-dm-bs" style="border-color:#0ea5e9;background:#e0f2fe">
                    <div class="red-dm-bsv" style="color:#0ea5e9">${i(t.apt_count)}</div>
                    <div class="red-dm-bsl">🏢 آپارتمان</div></div>
                <div class="red-dm-bs" style="border-color:#f59e0b;background:#fef3c7">
                    <div class="red-dm-bsv" style="color:#f59e0b">${i(t.shop_count)}</div>
                    <div class="red-dm-bsl">🏪 مغازه</div></div>
            </div>
            <div class="red-dm-section">مشخصات</div>
            ${n("آدرس",this.esc(t.address||"—"))}
            ${n("مساحت زمین",t.area_sqm?i(Math.round(+t.area_sqm))+" م²":"—")}
            ${n("کاربری فعلی",this.esc(t.current_use||"—"))}
            ${n("وضعیت",this.esc(t.status||"—"))}
            ${n("مرحله",this.esc(t.pipeline_stage||"—"))}
            ${n("کاربر مسئول",this.esc(t.assigned_user_name||"—"))}
            ${n("منطقه / محله",this.esc((t.district_name||"—")+" / "+(t.neighborhood_name||"—")))}
            <div class="red-dm-section">موقعیت</div>
            ${n("مختصات",t.lat&&t.lng?`${(+t.lat).toFixed(5)}, ${(+t.lng).toFixed(5)}`:"—")}
            ${t.block_code?'<button class="red-btn red-btn--primary" data-ref="mapBtn" style="width:100%;margin-top:14px">🗺️ نمایش بلوک روی نقشه</button>':""}
        </div>`,s.style.display="flex",(r=a.querySelector('[data-ref="detailClose"]'))==null||r.addEventListener("click",()=>s.style.display="none"),(o=a.querySelector('[data-ref="mapBtn"]'))==null||o.addEventListener("click",()=>{var l;try{sessionStorage.setItem("acc_gis_focus_block",JSON.stringify({block:t.block_code,filters:{land_use:this._use}}))}catch{}(l=this.eventBus)==null||l.emit("tab:open",{key:"gis",params:{focusBlock:t.block_code}}),s.style.display="none"})}_bindEvents(){var t,s,a,i,n,r,o,l,c;(t=this.ref("useSel"))==null||t.addEventListener("change",d=>{this._use=d.target.value,this._useTotal=null,this._updateUseChip()}),(s=this.ref("goBtn"))==null||s.addEventListener("click",()=>this._start()),(a=this.ref("searchInput"))==null||a.addEventListener("input",d=>{this._search=d.target.value,this._render()}),(i=this.ref("sortDirBtn"))==null||i.addEventListener("click",()=>{this._sortDir=this._sortDir==="desc"?"asc":"desc",this.ref("sortDirBtn").textContent=this._sortDir==="desc"?"↓":"↑",this._render()}),(n=this.ref("filterBtn"))==null||n.addEventListener("click",()=>this._toggleFilter(!0)),(r=this.ref("filterClose"))==null||r.addEventListener("click",()=>this._toggleFilter(!1)),(o=this.ref("applyBtn"))==null||o.addEventListener("click",()=>this._applyFilters()),(l=this.ref("resetBtn"))==null||l.addEventListener("click",()=>this._resetFilters()),(c=this.ref("detailOverlay"))==null||c.addEventListener("click",d=>{d.target===this.ref("detailOverlay")&&(this.ref("detailOverlay").style.display="none")})}_updateUseChip(){const t=this.ref("useChip");if(t)if(this._use){const s=this._uses.find(i=>i.value===this._use),a=this._useTotal!=null?this._useTotal:s?+s.count||0:null;t.textContent=`🏷️ ${this._use}${a!=null?` · ${a.toLocaleString("fa-IR")} ملک`:""}`,t.style.display="inline-flex"}else t.style.display="none"}_start(){if(!this._use){const t=this.ref("useSel");t&&(t.style.borderColor="#ef4444",setTimeout(()=>t.style.borderColor="",1200));return}this._started=!0,this._path=[],this._level="district",this._saveFilters(),this._load()}_toggleFilter(t){const s=this.ref("filterPanel");s&&s.classList.toggle("red-filter-panel--open",t)}_applyFilters(){var a,i,n,r;const t=[...((a=this.ref("statusChecks"))==null?void 0:a.querySelectorAll("input:checked"))??[]].map(o=>o.value);this._filters={statuses:t,layer_id:((i=this.ref("layerSel"))==null?void 0:i.value)||"",area_min:parseFloat((n=this.ref("areaMin"))==null?void 0:n.value)||null,area_max:parseFloat((r=this.ref("areaMax"))==null?void 0:r.value)||null};const s=this.ref("filterDot");s&&(s.style.display=this._hasActiveFilter()?"inline-block":"none"),this._saveFilters(),this._toggleFilter(!1),this._started&&this._use&&(this._path=[],this._level="district",this._load())}_resetFilters(){this._filters={statuses:[],layer_id:"",area_min:null,area_max:null},this._saveFilters(),this.render(this.container)}_hasActiveFilter(){var s;const t=this._filters;return((s=t.statuses)==null?void 0:s.length)||t.layer_id||t.area_min||t.area_max}_loadFilters(){try{return JSON.parse(localStorage.getItem(ya))||{}}catch{return{}}}_saveFilters(){try{localStorage.setItem(ya,JSON.stringify({...this._filters,_use:this._use}))}catch{}}_setRef(t,s){const a=this.ref(t);a&&(a.textContent=s)}esc(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}destroy(){var t;(t=super.destroy)==null||t.call(this)}}g(xa,"title","🧭 داشبورد کاربری"),E.register("usedash",xa);const al={shop:{label:"🛍️ فروشگاه",color:"#6366f1"},realestate:{label:"🏘️ املاک",color:"#059669"},portal:{label:"📰 پورتال",color:"#d97706"},custom:{label:"⚙️ سفارشی",color:"#64748b"}},il={active:{label:"فعال",color:"#22c55e"},draft:{label:"پیش‌نویس",color:"#94a3b8"},archived:{label:"بایگانی",color:"#f87171"}};class wa extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);this.api=t.api,this._rows=[],this._pages=[],this._filter={type:"",status:""},this._editing=null}async template(){return`
        <div class="pm-wrap" dir="rtl">
            <!-- هدر -->
            <div class="pm-header">
                <div class="pm-header-right">
                    <h2 class="pm-title">📁 مدیریت پروژه‌ها</h2>
                    <p class="pm-subtitle">هر پروژه یک سفارش سایت است. فعال‌سازی = اعمال تنظیمات روی سایت</p>
                </div>
                <button class="pm-btn pm-btn--primary" data-ref="newBtn">+ پروژه جدید</button>
            </div>

            <!-- فیلترها -->
            <div class="pm-filters">
                <select class="pm-select" data-ref="typeFilter">
                    <option value="">همه انواع</option>
                    <option value="shop">🛍️ فروشگاه</option>
                    <option value="realestate">🏘️ املاک</option>
                    <option value="portal">📰 پورتال</option>
                    <option value="custom">⚙️ سفارشی</option>
                </select>
                <select class="pm-select" data-ref="statusFilter">
                    <option value="">همه وضعیت‌ها</option>
                    <option value="active">فعال</option>
                    <option value="draft">پیش‌نویس</option>
                    <option value="archived">بایگانی</option>
                </select>
                <span class="pm-count" data-ref="countLbl"></span>
            </div>

            <!-- جدول -->
            <div class="pm-table-wrap" data-ref="tableWrap">
                <div class="pm-loading">⏳ بارگذاری...</div>
            </div>

            <!-- modal فرم -->
            <div class="pm-modal-overlay" data-ref="modal" style="display:none">
                <div class="pm-modal" data-ref="modalBody"></div>
            </div>
        </div>`}async afterRender(){this._bindTopbar(),await Promise.all([this._load(),this._loadPages()])}async _load(){try{const t=await this.api.get("projects",this._filter);this._rows=(t==null?void 0:t.data)??[],this._renderTable()}catch(t){const s=this.ref("tableWrap");s&&(s.innerHTML=`<div class="pm-error">❌ ${this.esc(t.message)}</div>`)}}async _loadPages(){try{const t=await this.api.get("projects/pages");this._pages=(t==null?void 0:t.data)??[]}catch{}}_renderTable(){var a;const t=this.ref("tableWrap"),s=this.ref("countLbl");if(t){if(s&&(s.textContent=`${this._rows.length} پروژه`),!this._rows.length){t.innerHTML=`
            <div class="pm-empty">
                <div style="font-size:56px">📁</div>
                <p>هنوز پروژه‌ای تعریف نشده</p>
                <button class="pm-btn pm-btn--primary" data-action="new">+ اولین پروژه را بسازید</button>
            </div>`,(a=t.querySelector('[data-action="new"]'))==null||a.addEventListener("click",()=>this._openForm(null));return}t.innerHTML=`
        <table class="pm-table">
            <thead>
                <tr>
                    <th style="width:36px"></th>
                    <th>عنوان پروژه</th>
                    <th>نوع</th>
                    <th>شرکت / سایت</th>
                    <th>صفحه اول</th>
                    <th>وضعیت</th>
                    <th>تاریخ</th>
                    <th>عملیات</th>
                </tr>
            </thead>
            <tbody>
                ${this._rows.map(i=>this._row(i)).join("")}
            </tbody>
        </table>`,t.querySelectorAll("[data-action]").forEach(i=>{i.addEventListener("click",n=>{n.stopPropagation();const{action:r,id:o}=i.dataset,l=this._rows.find(c=>c.id==o);r==="edit"&&this._openForm(l),r==="activate"&&this._activate(l),r==="delete"&&this._delete(l)})}),t.querySelectorAll(".pm-tr").forEach(i=>{i.addEventListener("click",()=>{const n=this._rows.find(r=>r.id==i.dataset.id);n&&this._openForm(n)})})}}_row(t){const s=al[t.type]||{label:t.type,color:"#64748b"},a=il[t.status]||{label:t.status,color:"#94a3b8"},i=+t.is_running==1,n=t.created_at?new Date(t.created_at).toLocaleDateString("fa-IR"):"—",r=t.company_logo?`<img src="${this.esc(t.company_logo)}" class="pm-logo-thumb" alt="">`:`<span class="pm-logo-placeholder">${(t.company_name||t.title||"?").charAt(0)}</span>`;return`
        <tr class="pm-tr ${i?"pm-tr--running":""}" data-id="${t.id}">
            <td>${r}</td>
            <td>
                <div class="pm-row-title">
                    ${i?'<span class="pm-running-badge">● فعال</span>':""}
                    <strong>${this.esc(t.title)}</strong>
                </div>
                ${t.description?`<div class="pm-row-desc">${this.esc(t.description.slice(0,60))}${t.description.length>60?"…":""}</div>`:""}
            </td>
            <td><span class="pm-badge" style="background:${s.color}20;color:${s.color}">${s.label}</span></td>
            <td>
                <div style="font-size:13px;font-weight:600">${this.esc(t.company_name||"—")}</div>
                ${t.domain?`<div style="font-size:11px;color:#64748b">${this.esc(t.domain)}</div>`:""}
            </td>
            <td style="font-size:12px;color:#475569">${this.esc(t.front_page_title||"—")}</td>
            <td><span class="pm-badge" style="background:${a.color}20;color:${a.color}">${a.label}</span></td>
            <td style="font-size:11px;color:#94a3b8">${n}</td>
            <td>
                <div class="pm-actions" onclick="event.stopPropagation()">
                    ${i?"":`
                    <button class="pm-act-btn pm-act-btn--activate" data-action="activate" data-id="${t.id}" title="فعال‌سازی">
                        ▶ فعال
                    </button>`}
                    <button class="pm-act-btn" data-action="edit" data-id="${t.id}" title="ویرایش">✏️</button>
                    ${i?"":`<button class="pm-act-btn pm-act-btn--del" data-action="delete" data-id="${t.id}" title="حذف">🗑️</button>`}
                </div>
            </td>
        </tr>`}_openForm(t){var o,l,c,d;this._editing=t;const s=this.ref("modal"),a=this.ref("modalBody");if(!s||!a)return;const i=!t,n=t||{},r=this._pages.map(h=>`<option value="${h.id}" ${+n.front_page_id===h.id?"selected":""}>${this.esc(h.title)}</option>`).join("");a.innerHTML=`
        <div class="pm-form-header">
            <h3>${i?"+ پروژه جدید":`✏️ ویرایش: ${this.esc(n.title||"")}`}</h3>
            <button class="pm-close-btn" data-ref="closeForm">✕</button>
        </div>
        <div class="pm-form-body">
            <div class="pm-form-cols">
                <!-- ستون چپ -->
                <div class="pm-form-col">
                    <div class="pm-field">
                        <label>عنوان پروژه <span class="pm-req">*</span></label>
                        <input type="text" id="pf-title" class="pm-input" value="${this.esc(n.title||"")}" placeholder="مثال: سایت فروشگاه آقای رضایی">
                    </div>
                    <div class="pm-field">
                        <label>نوع پروژه</label>
                        <select id="pf-type" class="pm-input">
                            <option value="shop"       ${n.type==="shop"?"selected":""}>🛍️ فروشگاه اینترنتی</option>
                            <option value="realestate" ${n.type==="realestate"?"selected":""}>🏘️ سایت املاک</option>
                            <option value="portal"     ${n.type==="portal"?"selected":""}>📰 پورتال خبری</option>
                            <option value="custom"     ${n.type==="custom"?"selected":""}>⚙️ سفارشی</option>
                        </select>
                    </div>
                    <div class="pm-field">
                        <label>وضعیت</label>
                        <select id="pf-status" class="pm-input">
                            <option value="draft"    ${n.status==="draft"?"selected":""}>پیش‌نویس</option>
                            <option value="active"   ${n.status==="active"?"selected":""}>فعال</option>
                            <option value="archived" ${n.status==="archived"?"selected":""}>بایگانی</option>
                        </select>
                    </div>
                    <div class="pm-field">
                        <label>دامنه سایت</label>
                        <input type="text" id="pf-domain" class="pm-input" value="${this.esc(n.domain||"")}" placeholder="example.com" dir="ltr">
                    </div>
                    <div class="pm-field">
                        <label>صفحه اول وردپرس</label>
                        <select id="pf-front-page" class="pm-input">
                            <option value="">— انتخاب نشده —</option>
                            ${r}
                        </select>
                    </div>
                    <div class="pm-field">
                        <label>توضیحات</label>
                        <textarea id="pf-desc" class="pm-input" rows="3" placeholder="توضیح کوتاه درباره این پروژه...">${this.esc(n.description||"")}</textarea>
                    </div>
                </div>

                <!-- ستون راست: اطلاعات شرکت -->
                <div class="pm-form-col">
                    <div class="pm-section-title">🏢 هویت شرکت / سایت</div>
                    <div class="pm-field">
                        <label>نام شرکت / سایت <span class="pm-req">*</span></label>
                        <input type="text" id="pf-company" class="pm-input" value="${this.esc(n.company_name||"")}" placeholder="فروشگاه نمونه">
                    </div>
                    <div class="pm-field">
                        <label>شعار (tagline)</label>
                        <input type="text" id="pf-tagline" class="pm-input" value="${this.esc(n.company_tagline||"")}" placeholder="بهترین انتخاب برای شما">
                    </div>
                    <div class="pm-field">
                        <label>آدرس لوگو (URL)</label>
                        <input type="text" id="pf-logo" class="pm-input" value="${this.esc(n.company_logo||"")}" placeholder="https://..." dir="ltr">
                        ${n.company_logo?`<img src="${this.esc(n.company_logo)}" style="height:40px;margin-top:6px;border-radius:6px;" alt="">`:""}
                    </div>
                    <div class="pm-field">
                        <label>شماره تماس</label>
                        <input type="text" id="pf-phone" class="pm-input" value="${this.esc(n.company_phone||"")}" placeholder="021-..." dir="ltr">
                    </div>
                    <div class="pm-field">
                        <label>ایمیل</label>
                        <input type="email" id="pf-email" class="pm-input" value="${this.esc(n.company_email||"")}" placeholder="info@..." dir="ltr">
                    </div>
                    <div class="pm-field">
                        <label>آدرس</label>
                        <textarea id="pf-address" class="pm-input" rows="2" placeholder="تهران، خ...">${this.esc(n.company_address||"")}</textarea>
                    </div>
                </div>
            </div>
        </div>
        <div class="pm-form-footer">
            <div id="pf-error" class="pm-form-error" style="display:none"></div>
            <div style="display:flex;gap:8px;">
                <button class="pm-btn pm-btn--ghost" data-ref="closeForm2">انصراف</button>
                <button class="pm-btn pm-btn--primary" id="pf-save">
                    ${i?"✅ ایجاد پروژه":"💾 ذخیره تغییرات"}
                </button>
                ${!i&&!+n.is_running?`
                <button class="pm-btn pm-btn--activate" id="pf-activate">▶ فعال‌سازی</button>`:""}
            </div>
        </div>`,s.style.display="flex",this._bindRefs(),(o=this.ref("closeForm"))==null||o.addEventListener("click",()=>this._closeForm()),(l=this.ref("closeForm2"))==null||l.addEventListener("click",()=>this._closeForm()),s.addEventListener("click",h=>{h.target===s&&this._closeForm()}),(c=document.getElementById("pf-save"))==null||c.addEventListener("click",()=>this._saveForm()),(d=document.getElementById("pf-activate"))==null||d.addEventListener("click",()=>{this._closeForm(),this._activate(t)})}_closeForm(){const t=this.ref("modal");t&&(t.style.display="none"),this._editing=null}async _saveForm(){const t=r=>{var o,l;return((l=(o=document.getElementById(r))==null?void 0:o.value)==null?void 0:l.trim())??""},s=document.getElementById("pf-save");document.getElementById("pf-error");const a=t("pf-title"),i=t("pf-company");if(!a)return this._showFormErr("عنوان پروژه الزامی است");s&&(s.disabled=!0,s.textContent="⏳...");const n={title:a,company_name:i,type:t("pf-type"),status:t("pf-status"),domain:t("pf-domain"),front_page_id:t("pf-front-page")||null,description:t("pf-desc"),company_tagline:t("pf-tagline"),company_logo:t("pf-logo"),company_phone:t("pf-phone"),company_email:t("pf-email"),company_address:t("pf-address")};try{this._editing?await this.api.put(`projects/${this._editing.id}`,n):await this.api.post("projects",n),this._closeForm(),await this._load()}catch(r){this._showFormErr(r.message),s&&(s.disabled=!1,s.textContent=this._editing?"💾 ذخیره":"✅ ایجاد")}}_showFormErr(t){const s=document.getElementById("pf-error");s&&(s.textContent=t,s.style.display="block")}async _activate(t){if(t&&confirm(`پروژه «${t.title}» فعال شود؟
نام سایت و صفحه اول تغییر می‌کند.`))try{const s=await this.api.post(`projects/${t.id}/activate`,{});alert((s==null?void 0:s.message)||"فعال شد"),await this._load()}catch(s){alert("❌ "+s.message)}}async _delete(t){if(t&&confirm(`پروژه «${t.title}» حذف شود؟`))try{await this.api.delete(`projects/${t.id}`),await this._load()}catch(s){alert("❌ "+s.message)}}_bindTopbar(){var t,s,a;(t=this.ref("newBtn"))==null||t.addEventListener("click",()=>this._openForm(null)),(s=this.ref("typeFilter"))==null||s.addEventListener("change",i=>{this._filter.type=i.target.value,this._load()}),(a=this.ref("statusFilter"))==null||a.addEventListener("change",i=>{this._filter.status=i.target.value,this._load()})}esc(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}destroy(){var t;(t=super.destroy)==null||t.call(this)}}g(wa,"title","📁 پروژه‌ها"),E.register("projects-manager",wa);const Ft={agent:"مشاور املاک",legal:"وکیل حقوقی",municipality:"کارشناس شهرداری",registry:"کارشناس ثبت",appraisal:"کارشناس رسمی",contractor:"پیمانکار ساخت",finance:"کارشناس مالی",other:"سایر"},$a={note:"یادداشت",action:"اقدام",legal:"حقوقی",municipality:"شهرداری",registry:"ثبت"};function nl(p){return String(p??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function be(p){if(!p)return"—";try{const e=new Date(p.replace(" ","T"));return Number.isNaN(e.getTime())?p:e.toLocaleString("fa-IR",{dateStyle:"medium",timeStyle:"short"})}catch{return p}}function rl(p,e){return(p||e||"?").trim().charAt(0).toUpperCase()}function ka(p){return{agent:"agent",legal:"legal",municipality:"municipality",registry:"registry",appraisal:"appraisal",contractor:"contractor",finance:"finance"}[p]||"other"}function ol(p,e,t){const s=p.user_login?`@${e(p.user_login)}`:"نام کاربری ثبت نشده",a=+p.note_count||0;return`<article class="em-member-card" data-member-uid="${p.user_id}" title="کلیک کنید تا نظرات این عضو را ببینید">
        <div class="em-member-avatar em-member-avatar--${ka(p.role_type)}">${e(rl(p.display_name||p.user_name,p.user_login))}</div>
        <div class="em-member-body">
            <div class="em-member-top">
                <div>
                    <div class="em-member-name">${e(p.display_name||p.user_name)}</div>
                    <div class="em-member-login">${s}</div>
                </div>
                <span class="em-member-role em-member-role--${ka(p.role_type)}">${e(p.role_label||Ft[p.role_type]||p.role_type)}</span>
            </div>
            <div class="em-member-meta">
                <span class="em-member-join" title="نحوه پیوستن">🔗 ${e(p.join_label||"عضو پرونده")}</span>
                <span class="em-member-date" title="تاریخ پیوستن">📅 ${e(be(p.joined_at))}</span>
            </div>
            <div class="em-member-foot">
                <span class="em-member-stat">${a} یادداشت</span>
                ${t?`<button type="button" class="em-link-btn" data-rm-part="${p.id}">حذف</button>`:""}
            </div>
        </div>
    </article>`}function ll(p,e){if(p.kind==="joined"){const s=p.user_login?` <span class="em-activity-login">@${e(p.user_login)}</span>`:"";return`<div class="em-activity-item em-activity-item--join">
            <div class="em-activity-icon">👤</div>
            <div class="em-activity-body">
                <div class="em-activity-head">
                    <strong>${e(p.user_name)}</strong>${s}
                    <span class="em-activity-role">${e(p.role_label||Ft[p.role_type]||"")}</span>
                </div>
                <p class="em-activity-text">به پرونده پیوست — ${e(p.join_label||"")}</p>
                <time class="em-activity-time">${e(be(p.at))}</time>
            </div>
        </div>`}const t=p.user_login?` <span class="em-activity-login">@${e(p.user_login)}</span>`:"";return`<div class="em-activity-item em-activity-item--${e(p.note_type||"note")}">
        <div class="em-activity-icon">${p.note_type==="action"?"⚡":"💬"}</div>
        <div class="em-activity-body">
            <div class="em-activity-head">
                <strong>${e(p.user_name)}</strong>${t}
                <span class="em-activity-badge">${e(p.note_type_label||$a[p.note_type]||"یادداشت")}</span>
            </div>
            <p class="em-activity-text">${e(p.body)}</p>
            <time class="em-activity-time">${e(be(p.at))}</time>
        </div>
    </div>`}function cl(p,e){const t=p.user_login?`<span class="em-note-login">@${e(p.user_login)}</span>`:"";return`<div class="em-note em-note--${e(p.note_type||"note")}" data-note-uid="${p.user_id}">
        <div class="em-note-head">
            <span class="em-note-author">${e(p.display_name||p.user_name)}</span>
            ${t}
            <span class="em-note-type">${e(p.note_type_label||$a[p.note_type]||p.note_type||"")}</span>
            <time class="em-note-time">${e(be(p.created_at))}</time>
        </div>
        <p>${e(p.body)}</p>
    </div>`}function dl(p,e={}){const t=e.esc||nl,s=!!e.canEditFull,a=e.roleOpts||"",i=p.participants||[],n=p.notes||[],r=p.activity_timeline||[],o=p.participant_count??i.length,l=p.note_count??n.length;return`
    <div class="em-case-collab">
        ${p.created_by_name?`<div class="em-case-creator">ایجاد پرونده: <strong>${t(p.created_by_name)}</strong>${p.created_by_login?` <span class="em-case-creator-login">@${t(p.created_by_login)}</span>`:""} — ${t(be(p.created_at))}</div>`:""}
        <div class="em-case-tabs" role="tablist">
            <button type="button" class="em-case-tab em-case-tab--active" data-case-tab="members" role="tab">👥 اعضا (${o})</button>
            <button type="button" class="em-case-tab" data-case-tab="activity" role="tab">📜 فعالیت (${r.length})</button>
            <button type="button" class="em-case-tab" data-case-tab="notes" role="tab">📝 نظرات (${l})</button>
        </div>
        <div class="em-case-tab-panel em-case-tab-panel--active" data-case-panel="members">
            <div class="em-member-grid">
                ${i.map(d=>ol(d,t,s)).join("")||'<div class="em-empty-inline">عضوی ثبت نشده</div>'}
            </div>
            ${s?`<div class="em-add-part">
                <label class="em-add-part-label">افزودن عضو جدید</label>
                <input data-ref="partUserQ" class="red-inp" placeholder="جستجوی نام یا نام کاربری...">
                <div data-ref="partUserResults" class="em-user-results"></div>
                <select data-ref="partRoleSel">${a}</select>
            </div>`:""}
        </div>
        <div class="em-case-tab-panel" data-case-panel="activity" hidden>
            <div class="em-activity-timeline">
                ${r.map(d=>ll(d,t)).join("")||'<div class="em-empty-inline">فعالیتی ثبت نشده</div>'}
            </div>
        </div>
        <div class="em-case-tab-panel" data-case-panel="notes" hidden>
            <div class="em-notes em-notes--full">
                ${n.map(d=>cl(d,t)).join("")||'<div class="em-empty-inline">یادداشتی ثبت نشده</div>'}
            </div>
            <div class="em-note-form">
                <select data-ref="noteTypeSel">
                    <option value="note">یادداشت</option>
                    <option value="action">اقدام</option>
                    <option value="legal">حقوقی</option>
                    <option value="municipality">شهرداری</option>
                    <option value="registry">ثبت</option>
                </select>
                <textarea data-ref="noteInput" rows="3" placeholder="یادداشت یا اقدام جدید..."></textarea>
                <button type="button" class="red-btn red-btn--primary" data-ref="noteSubmit">ثبت یادداشت</button>
            </div>
        </div>
    </div>`}function pl(p){if(!p)return;const e=p.querySelectorAll("[data-case-tab]"),t=p.querySelectorAll("[data-case-panel]");e.forEach(s=>{s.addEventListener("click",()=>{const a=s.dataset.caseTab;e.forEach(i=>i.classList.toggle("em-case-tab--active",i.dataset.caseTab===a)),t.forEach(i=>{const n=i.dataset.casePanel===a;i.classList.toggle("em-case-tab-panel--active",n),i.hidden=!n}),a==="notes"&&p.querySelectorAll(".em-note[data-note-uid]").forEach(i=>{i.style.display=""})})})}function hl(p,e){if(!p||!e)return;const t=p.querySelector('[data-case-tab="notes"]');t==null||t.click(),p.querySelectorAll(".em-note[data-note-uid]").forEach(s=>{s.style.display=+s.dataset.noteUid==+e?"":"none"})}const ge={open:{label:"باز",color:"#3b82f6"},in_progress:{label:"در جریان",color:"#f59e0b"},review:{label:"بررسی",color:"#8b5cf6"},closed:{label:"بسته",color:"#94a3b8"}};class Ea extends C{constructor(t={}){super(t);g(this,"useContextBadge",!1);g(this,"_onOpenCaseEvent",({caseId:t})=>{t&&this._openCase(t)});this.api=t.api,this._tab="dashboard",this._overview=null,this._data=[],this._cases=[],this._org=[],this._level="district",this._path=[],this._search="",this._participantRoles=[],this._canManage=!1,this._blockCtx=null}async template(){return`<div class="em-wrap red-wrap" dir="rtl">
            <div class="red-hero em-hero">
                <div class="red-hero-title">
                    <span class="red-hero-icon">🏛️</span>
                    <div>
                        <div class="red-hero-name">اقتصاد ملک</div>
                        <div class="red-hero-sub">شبکه همکاری بنگاه — منطقه → محله → بلوک → ملک → پرونده</div>
                    </div>
                </div>
                <div class="red-kpis">
                    <div class="red-kpi"><div class="red-kpi-val" data-ref="kDistricts">—</div><div class="red-kpi-lbl">منطقه</div></div>
                    <div class="red-kpi"><div class="red-kpi-val" data-ref="kCases">—</div><div class="red-kpi-lbl">پرونده باز</div></div>
                    <div class="red-kpi"><div class="red-kpi-val em-role-chip" data-ref="kRole">—</div><div class="red-kpi-lbl">نقش شما</div></div>
                </div>
            </div>

            <div class="em-main-tabs" data-ref="mainTabs">
                <button class="em-main-tab em-main-tab--active" data-tab="dashboard">🗺️ داشبورد</button>
                <button class="em-main-tab" data-tab="cases">📋 پرونده‌ها</button>
                <button class="em-main-tab em-main-tab--org" data-tab="org" style="display:none">👥 سازمان</button>
            </div>

            <div data-ref="panelDashboard">
                <div class="em-toolbar red-toolbar">
                    <input class="red-inp" placeholder="🔍 جستجو..." data-ref="searchInput">
                    <div class="red-crumbs" data-ref="crumbs"></div>
                    <button class="red-btn" data-ref="backBtn" style="display:none">← بازگشت</button>
                    <button class="red-btn red-btn--primary" data-ref="refreshBtn">↻</button>
                    <button class="red-btn" data-ref="newCaseBtn" style="display:none">➕ پرونده</button>
                    <button class="red-btn" data-ref="mapBtn">🗺️ نقشه</button>
                </div>
                <div class="em-grid red-grid" data-ref="grid"></div>
            </div>

            <div data-ref="panelCases" style="display:none">
                <div class="em-toolbar red-toolbar">
                    <select class="red-sel" data-ref="caseStatusFilter">
                        <option value="">همه وضعیت‌ها</option>
                        <option value="open">باز</option>
                        <option value="in_progress">در جریان</option>
                        <option value="review">بررسی</option>
                        <option value="closed">بسته</option>
                    </select>
                    <button class="red-btn red-btn--primary" data-ref="reloadCasesBtn">↻ بروزرسانی</button>
                </div>
                <div class="em-cases-full" data-ref="casesFull"></div>
            </div>

            <div data-ref="panelOrg" style="display:none">
                <div class="em-org-form" data-ref="orgForm"></div>
                <div class="em-org-list" data-ref="orgList"></div>
            </div>

            <div class="red-detail-overlay" data-ref="detailOverlay" style="display:none">
                <div class="red-detail em-detail">
                    <button class="red-detail-close" data-ref="detailClose">✕</button>
                    <div data-ref="detailBody"></div>
                </div>
            </div>
        </div>`}async afterRender(){var t,s;if(this._canManage=L.can("melk.manage"),this._canManage){const a=(t=this.ref("mainTabs"))==null?void 0:t.querySelector('[data-tab="org"]');a&&(a.style.display="")}try{const a=await this.api.get("melk/participant-roles");this._participantRoles=(a==null?void 0:a.data)??[]}catch{this._participantRoles=[]}await this._loadOverview(),this._bindEvents(),this._checkGisHandoff(),(s=this.eventBus)==null||s.on("melk:open-case",this._onOpenCaseEvent,this)}destroy(){var t,s;(t=this.eventBus)==null||t.off("melk:open-case",this._onOpenCaseEvent),(s=super.destroy)==null||s.call(this)}async _checkGisHandoff(){try{const t=sessionStorage.getItem("acc_melk_create_parcel");if(!t)return;sessionStorage.removeItem("acc_melk_create_parcel");const s=JSON.parse(t);s!=null&&s.parcel_id&&await this._createCaseFromParcel(s)}catch{}}async _loadOverview(){var t;try{const s=await this.api.get("melk/overview");this._overview=(s==null?void 0:s.data)??s,this._data=((t=this._overview)==null?void 0:t.districts)??[],this._level="district",this._path=[],this._blockCtx=null,this._updateKpis(),this._tab==="dashboard"&&(this._renderGrid(),this._renderCrumbs())}catch(s){this.ref("grid").innerHTML=`<div class="em-empty">خطا: ${this.esc(s.message)}</div>`}}async _switchMainTab(t){var s;this._tab=t,(s=this.ref("mainTabs"))==null||s.querySelectorAll(".em-main-tab").forEach(a=>a.classList.toggle("em-main-tab--active",a.dataset.tab===t)),this.ref("panelDashboard").style.display=t==="dashboard"?"":"none",this.ref("panelCases").style.display=t==="cases"?"":"none",this.ref("panelOrg").style.display=t==="org"?"":"none",t==="cases"&&await this._loadCases(),t==="org"&&await this._loadOrg()}async _loadCases(t={}){var i,n;const s=(i=this.ref("caseStatusFilter"))==null?void 0:i.value;s&&(t.status=s);const a=new URLSearchParams(t).toString();try{const r=await this.api.get(`melk/cases${a?"?"+a:""}`);this._cases=((n=r==null?void 0:r.data)==null?void 0:n.data)??(r==null?void 0:r.data)??[]}catch{this._cases=[]}this._renderCasesList(this.ref("casesFull"))}async _loadOrg(){var t;try{const s=await this.api.get("melk/org-assignments");this._org=((t=s==null?void 0:s.data)==null?void 0:t.data)??(s==null?void 0:s.data)??[]}catch{this._org=[]}this._renderOrg()}async _drill(t){var s,a,i;if(this._level==="district"){this._path.push({level:"district",id:t.id,label:t.name}),this._level="neighborhood";const n=await this.api.get(`melk/hierarchy?level=neighborhood&district=${t.id}`);this._data=((s=n==null?void 0:n.data)==null?void 0:s.data)??(n==null?void 0:n.data)??[]}else if(this._level==="neighborhood"){this._path.push({level:"neighborhood",id:t.id,label:t.name}),this._level="block";const n=await this.api.get(`melk/hierarchy?level=block&neighborhood=${t.id}`);this._data=((a=n==null?void 0:n.data)==null?void 0:a.data)??(n==null?void 0:n.data)??[]}else if(this._level==="block"){this._path.push({level:"block",id:t.block_code,label:t.block_code,block:t}),this._level="parcel",this._blockCtx=t;const n=await this.api.get(`gis/parcels?block=${encodeURIComponent(t.block_code)}`);this._data=((i=n==null?void 0:n.data)==null?void 0:i.data)??(n==null?void 0:n.data)??[]}else return;this._renderGrid(),this._renderCrumbs(),this.ref("backBtn").style.display="",this._toggleNewCaseBtn()}_toggleNewCaseBtn(){const t=this.ref("newCaseBtn");if(!t)return;const s=L.can("melk.cases.create")&&(this._level==="block"||this._level==="parcel");t.style.display=s?"":"none"}_updateKpis(){const t=this._overview||{};this.ref("kDistricts")&&(this.ref("kDistricts").textContent=t.district_count??"—"),this.ref("kCases")&&(this.ref("kCases").textContent=t.open_cases??"—"),this.ref("kRole")&&(this.ref("kRole").textContent=t.user_role||"کاربر")}_renderCrumbs(){var i;const t=this.ref("crumbs");if(!t)return;const a=[{label:`🏛️ ${((i=this._overview)==null?void 0:i.city)||"شهر"}`},...this._path.map(n=>({label:n.label}))];t.innerHTML=a.map((n,r)=>`<span class="red-crumb${r===a.length-1?" red-crumb--active":""}" data-idx="${r}">${this.esc(n.label)}</span>`).join('<span class="red-crumb-sep">›</span>'),t.querySelectorAll(".red-crumb").forEach(n=>{n.addEventListener("click",()=>this._crumbNav(parseInt(n.dataset.idx,10)))})}async _crumbNav(t){var a,i,n;if(t<=0){await this._loadOverview(),this.ref("backBtn").style.display="none",this._toggleNewCaseBtn();return}const s=this._path[t-1];if(this._path=this._path.slice(0,t),s.level==="district"){this._level="neighborhood";const r=await this.api.get(`melk/hierarchy?level=neighborhood&district=${s.id}`);this._data=((a=r==null?void 0:r.data)==null?void 0:a.data)??(r==null?void 0:r.data)??[]}else if(s.level==="neighborhood"){this._level="block";const r=await this.api.get(`melk/hierarchy?level=block&neighborhood=${s.id}`);this._data=((i=r==null?void 0:r.data)==null?void 0:i.data)??(r==null?void 0:r.data)??[],this._blockCtx=null}else if(s.level==="block"){this._level="parcel",this._blockCtx=s.block;const r=await this.api.get(`gis/parcels?block=${encodeURIComponent(s.id)}`);this._data=((n=r==null?void 0:r.data)==null?void 0:n.data)??(r==null?void 0:r.data)??[]}this._renderGrid(),this._renderCrumbs(),this._toggleNewCaseBtn()}_renderGrid(){const t=this.ref("grid");if(!t)return;const s=this._search.toLowerCase(),a=(this._data||[]).filter(i=>{const n=(i.name||i.block_code||i.code||"").toLowerCase();return!s||n.includes(s)});if(!a.length){t.innerHTML='<div class="em-empty">موردی یافت نشد.</div>';return}this._level==="district"?t.innerHTML=a.map(i=>`
                <div class="red-card em-card" data-id="${i.id}">
                    <div class="em-card-badge" style="background:${i.color||"#6366f1"}">${this.esc(i.code||i.id)}</div>
                    <div class="red-card-title">${this.esc(i.name)}</div>
                    <div class="red-card-meta"><span>🏘️ ${i.neighborhood_count||0}</span><span>📍 ${i.parcel_count||0}</span></div>
                    ${i.lead_name?`<div class="em-lead">👤 ${this.esc(i.lead_name)}</div>`:'<div class="em-lead em-lead--empty">سرگروه تعیین نشده</div>'}
                </div>`).join(""):this._level==="neighborhood"?t.innerHTML=a.map(i=>`
                <div class="red-card em-card" data-id="${i.id}">
                    <div class="red-card-title">${this.esc(i.name)}</div>
                    <div class="red-card-meta"><span>🧱 ${i.block_count||0}</span><span>📍 ${i.parcel_count||0}</span></div>
                    ${i.manager_name?`<div class="em-lead">👤 ${this.esc(i.manager_name)}</div>`:""}
                </div>`).join(""):this._level==="block"?t.innerHTML=a.map(i=>`
                <div class="red-card em-card" data-block="${this.esc(i.block_code)}">
                    <div class="red-card-title">🧱 ${this.esc(i.block_code)}</div>
                    <div class="red-card-meta"><span>📍 ${i.parcel_count||0}</span><span>🏢 ${i.bld_count||0}</span></div>
                    ${i.open_cases>0?`<div class="em-case-badge">${i.open_cases} پرونده</div>`:""}
                </div>`).join(""):t.innerHTML=a.map(i=>`
                <div class="red-card em-card em-card--parcel" data-parcel="${i.id}">
                    <div class="red-card-title">${this.esc(i.code||"ملک #"+i.id)}</div>
                    <div class="red-card-meta"><span>${this.esc(i.status||"")}</span>${i.area_sqm?`<span>${i.area_sqm} m²</span>`:""}</div>
                    <div class="em-card-actions">
                        ${L.can("melk.cases.create")?`<button class="em-mini-btn" data-action="case" data-id="${i.id}">➕ پرونده</button>`:""}
                        <button class="em-mini-btn" data-action="map" data-id="${i.id}" data-code="${this.esc(i.code||"")}">🗺️</button>
                    </div>
                </div>`).join(""),t.querySelectorAll(".red-card").forEach(i=>{i.addEventListener("click",n=>{if(n.target.closest("[data-action]"))return;const r=i.dataset.id,o=i.dataset.block;if(this._level==="parcel")return;const l=a.find(c=>String(c.id)===r||c.block_code===o);l&&this._drill(l)})}),t.querySelectorAll('[data-action="case"]').forEach(i=>{i.addEventListener("click",async n=>{n.stopPropagation();const r=a.find(o=>String(o.id)===i.dataset.id);r&&await this._createCaseFromParcel(r)})}),t.querySelectorAll('[data-action="map"]').forEach(i=>{i.addEventListener("click",n=>{var o,l,c;n.stopPropagation();const r=i.dataset.code;(o=this._blockCtx)!=null&&o.block_code&&sessionStorage.setItem("acc_gis_focus_block",JSON.stringify({block:this._blockCtx.block_code})),(c=this.eventBus)==null||c.emit("tab:open",{key:"gis",params:{focusBlock:(l=this._blockCtx)==null?void 0:l.block_code,code:r}})})})}_renderCasesList(t){if(t){if(!this._cases.length){t.innerHTML='<div class="em-empty">پرونده‌ای ثبت نشده.</div>';return}t.innerHTML=this._cases.map(s=>this._caseRowHtml(s)).join(""),t.querySelectorAll(".em-case-row").forEach(s=>{s.addEventListener("click",()=>this._openCase(parseInt(s.dataset.case,10)))})}}_caseRowHtml(t){const s=ge[t.status]||ge.open;return`<div class="em-case-row" data-case="${t.id}">
            <div class="em-case-key">${this.esc(t.case_key)}</div>
            <div class="em-case-title">${this.esc(t.title)}</div>
            <div class="em-case-loc">${this.esc(t.district_name||"")} ${t.neighborhood_name?"› "+this.esc(t.neighborhood_name):""} ${t.block_code?"› "+this.esc(t.block_code):""}</div>
            <span class="em-status" style="background:${s.color}">${s.label}</span>
        </div>`}async _createCaseFromParcel(t){var a;if(!L.can("melk.cases.create"))return alert("مجوز ایجاد پرونده ندارید");const s=prompt("عنوان پرونده:",`پرونده ${t.code||t.id}`);if(s!==null)try{const i=await this.api.post("melk/cases",{parcel_id:t.id||t.parcel_id,title:s||`پرونده ${t.code||t.id}`,district_id:t.district_id,neighborhood_id:t.neighborhood_id,block_code:t.block_code}),n=(i==null?void 0:i.id)??((a=i==null?void 0:i.data)==null?void 0:a.id);n&&(await this._openCase(n),await this._loadOverview())}catch(i){alert(i.message||i)}}async _createCaseFromContext(){var n,r;const t=this._path.find(o=>o.level==="district"),s=this._path.find(o=>o.level==="neighborhood"),a=this._path.find(o=>o.level==="block"),i=prompt("عنوان پرونده:",a?`پرونده بلوک ${a.label}`:"پرونده جدید");if(i!==null)try{const o=await this.api.post("melk/cases",{title:i,district_id:t==null?void 0:t.id,neighborhood_id:s==null?void 0:s.id,block_code:(a==null?void 0:a.id)||((n=this._blockCtx)==null?void 0:n.block_code)}),l=(o==null?void 0:o.id)??((r=o==null?void 0:o.data)==null?void 0:r.id);l&&await this._openCase(l)}catch(o){alert(o.message||o)}}async _openCase(t){var s,a,i;try{const n=await this.api.get(`melk/cases/${t}`),r=((s=n==null?void 0:n.data)==null?void 0:s.data)??(n==null?void 0:n.data),o=ge[r.status]||ge.open,l=L.can("melk.cases.edit")||L.can("melk.manage"),c=this.ref("detailBody"),d=(this._participantRoles.length?this._participantRoles:Object.entries(Ft).map(([b,v])=>({key:b,label:v}))).map(b=>`<option value="${b.key}">${this.esc(b.label)}</option>`).join(""),h=dl(r,{esc:b=>this.esc(b),canEditFull:l,roleOpts:d});c.innerHTML=`
                <h2>${this.esc(r.title)}</h2>
                <div class="em-detail-meta">
                    <span class="em-status" style="background:${o.color}">${o.label}</span>
                    <span>${this.esc(r.case_key)}</span>
                    ${r.parcel_code?`<span>کد: ${this.esc(r.parcel_code)}</span>`:""}
                </div>
                <p class="em-detail-loc">📍 ${this.esc(r.district_name||"")} ${r.neighborhood_name?"› "+this.esc(r.neighborhood_name):""} ${r.block_code?"› "+this.esc(r.block_code):""}</p>
                ${l?`<div class="em-detail-edit">
                    <label>وضعیت</label>
                    <select data-ref="caseStatusSel">${Object.entries(ge).map(([b,v])=>`<option value="${b}" ${r.status===b?"selected":""}>${v.label}</option>`).join("")}</select>
                    <label>خلاصه</label>
                    <textarea data-ref="caseSummary" rows="2">${this.esc(r.summary||"")}</textarea>
                    <button class="red-btn red-btn--primary" data-ref="saveCaseBtn">ذخیره</button>
                </div>`:r.summary?`<p>${this.esc(r.summary)}</p>`:""}
                <div class="em-case-section em-case-section--collab">
                    <h4>👥 همکاری و نظرات اعضا</h4>
                    ${h}
                </div>`,pl(c.querySelector(".em-case-collab")),c.querySelectorAll(".em-member-card").forEach(b=>{b.addEventListener("click",v=>{v.target.closest("[data-rm-part]")||hl(c.querySelector(".em-case-collab"),+b.dataset.memberUid)})}),this.ref("detailOverlay").style.display="flex",(a=c.querySelector('[data-ref="noteSubmit"]'))==null||a.addEventListener("click",()=>this._submitNote(t)),(i=c.querySelector('[data-ref="saveCaseBtn"]'))==null||i.addEventListener("click",()=>this._saveCase(t,c)),c.querySelectorAll("[data-rm-part]").forEach(b=>{b.addEventListener("click",async()=>{await this.api.delete(`melk/cases/${t}/participants/${b.dataset.rmPart}`),await this._openCase(t)})});const u=c.querySelector('[data-ref="partUserQ"]'),f=c.querySelector('[data-ref="partUserResults"]');let m;u==null||u.addEventListener("input",()=>{clearTimeout(m),m=setTimeout(async()=>{const b=u.value.trim();if(b.length<1){f.innerHTML="";return}const v=await this.api.get(`melk/users?q=${encodeURIComponent(b)}`),y=(v==null?void 0:v.data)??[];f.innerHTML=y.map($=>`<button type="button" class="em-user-pick" data-uid="${$.id}">${this.esc($.display_name)} (${this.esc($.user_login)})</button>`).join(""),f.querySelectorAll(".em-user-pick").forEach($=>{$.addEventListener("click",async()=>{var w;await this.api.post(`melk/cases/${t}/participants`,{user_id:+$.dataset.uid,role_type:((w=c.querySelector('[data-ref="partRoleSel"]'))==null?void 0:w.value)||"other"}),await this._openCase(t)})})},300)})}catch(n){alert(n.message||n)}}async _saveCase(t,s){var a,i;try{await this.api.put(`melk/cases/${t}`,{status:(a=s.querySelector('[data-ref="caseStatusSel"]'))==null?void 0:a.value,summary:(i=s.querySelector('[data-ref="caseSummary"]'))==null?void 0:i.value}),await this._openCase(t),await this._loadOverview()}catch(n){alert(n.message||n)}}async _submitNote(t){var i,n;const s=(i=this.ref("detailBody"))==null?void 0:i.querySelector('[data-ref="noteInput"]'),a=(n=s==null?void 0:s.value)==null?void 0:n.trim();if(a)try{await this.api.post(`melk/cases/${t}/notes`,{body:a}),await this._openCase(t)}catch(r){alert(r.message||r)}}async _renderOrg(){var u,f;const t=this.ref("orgForm"),s=this.ref("orgList");if(!t||!s)return;let a=[],i=[];try{const m=await this.api.get("gis/districts");a=((u=m==null?void 0:m.data)==null?void 0:u.data)??(m==null?void 0:m.data)??[];const b=await this.api.get("gis/neighborhoods");i=((f=b==null?void 0:b.data)==null?void 0:f.data)??(b==null?void 0:b.data)??[]}catch{}t.innerHTML=`
            <h3>تعیین سرگروه / مدیر محله</h3>
            <div class="em-org-row">
                <select data-ref="orgUnitType">
                    <option value="district">منطقه (سرگروه)</option>
                    <option value="neighborhood">محله (مدیر)</option>
                </select>
                <select data-ref="orgUnitId">
                    ${a.map(m=>`<option value="${m.id}" data-type="district">${this.esc(m.name)}</option>`).join("")}
                </select>
                <input data-ref="orgUserQ" class="red-inp" placeholder="جستجوی کاربر...">
                <input type="hidden" data-ref="orgUserId" value="">
                <div data-ref="orgUserPick"></div>
                <button class="red-btn red-btn--primary" data-ref="orgSaveBtn">ذخیره</button>
            </div>`;const n=t.querySelector('[data-ref="orgUnitType"]'),r=t.querySelector('[data-ref="orgUnitId"]'),o=()=>{const m=n.value;r.innerHTML=(m==="district"?a:i).map(b=>`<option value="${b.id}">${this.esc(b.name)}</option>`).join("")};n.addEventListener("change",o);let l;const c=t.querySelector('[data-ref="orgUserQ"]'),d=t.querySelector('[data-ref="orgUserPick"]'),h=t.querySelector('[data-ref="orgUserId"]');c.addEventListener("input",()=>{clearTimeout(l),l=setTimeout(async()=>{const m=c.value.trim();if(!m){d.innerHTML="";return}const b=await this.api.get(`melk/users?q=${encodeURIComponent(m)}`);d.innerHTML=((b==null?void 0:b.data)??[]).map(v=>`<button type="button" class="em-user-pick" data-uid="${v.id}">${this.esc(v.display_name)}</button>`).join(""),d.querySelectorAll(".em-user-pick").forEach(v=>{v.addEventListener("click",()=>{h.value=v.dataset.uid,c.value=v.textContent,d.innerHTML=""})})},300)}),t.querySelector('[data-ref="orgSaveBtn"]').addEventListener("click",async()=>{const m=+h.value;if(!m)return alert("کاربر را انتخاب کنید");try{await this.api.post("melk/org-assignments",{unit_type:n.value,unit_id:+r.value,user_id:m,role_slug:n.value==="district"?"district_lead":"neighborhood_manager"}),await this._loadOrg(),await this._loadOverview()}catch(b){alert(b.message||b)}}),s.innerHTML="<h3>انتصاب‌های فعلی</h3>"+(this._org.length?`
            <table class="em-org-table"><thead><tr><th>نوع</th><th>واحد</th><th>مسئول</th><th></th></tr></thead>
            <tbody>${this._org.map(m=>`<tr>
                <td>${m.unit_type==="district"?"منطقه":"محله"}</td>
                <td>${this.esc(m.district_name||m.neighborhood_name||m.unit_id)}</td>
                <td>${this.esc(m.user_name||m.user_id)}</td>
                <td><button class="em-link-btn" data-del-org="${m.id}">حذف</button></td>
            </tr>`).join("")}</tbody></table>`:'<p class="em-empty">انتصابی ثبت نشده.</p>'),s.querySelectorAll("[data-del-org]").forEach(m=>{m.addEventListener("click",async()=>{confirm("حذف شود؟")&&(await this.api.delete(`melk/org-assignments/${m.dataset.delOrg}`),await this._loadOrg(),await this._loadOverview())})})}_bindEvents(){var t,s,a,i,n,r,o,l,c;(t=this.ref("mainTabs"))==null||t.querySelectorAll(".em-main-tab").forEach(d=>{d.addEventListener("click",()=>this._switchMainTab(d.dataset.tab))}),(s=this.ref("searchInput"))==null||s.addEventListener("input",d=>{this._search=d.target.value,this._renderGrid()}),(a=this.ref("refreshBtn"))==null||a.addEventListener("click",()=>this._loadOverview()),(i=this.ref("reloadCasesBtn"))==null||i.addEventListener("click",()=>this._loadCases()),(n=this.ref("caseStatusFilter"))==null||n.addEventListener("change",()=>this._loadCases()),(r=this.ref("newCaseBtn"))==null||r.addEventListener("click",()=>this._createCaseFromContext()),(o=this.ref("backBtn"))==null||o.addEventListener("click",async()=>{this._path.length&&await this._crumbNav(this._path.length)}),(l=this.ref("detailClose"))==null||l.addEventListener("click",()=>{this.ref("detailOverlay").style.display="none"}),(c=this.ref("mapBtn"))==null||c.addEventListener("click",()=>{var d;(d=this.eventBus)==null||d.emit("tab:open",{key:"gis"})})}esc(t){return String(t??"").replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}}g(Ea,"title","🏛️ اقتصاد ملک"),E.register("eqtesad_melk",Ea);class ul{constructor(){this.eventBus=new Ma,this.store=new Ra(this.eventBus),this.api=new qa({config:{apiUrl:window.ACC_CONFIG.api},eventBus:this.eventBus,store:this.store}),this.tabManager=null,this.eventBus.on("auth:login:success",e=>{var t;this.store.set("auth",{user:e.user,nonce:e.nonce,loggedIn:!0}),e.token&&this.store.set("session",{user:e.user,token:e.token,isCustomLogin:!0}),(t=e.user)!=null&&t.id&&(window.accCurrentUserId=+e.user.id),window.dispatchEvent(new Event("erp:login")),L._loaded=!1,L.load(this.api).then(()=>{var a,i,n,r;const s=((i=(a=L.roles)==null?void 0:a[0])==null?void 0:i.name)||((r=(n=L.roles)==null?void 0:n[0])==null?void 0:r.slug)||"";if(s){const o=this.store.get("auth")||{};this.store.set("auth",{...o,user:{...o.user||e.user||{},role:s},loggedIn:!0})}this.initShellUI().then(()=>{this.showWorkspace(),this._consumePendingTab()})})}),this.eventBus.on("auth:unauthorized",()=>{try{sessionStorage.removeItem("acc_token")}catch{}this.store.set("auth",{user:null,nonce:null,loggedIn:!1}),this.store.set("session",null),this.showLogin()}),this.eventBus.on("tabs:switchUser",({tabId:e})=>{const t=prompt("Enter username:");t&&this.eventBus.emit("modal:userSelected",{tabId:e,user:{username:t}})}),this.eventBus.on("view:switchUser",({view:e})=>{var s;const t=prompt("Enter username:");t&&this.eventBus.emit("modal:userSelected",{tabId:(s=e.tab)==null?void 0:s.id,user:{username:t}})}),this.eventBus.on("tab:open",({key:e,params:t})=>{if(!this.tabManager){console.warn("TabManager not ready yet.");return}const s=this.getCurrentUserContext();this.tabManager.openTab(e,{userContext:s,params:t||{}})})}async start(){var a;const e=new URLSearchParams(window.location.search).get("tab")||sessionStorage.getItem("acc_pending_tab");if(e&&sessionStorage.setItem("acc_pending_tab",e),await this._restoreSession()){try{await this._reloadAcl()}catch{try{await L.load(this.api)}catch{}}await this.initShellUI(),this.showWorkspace(),this._consumePendingTab();return}const s=this.store.get("auth");if(s!=null&&s.loggedIn){(a=s.user)!=null&&a.id&&(window.accCurrentUserId=+s.user.id);try{await L.load(this.api)}catch{}await this.initShellUI(),this.showWorkspace(),this._consumePendingTab()}else await this.initShellUI(),this.showLogin(),new URLSearchParams(window.location.search).get("auth")==="1"&&setTimeout(()=>this._openLoginPanel(),300)}async _reloadAcl(){L._loaded=!1,await L.load(this.api)}async _restoreSession(){var t,s,a,i;const e=sessionStorage.getItem("acc_token");if(!e)return!1;try{const n=await this.api.get("/acl/me");if(!(n!=null&&n.user_id)&&!(n!=null&&n.user))throw new Error("no user");const r=n.user||{id:n.user_id,display_name:"کاربر"},o=((s=(t=n.roles)==null?void 0:t[0])==null?void 0:s.name)||((i=(a=n.roles)==null?void 0:a[0])==null?void 0:i.slug)||"";return this.store.set("auth",{user:{...r,role:o},nonce:null,loggedIn:!0}),this.store.set("session",{user:r,token:e,isCustomLogin:!0}),r.id&&(window.accCurrentUserId=+r.id),window.dispatchEvent(new Event("erp:login")),!0}catch{return sessionStorage.removeItem("acc_token"),this.store.set("auth",{user:null,nonce:null,loggedIn:!1}),!1}}_openLoginPanel(){const e=document.querySelector("#lp-auth-panel"),t=document.querySelector("#lp-open-auth");e?(e.classList.add("lp-auth-panel--open"),e.scrollIntoView({behavior:"smooth",block:"nearest"})):t&&t.click()}_consumePendingTab(){const e=new URLSearchParams(window.location.search),t=e.get("tab")||sessionStorage.getItem("acc_pending_tab");if(!t||!this.tabManager)return;sessionStorage.removeItem("acc_pending_tab");const s=this.getCurrentUserContext();if(this.tabManager.openTab(t,{userContext:s}),e.get("tab")){const a=window.location.pathname+window.location.hash;history.replaceState({},"",a)}}async initShellUI(){var n;const e=document.getElementById("acc-user-name"),t=document.getElementById("acc-user-role"),s=document.getElementById("acc-logout-btn"),a=document.getElementById("erp-shell-header"),i=this.store.get("auth");if(i!=null&&i.user&&e&&(e.textContent=i.user.display_name||i.user.user_login||"کاربر"),t){const r=((n=i==null?void 0:i.user)==null?void 0:n.role)||"";t.textContent=r,t.style.display=r?"":"none"}if(a&&(a.hidden=!(i!=null&&i.loggedIn)),s&&!s.__accBound&&(s.__accBound=!0,s.addEventListener("click",r=>{r.preventDefault(),this._logout()})),!this.tabManager){const{default:r}=await Ta(async()=>{const{default:o}=await Promise.resolve().then(()=>ml);return{default:o}},void 0);this.tabManager=new r({eventBus:this.eventBus,store:this.store,api:this.api,cache:this.cache,auth:this.auth,tabbarSelector:"#acc-tabbar",contentSelector:"#acc-tab-content",tabConfigRegistry:Pt,viewResolver:Fa})}}_logout(){var t,s;try{sessionStorage.removeItem("acc_token"),sessionStorage.removeItem("acc_tabs_state"),sessionStorage.removeItem("acc_pending_tab"),localStorage.removeItem("acc_token")}catch{}this.store.set("auth",{user:null,nonce:null,loggedIn:!1}),this.store.set("session",null),window.accCurrentUserId=null,window.dispatchEvent(new Event("erp:logout"));const e=document.getElementById("erp-shell-header");e&&(e.hidden=!0);try{(s=(t=this.tabManager)==null?void 0:t.tabs)!=null&&s.clear&&this.tabManager.tabs.clear()}catch{}this.showLogin()}showLogin(){const e=document.getElementById("acc-login-container"),t=document.getElementById("acc-tabbar"),s=document.getElementById("acc-tab-content"),a=document.getElementById("erp-shell-header");if(!e)return;a&&(a.hidden=!0),t&&(t.style.display="none",t.innerHTML=""),s&&(s.style.display="none",s.innerHTML=""),e.style.display="block",e.innerHTML="",new Ha({api:this.api,store:this.store,eventBus:this.eventBus}).render(e)}async showWorkspace(){const e=document.getElementById("acc-login-container"),t=document.getElementById("acc-tabbar"),s=document.getElementById("acc-tab-content"),a=document.getElementById("erp-shell-header");if(e&&(e.style.display="none",e.innerHTML=""),a&&(a.hidden=!1),t&&(t.style.display="flex"),s&&(s.style.display="block"),await this.initShellUI(),this.tabManager){const i=this.getCurrentUserContext();this.tabManager.openTab("sidebar",{fixed:!0,userContext:i})}this.initMenuHandlers()}initMenuHandlers(){const e=document.getElementById("acc-menu-root");!e||e.__acc_bound||(e.__acc_bound=!0,e.addEventListener("click",t=>{const s=t.target.closest(".acc-menu-item");if(!s)return;const a=s.dataset.view;if(!a)return;const i=this.getCurrentUserContext();this.tabManager.openTab(a,{userContext:i})}))}getCurrentUser(){var e;return((e=this.store.get("auth"))==null?void 0:e.user)??null}getCurrentUserContext(){const e=this.getCurrentUser();return e?{id:e.id??null,display_name:e.display_name||e.fullname||e.name||e.user_login||e.username||"کاربر",username:e.user_login||e.username||null}:null}}new ul().start();const La=window.ACC_CONFIG||{},ye=(Sa=window.wp)==null?void 0:Sa.apiFetch;ye&&(La.api&&ye.use(ye.createRootURLMiddleware(La.api)),ye.use((p,e)=>{const t=sessionStorage.getItem("acc_token");return t&&(p.headers={...p.headers,Authorization:`Bearer ${t}`}),e(p)}),ye.use(async(p,e)=>{try{return await e(p)}catch(t){throw(t==null?void 0:t.status)===401&&(sessionStorage.removeItem("acc_token"),window.location.href="/login"),t}}));class fl{constructor({eventBus:e,store:t,api:s=null,cache:a=null,auth:i=null,tabbarSelector:n="#acc-tabbar",contentSelector:r="#acc-tab-content",tabConfigRegistry:o,viewResolver:l}){if(!o)throw new Error("TabManager: tabConfigRegistry is required");if(!l)throw new Error("TabManager: viewResolver is required");this.eventBus=e,this.store=t,this.api=s,this.cache=a,this.auth=i,this.tabConfigRegistry=o,this.viewResolver=l,this.tabs=new Map,this.activeTabId=null,this.tabsContainer=document.querySelector(n),this.contentContainer=document.querySelector(r),this.boundEvents=[],this.boundBusEvents=[],this.viewCache=new Map,this.enablePersistence=!0,this.storageKey="acc_tabs_state",this.restoredTabs=null,this._restoreTabsFromStorage(),(!this.tabsContainer||!this.contentContainer)&&console.warn("TabManager: tab containers not found."),this._registerGlobalEvents(),this.restoredTabs&&this._hydrateRestoredTabs()}_registerGlobalEvents(){const e=a=>this.closeTab(a),t=()=>{this.activeTabId&&this.refreshTab(this.activeTabId)},s=({tabId:a,user:i,userId:n})=>{if(!a)return;const r=this.tabs.get(a);if(!r)return;const o=n||(i==null?void 0:i.id)||null;r.userContext=i?{id:o,username:i.username,fullname:i.fullname}:{id:o},this._saveTabsToStorage(),this.refreshTab(a)};this.eventBus.on("tabs:closeById",e),this.eventBus.on("tabs:refreshActive",t),this.eventBus.on("modal:userSelected",s),this.boundBusEvents.push(["tabs:closeById",e],["tabs:refreshActive",t],["modal:userSelected",s])}openTab(e,t={}){var c,d;let s=null,a={};if(typeof e=="string"){const h=e;a=this.tabConfigRegistry.get(h)||{};try{const u=window.acl;if(u&&u._loaded){const f=a.requiredPermission||((d=(c=u.menus)==null?void 0:c.find(m=>m.route===h))==null?void 0:d.required_permission);if(f&&!u.can(f)){this._showDeniedToast(`دسترسی به «${a.title||h}» مجاز نیست`);return}}}catch{}if(s=this.viewResolver.resolve(h,a),!s){console.error(`TabManager: View not found for key "${h}"`);return}}if(typeof e=="function"&&(s=e),!s){console.warn("TabManager.openTab: invalid ViewClass");return}const i=t.title||a.title||s.title||s.viewTitle||s.name||"تب جدید",n=t.key||a.key||s.tabKey||s.name,r=[...this.tabs.values()].find(h=>h.key===n);if(r)return this.activateTab(r.id),r;const o=this._generateTabId(),l={id:o,key:n,title:i,ViewClass:s,view:null,params:t.params||a.params||{},userContext:t.userContext||null,api:t.api||this.api||null,fixed:t.fixed??a.fixed??!1,persist:t.persist??a.persist??!0,config:a};return this.tabs.set(o,l),this._renderTabHeader(l),this.activateTab(o),t.silent||this._saveTabsToStorage(),l}_generateTabId(){return"tab_"+Math.random().toString(36).slice(2,11)}async activateTab(e){if(!this.tabs.has(e))return;this.activeTabId=e;const t=this.tabs.get(e);this._updateTabHeaders(),this.contentContainer&&[...this.contentContainer.children].forEach(s=>{s.dataset&&s.dataset.tabContentId&&(s.style.display="none")}),await this._renderView(t),this._saveTabsToStorage()}closeTab(e){var a,i,n,r,o;const t=this.tabs.get(e);if(!t||t.fixed)return;(i=(a=t.view)==null?void 0:a.destroy)==null||i.call(a),this.viewCache.delete(e),(r=(n=this.tabsContainer)==null?void 0:n.querySelector(`[data-tab-id="${e}"]`))==null||r.remove(),this.tabs.delete(e);const s=(o=this.contentContainer)==null?void 0:o.querySelector(`[data-tab-content-id="${e}"]`);if(s==null||s.remove(),this.activeTabId===e){const l=[...this.tabs.values()];this.activeTabId=l.length?l.at(-1).id:null,this.activeTabId?this.activateTab(this.activeTabId):this.contentContainer&&(this.contentContainer.innerHTML="")}this._updateTabHeaders(),this._saveTabsToStorage()}_renderTabHeader(e){const t=document.createElement("div");t.className="acc-tab",t.dataset.tabId=e.id,t.innerHTML=`<span class="tab-title">${e.title}</span>`,e.fixed?this.tabsContainer.prepend(t):this.tabsContainer.appendChild(t),t.addEventListener("click",()=>this.activateTab(e.id)),this._updateTabHeaders()}_updateTabHeaders(){[...this.tabsContainer.children].forEach(e=>{e.classList.toggle("active",e.dataset.tabId===this.activeTabId)})}async _renderView(e){var i;if(!this.contentContainer)return;const t=()=>{let n=this.contentContainer.querySelector(`[data-tab-content-id="${e.id}"]`);return n||(n=document.createElement("div"),n.dataset.tabContentId=e.id,n.style.width="100%",n.style.height="100%",this.contentContainer.appendChild(n)),n};if(this.viewCache.has(e.id)){const n=this.viewCache.get(e.id);e.view=n;const r=t();if(r.style.display="",typeof n.resume=="function")return n.resume(r);n.container&&n.container;return}if(e.ViewClass||(e.ViewClass=this.viewResolver.resolve(e.key,e.config)),e.ViewClass instanceof Promise&&(e.ViewClass=await e.ViewClass),(i=e.ViewClass)!=null&&i.default&&(e.ViewClass=e.ViewClass.default),typeof e.ViewClass!="function")throw new Error(`tab.ViewClass is not a constructor for tab.key=${e.key}`);const s=t();s.style.display="";const a=new e.ViewClass({eventBus:this.eventBus,store:this.store,tab:e,api:e.api,container:s});e.view=a,await a.render(s),this.viewCache.set(e.id,a)}async refreshTab(e){var n,r,o,l;const t=this.tabs.get(e);if(!t)return;try{(r=(n=t.view)==null?void 0:n.destroy)==null||r.call(n)}catch(c){console.warn("destroy failed",c)}this.viewCache.delete(e),t.view=null;const s=(o=this.contentContainer)==null?void 0:o.querySelector(`[data-tab-content-id="${t.id}"]`);s&&(s.innerHTML="");const a=(l=this.tabsContainer)==null?void 0:l.querySelector(`[data-tab-id="${t.id}"]`),i=a==null?void 0:a.querySelector(".tab-refresh");i&&(i.style.transition="transform .3s",i.style.transform="rotate(360deg)",setTimeout(()=>{i.style.transform=""},350)),await this._renderView(t),this.activeTabId===t.id&&s&&(s.style.display="")}_saveTabsToStorage(){this.enablePersistence&&localStorage.setItem(this.storageKey,JSON.stringify({active:this.activeTabId,tabs:[...this.tabs.values()].filter(e=>e.persist!==!1).map(e=>({key:e.key,title:e.title,params:e.params,userContext:e.userContext,fixed:e.fixed,persist:e.persist}))}))}_restoreTabsFromStorage(){try{const e=localStorage.getItem(this.storageKey);e&&(this.restoredTabs=JSON.parse(e))}catch{console.warn("Tab restore failed")}}_showDeniedToast(e){const t=document.createElement("div");t.style.cssText="position:fixed;top:80px;left:24px;background:#ef4444;color:#fff;padding:12px 20px;border-radius:10px;font-size:13px;font-weight:600;z-index:99999;box-shadow:0 4px 20px rgba(0,0,0,.2);",t.textContent="🚫 "+e,document.body.appendChild(t),setTimeout(()=>t.remove(),3500)}_hydrateRestoredTabs(){const{tabs:e=[],active:t}=this.restoredTabs||{};e.filter(s=>s.persist!==!1).forEach(s=>{this.openTab(s.key,{...s,silent:!0})}),t&&this.tabs.has(t)&&this.activateTab(t)}destroy(){this.boundBusEvents.forEach(([e,t])=>{var s,a;return(a=(s=this.eventBus).off)==null?void 0:a.call(s,e,t)}),this.tabs.forEach(e=>{var t,s;return(s=(t=e.view)==null?void 0:t.destroy)==null?void 0:s.call(t)}),this.tabs.clear(),this.viewCache.clear(),this.activeTabId=null,[...this.tabsContainer.querySelectorAll("[data-tab-id]")].forEach(e=>e.remove()),this.contentContainer.innerHTML=""}getActiveTab(){return this.activeTabId?this.tabs.get(this.activeTabId):null}}const ml=Object.freeze(Object.defineProperty({__proto__:null,default:fl},Symbol.toStringTag,{value:"Module"}))})();
