{"id":159,"date":"2026-03-31T07:17:45","date_gmt":"2026-03-31T07:17:45","guid":{"rendered":"https:\/\/ph-taskportal.zyneventures.com\/?page_id=159"},"modified":"2026-07-09T09:39:02","modified_gmt":"2026-07-09T09:39:02","slug":"quality","status":"publish","type":"page","link":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/quality\/","title":{"rendered":"Quality Executive"},"content":{"rendered":"<style>.kadence-column159_5232d0-98 > .kt-inside-inner-col,.kadence-column159_5232d0-98 > .kt-inside-inner-col:before{border-top-left-radius:0px;border-top-right-radius:0px;border-bottom-right-radius:0px;border-bottom-left-radius:0px;}.kadence-column159_5232d0-98 > .kt-inside-inner-col{column-gap:var(--global-kb-gap-sm, 1rem);}.kadence-column159_5232d0-98 > .kt-inside-inner-col{flex-direction:column;}.kadence-column159_5232d0-98 > .kt-inside-inner-col > .aligncenter{width:100%;}.kadence-column159_5232d0-98 > .kt-inside-inner-col:before{opacity:0.3;}.kadence-column159_5232d0-98{position:relative;}@media all and (max-width: 1024px){.kadence-column159_5232d0-98 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}@media all and (max-width: 767px){.kadence-column159_5232d0-98 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}<\/style>\n<div class=\"wp-block-kadence-column kadence-column159_5232d0-98\"><div class=\"kt-inside-inner-col\"><style>.kb-row-layout-id159_fc574e-ad > .kt-row-column-wrap{align-content:start;}:where(.kb-row-layout-id159_fc574e-ad > .kt-row-column-wrap) > .wp-block-kadence-column{justify-content:start;}.kb-row-layout-id159_fc574e-ad > .kt-row-column-wrap{column-gap:var(--global-kb-gap-md, 2rem);row-gap:var(--global-kb-gap-md, 2rem);padding-top:0px;padding-right:0px;padding-bottom:0px;padding-left:0px;grid-template-columns:minmax(0, 1fr);}.kb-row-layout-id159_fc574e-ad > .kt-row-layout-overlay{opacity:0.30;}@media all and (max-width: 1024px){.kb-row-layout-id159_fc574e-ad > .kt-row-column-wrap{grid-template-columns:minmax(0, 1fr);}}@media all and (max-width: 767px){.kb-row-layout-id159_fc574e-ad > .kt-row-column-wrap{grid-template-columns:minmax(0, 1fr);}}<\/style><div class=\"kb-row-layout-wrap kb-row-layout-id159_fc574e-ad alignnone wp-block-kadence-rowlayout\"><div class=\"kt-row-column-wrap kt-has-1-columns kt-row-layout-equal kt-tab-layout-inherit kt-mobile-layout-row kt-row-valign-top\">\n<style>.kadence-column159_2f2d59-c0 > .kt-inside-inner-col,.kadence-column159_2f2d59-c0 > .kt-inside-inner-col:before{border-top-left-radius:0px;border-top-right-radius:0px;border-bottom-right-radius:0px;border-bottom-left-radius:0px;}.kadence-column159_2f2d59-c0 > .kt-inside-inner-col{column-gap:var(--global-kb-gap-sm, 1rem);}.kadence-column159_2f2d59-c0 > .kt-inside-inner-col{flex-direction:column;}.kadence-column159_2f2d59-c0 > .kt-inside-inner-col > .aligncenter{width:100%;}.kadence-column159_2f2d59-c0 > .kt-inside-inner-col:before{opacity:0.3;}.kadence-column159_2f2d59-c0{position:relative;}@media all and (max-width: 1024px){.kadence-column159_2f2d59-c0 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}@media all and (max-width: 767px){.kadence-column159_2f2d59-c0 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}<\/style>\n<div class=\"wp-block-kadence-column kadence-column159_2f2d59-c0\"><div class=\"kt-inside-inner-col\">\n<style>\n  :root {\n    --primary-blue: #0180FF;\n    --hover-blue: #3499FF;\n    --text-dark: #212529;\n    --text-muted: #8D8C9C;\n    --border-color: #EFEFEF;\n    --bg-light: #F8F9FA;\n  }\n  *, *::before, *::after { box-sizing: border-box;}\n  body { \n    font-family: 'Sora', sans-serif; \n    color: var(--text-dark); \n    background: #fff; \n    min-height: 100vh; \n  }\n\n  \/* \u2500\u2500 PAGE WRAPPER \u2500\u2500 *\/\n  .page-wrapper { max-width: 100%; }\n\n  \/* \u2500\u2500 PAGE TITLE \u2500\u2500 *\/\n  .page-title { \n    font-size: 21px; \n    font-weight: 500; \n    text-transform: uppercase; \n    letter-spacing: 0.5px; \n    margin-bottom: 28px; }\n\n  \/* \u2500\u2500 FILTER CARD \u2500\u2500 *\/\n  .filter-card { \n    background: transparent; \n    border: none; \n    border-radius: 0; \n    padding: 0; \n    margin-bottom: 24px; \n  }\n\n  .filter-row { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }\n  .filter-row + .filter-row { margin-top: 14px; }\n\n  \/* custom select wrapper *\/\n  .sel-wrap { position: relative; flex: 1 1 160px; min-width: 140px; max-width: 220px; }\n  .sel-wrap select {\n    width: 100%; \n    appearance: none; \n    -webkit-appearance: none;\n    padding: 9px 32px 9px 14px; \n    border: 1px solid #DDE2E8; \n    border-radius: 7px;\n    font-family: 'Sora', sans-serif; \n    font-size: 12px; \n    color: var(--text-dark);\n    background: #fff; \n    cursor: pointer; \n    outline: none;\n  }\n  .sel-wrap select:focus { border-color: var(--primary-blue); }\n  .sel-wrap::after {\n    content: ''; \n    position: absolute; \n    right: 12px; \n    top: 50%; \n    transform: translateY(-50%);\n    width: 0; height: 0; \n    border-left: 5px solid transparent; \n    border-right: 5px solid transparent;\n    border-top: 5px solid #8D8C9C; \n    pointer-events: none;\n  }\n\n  \/* \u2500\u2500 CUSTOM MULTI-SELECT \u2500\u2500 *\/\n  .cs-wrap {\n    position: relative;\n    flex: 1 1 160px;\n    min-width: 140px;\n    max-width: 220px;\n  }\n  .cs-wrap.wide { max-width: 240px; }\n  .custom-select-trigger {\n    height: 37px;\n    padding: 0 32px 0 14px;\n    border: 1px solid #DDE2E8;\n    background-color: #fff;\n    border-radius: 7px;\n    font-family: 'Sora', sans-serif;\n    font-size: 12px;\n    color: var(--text-dark);\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    box-sizing: border-box;\n    width: 100%;\n    user-select: none;\n    position: relative;\n    transition: border-color 0.2s;\n    overflow: hidden;\n    white-space: nowrap;\n  }\n  .custom-select-trigger:hover { border-color: var(--primary-blue); }\n  .cs-wrap.open .custom-select-trigger {\n    border-color: var(--primary-blue);\n    border-radius: 7px 7px 0 0;\n    box-shadow: 0 0 0 3px rgba(1,128,255,0.1);\n  }\n  .custom-select-trigger.placeholder-shown { color: #8D8C9C; }\n  .custom-select-trigger .cs-arrow {\n    position: absolute;\n    right: 10px;\n    top: 50%;\n    transform: translateY(-50%);\n    pointer-events: none;\n    color: #8D8C9C;\n    transition: transform 0.2s;\n    flex-shrink: 0;\n  }\n  .cs-wrap.open .custom-select-trigger .cs-arrow { transform: translateY(-50%) rotate(180deg); }\n\n  .cs-label {\n    display: flex;\n    flex-wrap: nowrap;\n    align-items: center;\n    gap: 6px;\n    overflow-x: auto;\n    overflow-y: hidden;\n    white-space: nowrap;\n    width: 100%;\n    min-width: 0;\n    scrollbar-width: thin;\n    -ms-overflow-style: auto;\n  }\n  .cs-label::-webkit-scrollbar { display: block; height: 4px; }\n  .cs-label::-webkit-scrollbar-thumb { background: #ccc; border-radius: 4px; }\n\n  .custom-select-dropdown {\n    display: none;\n    position: absolute;\n    top: 100%;\n    left: 0;\n    right: 0;\n    background: #fff;\n    border: 1px solid var(--primary-blue);\n    border-top: none;\n    border-radius: 0 0 7px 7px;\n    z-index: 9999;\n    overflow-y: auto;\n    max-height: 250px;\n    box-shadow: 0 4px 12px rgba(0,0,0,0.10);\n  }\n  .cs-wrap.open .custom-select-dropdown { display: block; }\n\n  .cs-chips {\n    display: flex;\n    align-items: center;\n    gap: 4px;\n  }\n  .cs-chip {\n    display: inline-flex;\n    align-items: center;\n    background-color: #e8f0fe;\n    border: 1px solid #d2e3fc;\n    border-radius: 4px;\n    padding: 0 8px;\n    font-size: 12px;\n    color: #1967d2;\n    gap: 4px;\n    white-space: nowrap;\n    flex-shrink: 0;\n    height: 26px;\n    margin: 0;\n  }\n  .cs-chip-remove {\n    cursor: pointer;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    width: 14px;\n    height: 14px;\n    border-radius: 50%;\n    color: #5f6368;\n    font-weight: bold;\n    transition: background 0.2s;\n  }\n  .cs-chip-remove:hover { background: #dadce0; color: #202124; }\n\n  .custom-select-option {\n    padding: 8px 12px;\n    font-size: 12px;\n    font-family: 'Sora', sans-serif;\n    color: var(--text-dark);\n    cursor: pointer;\n    white-space: nowrap;\n    overflow: hidden;\n    text-overflow: ellipsis;\n    line-height: 1.4;\n    display: flex;\n    align-items: center;\n    gap: 10px;\n  }\n  .custom-select-option:hover { background: #f0f6ff; color: var(--primary-blue); }\n  .custom-select-option.selected { background: #e8f1ff; color: var(--primary-blue); font-weight: 500; }\n  .custom-select-option .cs-checkbox {\n    width: 16px;\n    height: 16px;\n    border: 1px solid #ced4da;\n    border-radius: 3px;\n    background: #fff;\n    position: relative;\n    flex-shrink: 0;\n    display: block;\n  }\n  .custom-select-option.selected .cs-checkbox {\n    background: var(--primary-blue);\n    border-color: var(--primary-blue);\n  }\n  .custom-select-option.selected .cs-checkbox::after {\n    content: '';\n    position: absolute;\n    left: 5px;\n    top: 2px;\n    width: 4px;\n    height: 8px;\n    border: solid white;\n    border-width: 0 2px 2px 0;\n    transform: rotate(45deg);\n  }\n  .custom-select-option.placeholder-option { color: #999; display: none; }\n  .custom-select-option.placeholder-option .cs-checkbox { display: none; }\n  .custom-select-option.highlighted { background: #f0f6ff; color: var(--primary-blue); }\n\n  \/* Integrated search input inside the trigger *\/\n  .cs-search-input {\n    flex: 1;\n    min-width: 60px;\n    border: 0 !important;\n    outline: 0 !important;\n    box-shadow: none !important;\n    background: transparent !important;\n    font-family: 'Sora', sans-serif;\n    font-size: 12px;\n    color: var(--text-dark);\n    padding: 0;\n    height: 26px;\n    -webkit-appearance: none;\n    -moz-appearance: none;\n    appearance: none;\n  }\n  .cs-search-input:focus,\n  .cs-search-input:active,\n  .cs-search-input:hover,\n  .cs-search-input:focus-visible {\n    border: 0 !important;\n    outline: 0 !important;\n    box-shadow: none !important;\n    background: transparent !important;\n  }\n  .cs-search-input::placeholder { color: #8D8C9C; }\n  .custom-select-trigger:has(.cs-search-input) { cursor: text; }\n\n  .custom-select-search {\n    padding: 8px;\n    border-bottom: 1px solid #EFEFEF;\n    position: sticky;\n    top: 0;\n    background: #fff;\n    z-index: 10;\n  }\n  .custom-select-search input {\n    width: 100%;\n    height: 30px;\n    padding: 0 10px;\n    border: 1px solid #DDE2E8;\n    border-radius: 4px;\n    font-family: 'Sora', sans-serif;\n    font-size: 11px;\n    outline: none;\n    box-sizing: border-box;\n  }\n  .custom-select-search input:focus { border-color: var(--primary-blue); }\n\n  \/* search input *\/\n  .search-box {\n    flex: 1 1 180px; \n    min-width: 140px; \n    max-width: 260px;\n    padding: 9px 14px; \n    border: 1px solid #DDE2E8; \n    border-radius: 7px;\n    font-family: 'Sora', sans-serif; \n    font-size: 12px; \n    color: var(--text-dark); \n    outline: none;\n  }\n  .search-box:focus { border-color: var(--primary-blue); }\n  .search-box::placeholder { color: #bbb; }\n\n  \/* buttons *\/\n  .btn { \n    padding: 9px 22px; \n    border-radius: 7px; \n    font-family: 'Sora', sans-serif; \n    font-size: 12px; \n    font-weight: 400; \n    cursor: pointer; \n    border: none; \n    transition: background 0.2s; \n    white-space: nowrap; \n  }\n  .btn-clear { background: #EBF2FF; color: var(--primary-blue); }\n  .btn-clear:hover { background: #d6e8ff; }\n  .btn-primary { background: var(--primary-blue); color: #fff; }\n  .btn-primary:hover { background: var(--hover-blue); }\n  .btn-csv { background: var(--primary-blue); color: #fff; }\n  .btn-csv:hover { background: var(--hover-blue); }\n  .btn-group { display: flex; gap: 10px; align-items: center; }\n  .btn-group-right { margin-left: auto; }\n\n  \/* \u2500\u2500 TABS \u2500\u2500 *\/\n  .tab-bar { \n    padding-top: 15px;\n    display: flex; \n    border-bottom: 2px solid var(--border-color); \n    margin-bottom: 0; \n    gap: 0; \n  }\n  .tab-item {\n    padding: 12px 22px; \n    font-size: 16px; \n    font-weight: 400; \n    color: var(--text-muted);\n    cursor: pointer; \n    position: relative; \n    white-space: nowrap; \n    user-select: none;\n  }\n  .tab-item.active { color: #212529; font-weight: 500; }\n  .tab-item.active::after {\n    content: ''; \n    position: absolute; \n    bottom: -3px; \n    left: 0; \n    right: 0; \n    height: 3px; \n    background: var(--primary-blue);\n  }\n  .tab-item:hover:not(.active) { color:  var(--text-muted) }\n\n  \/* \u2500\u2500 TABLE WRAPPER \u2500\u2500 *\/\n  .table-wrapper { \n    overflow-x: auto; \n    max-width: 100%;\n    -webkit-overflow-scrolling: touch;\n    margin-top: 0; \n    border: 1px solid var(--border-color); \n    border-top: none; \n    border-radius: 0 0 10px 10px; \n  }\n  table {\n    width: 100%;\n    max-width: 100%;\n    border-collapse: collapse;\n    table-layout: fixed;\n    font-size: 10px;\n  }\n  thead tr { background: #f5f5f5; }\n  thead th {\n    padding: 8px 5px; \n    font-weight: 500; \n    font-size: 9px; \n    text-transform: uppercase;\n    letter-spacing: 0.3px; \n    color: #212529; \n    border-bottom: 1px solid var(--border-color);\n    white-space: normal;\n    word-break: normal;\n    overflow-wrap: anywhere;\n    line-height: 1.25;\n    text-align: left;\n    vertical-align: middle;\n  }\n  tbody tr { border-bottom: 1px solid var(--border-color); transition: background 0.15s; }\n  tbody tr:last-child { border-bottom: none; }\n  tbody tr:hover { background: #f5f5f5; }\n  tbody td { \n    padding: 8px 5px; \n    font-weight: 400;\n    font-size: 9px;\n    line-height: 1.25;\n    color: var(--text-muted); \n    vertical-align: middle; \n    white-space: normal;\n    word-break: break-word;\n    overflow-wrap: anywhere;\n  }\n\n  \/* \u2500\u2500 COLORED BADGES \u2500\u2500 *\/\n  .badge-mi { \n    background: #FFF8E1; \n    color: #B7791F; \n    border: 1px solid #F6E05E; \n    border-radius: 6px; \n    padding: 3px 8px; \n    font-size: 12px; \n    font-weight: 400; \n    display: inline-block; \n  }\n  .badge-cr { \n    background: #FFF0F0; \n    color: #C53030; \n    border: 1px solid #FEB2B2; \n    border-radius: 6px; \n    padding: 3px 8px; \n    font-size: 12px; \n    font-weight: 400; \n    display: inline-block; \n  }\n  .badge-zte { \n    background: #FFF0F6; \n    color: #B83280; \n    border: 1px solid #FBB6CE; \n    border-radius: 6px; \n    padding: 3px 8px; \n    font-size: 12px; \n    font-weight: 400; \n    display: inline-block; \n  }\n\n  \/* name pill *\/\n  .name-pill { \n    background: #E0F7F0; \n    color: #0D6E52; \n    border-radius: 20px; \n    padding: 4px 14px; \n    font-size: 12px; \n    font-weight: 400; \n    display: inline-block; \n  }\n\n  \/* quality color *\/\n  .q-high { color: #1A7A4A; font-weight: 400; }\n  .q-mid  { color: #B7791F; font-weight: 400; }\n  .q-low  { color: #C53030; font-weight: 400; }\n\n  \/* \u2500\u2500 PAGINATION \u2500\u2500 *\/\n  .pagination-footer {\n    display: flex; \n    justify-content: space-between; \n    align-items: center;\n    padding: 16px 4px; \n    font-size: 12px; \n    color: var(--text-muted); \n    flex-wrap: wrap; gap: 10px;\n  }\n  .pagination-controls { display: flex; align-items: center; gap: 6px; }\n  .nav-btn {\n    padding: 6px 14px; \n\/*    border-radius: 6px; *\/\n    cursor: pointer; \n    font-size: 12px;\n    background: transparent; \n    color: var(--text-muted); \n    user-select: none; \n    transition: background 0.2s;\n   \/* border: 1px solid var(--border-color); *\/\n  }\n  .nav-btn:hover:not(.disabled) { background: transparent; }\n  .nav-btn.disabled { opacity: 0.4; pointer-events: none; }\n  .page-num {\n    width: 32px; \n    height: 32px; \n    border-radius: 50%; \n    display: flex; \n    align-items: center; \n    justify-content: center;\n    cursor: pointer; \n    font-size: 12px; \n    background: transparent; \n    color: var(--text-muted);\n\/*    border: 1px solid var(--border-color); *\/\n    transition: background 0.2s;\n  }\n  .page-num.active { background: var(--primary-blue); color: #fff; border-color: var(--primary-blue); }\n  .page-num:hover:not(.active) { background: transparent; }\n\n  \/* loading \/ empty *\/\n  .state-row td { text-align: center; padding: 40px; color: var(--text-muted); font-size: 13px; }\n  .spinner { \n    display: inline-block; \n    width: 18px; height: 18px; \n    border: 2px solid #ddd; \n    border-top-color: var(--primary-blue); \n    border-radius: 50%; \n    animation: spin 0.7s linear infinite; \n    vertical-align: middle; \n    margin-right: 6px; \n  }\n  @keyframes spin { to { transform: rotate(360deg); } }\n\n  \/* \u2500\u2500 RESPONSIVE \u2500\u2500 *\/\n  @media (max-width: 900px) {\n    .page-wrapper { padding: 20px 16px 40px; }\n    .btn-group { margin-left: 0; }\n    .filter-row { gap: 8px; }\n    .sel-wrap { max-width: 100%; }\n    .tab-item { padding: 10px 14px; font-size: 13px; }\n  }\n  @media (max-width: 600px) {\n    .tab-bar { overflow-x: auto; }\n    .btn-group { flex-wrap: wrap; }\n  }\n<\/style>\n\n\n<div class=\"page-wrapper\">\n\n  <!-- TITLE + dynamic tab title -->\n  <div class=\"page-title\" id=\"pageTitle\">EXECUTIVE WISE-QUALITY<\/div>\n\n  <!-- FILTER CARD (dynamic content per tab) -->\n  <div class=\"filter-card\" id=\"filterCard\"><\/div>\n\n  <!-- TABS -->\n  <div class=\"tab-bar\">\n    <div class=\"tab-item active\" data-tab=\"executive\" onclick=\"switchTab('executive')\">Executive Wise<\/div>\n    <div class=\"tab-item\" data-tab=\"qc_executive\" onclick=\"switchTab('qc_executive')\">QC Executive Wise<\/div>\n    <div class=\"tab-item\" data-tab=\"data_wise\" onclick=\"switchTab('data_wise')\">Data Wise<\/div>\n    <div class=\"tab-item\" data-tab=\"client\" onclick=\"switchTab('client')\">Client Wise<\/div>\n  <\/div>\n\n  <!-- TABLE -->\n  <div class=\"table-wrapper\">\n    <table id=\"dataTable\">\n      <thead id=\"tableHead\"><\/thead>\n      <tbody id=\"tableBody\"><tr class=\"state-row\"><td colspan=\"20\"><span class=\"spinner\"><\/span>Loading\u2026<\/td><\/tr><\/tbody>\n    <\/table>\n  <\/div>\n\n  <!-- PAGINATION -->\n  <div class=\"pagination-footer\">\n    <div class=\"pagination-controls\">\n      <span class=\"nav-btn disabled\" id=\"prevBtn\" onclick=\"changePage(-1)\">\u00ab Previous<\/span>\n      <div id=\"pageNumbers\" style=\"display:flex;gap:6px;\"><\/div>\n      <span class=\"nav-btn disabled\" id=\"nextBtn\" onclick=\"changePage(1)\">Next \u00bb<\/span>\n    <\/div>\n    <div id=\"entryInfo\">Showing 0 to 0 of 0 entries<\/div>\n  <\/div>\n<\/div>\n\n<script>\n\/\/ Helper to avoid logical-and escaping issues in WordPress\nfunction both(a, b) { if (a) return b; return a; }\n\n\/\/CONFIGURATION\nconst BASE_URL = 'https:\/\/api-ph-portal.zyneventures.com\/api\/v1';\nconst ENDPOINTS = {\n  USER_ALL:       `${BASE_URL}\/user\/all`,\n  ENTITY:         `${BASE_URL}\/entity\/all`,\n  CATEGORY:       `${BASE_URL}\/category\/all`,\n  CLIENT_ALL:     `${BASE_URL}\/client\/all`,\n  DATA_INDEX:     `${BASE_URL}\/productivity\/data\/indexexecutive`,\n  TABLE_LIST:     `${BASE_URL}\/accountandbenchmark\/tableList`,\n  USER_TEAM:     `${BASE_URL}\/user\/team-members`,\n  INDEX_CLIENT:   `${BASE_URL}\/quality\/index-client`,\n  INDEX_ACCOUNT:  `${BASE_URL}\/quality\/index-account`,\n  INDEX_EXECUTIVE:`${BASE_URL}\/quality\/index-executive`,\n  QC_EXECUTIVE:   `${BASE_URL}\/quality\/qc-index-executive`,\n};\n\nconst MONTHS = ['January','February','March','April','May','June','July','August','September','October','November','December'];\nconst CUR_YEAR = new Date().getFullYear();\nconst YEARS = Array.from({length:10},(_,i)=>CUR_YEAR-i);\n\n\/\/ STATE\nlet activeTab       = 'executive';\nlet pagination      = { page:1, limit:10, total:0, pages:0 };\nlet accountList     = [];  \/\/ from tableList\nlet executiveList   = [];  \/\/ from index-executive\nlet qcExecutiveList = [];  \/\/ from qc-index-executive\nlet dataWiseExecutiveList = [];  \/\/ from \/productivity\/data\/indexexecutive\nlet entityList      = [];  \/\/ from \/entity\/all\nlet categoryList    = [];  \/\/ from \/category\/all\nlet clientAllList   = [];  \/\/ from \/client\/all\nlet filterState     = {};  \/\/ dynamic per tab\n\nfunction getDefaultFilterState(){\n  return {\n    month: '',\n    year: '',\n  };\n}\n\n\/\/ AUTH HELPER\nfunction getHeaders(){\n  const token = localStorage.getItem('TOKEN') || '';\n  return { 'Content-Type':'application\/json', 'Accept':'application\/json', 'Authorization':`Bearer ${token}` };\n}\n\nfunction extractRows(payload){\n  if (Array.isArray(payload)) return payload;\n  if (Array.isArray(payload?.data)) return payload.data;\n  if (Array.isArray(payload?.data?.data)) return payload.data.data;\n  if (Array.isArray(payload?.data?.rows)) return payload.data.rows;\n  if (Array.isArray(payload?.rows)) return payload.rows;\n  return [];\n}\n\nfunction extractPagination(payload, fallbackLimit, fallbackTotal){\n  const paginationInfo = payload?.pagination || payload?.data?.pagination || {};\n  const limitValue = Number(\n    paginationInfo.limit || payload?.limit || payload?.data?.limit || fallbackLimit || 10\n  );\n  const safeLimit = both(Number.isFinite(limitValue), limitValue > 0) ? limitValue : (fallbackLimit || 10);\n\n  const totalValue = Number(\n    paginationInfo.total || payload?.total || payload?.data?.total || fallbackTotal || 0\n  );\n  const safeTotal = both(Number.isFinite(totalValue), totalValue >= 0) ? totalValue : (fallbackTotal || 0);\n\n  const pagesValue = Number(\n    paginationInfo.pages || payload?.pages || payload?.data?.pages || (safeTotal > 0 ? Math.ceil(safeTotal \/ safeLimit) : 1)\n  );\n  const safePages = both(Number.isFinite(pagesValue), pagesValue > 0) ? pagesValue : 1;\n\n  const pageValue = Number(\n    paginationInfo.page || payload?.page || payload?.data?.page || 1\n  );\n  const safePage = both(Number.isFinite(pageValue), pageValue > 0) ? pageValue : 1;\n\n  return { page: safePage, limit: safeLimit, total: safeTotal, pages: safePages };\n}\n\nfunction hasRequestFilters(payload = {}){\n  return Object.keys(payload).some(key => both(\n    !['page', 'limit'].includes(key),\n    both(payload[key] !== '', both(payload[key] !== null, payload[key] !== undefined))\n  ));\n}\n\nfunction hasMeaningfulResponse(payload){\n  const rows = extractRows(payload);\n  if (rows.length > 0) return true;\n  const paginationInfo = extractPagination(payload, pagination.limit, rows.length);\n  return paginationInfo.total > 0;\n}\n\nfunction requestViaXhr(method, url, payload){\n  return new Promise((resolve, reject) => {\n    const xhr = new XMLHttpRequest();\n    xhr.open(method, url, true);\n\n    Object.entries(getHeaders()).forEach(([key, value]) => {\n      xhr.setRequestHeader(key, value);\n    });\n\n    xhr.onload = () => {\n      if (both(xhr.status >= 200, xhr.status < 300)) {\n        try {\n          resolve(JSON.parse(xhr.responseText || '{}'));\n        } catch (error) {\n          reject(error);\n        }\n      } else {\n        reject(new Error(`HTTP ${xhr.status}`));\n      }\n    };\n\n    xhr.onerror = () => reject(new Error('Network request failed'));\n    xhr.send(payload ? JSON.stringify(payload) : null);\n  });\n}\n\nasync function requestWithBodyFallback(url, payload = {}){\n  \/\/ Some of these APIs are implemented as GET endpoints that still expect a JSON body.\n  const shouldRequireDataBeforeAccepting = hasRequestFilters(payload);\n\n  const shouldAcceptResponse = (responsePayload) => {\n    if (!shouldRequireDataBeforeAccepting) return true;\n    return hasMeaningfulResponse(responsePayload);\n  };\n\n  const buildQueryUrl = () => {\n    const params = new URLSearchParams();\n    Object.entries(payload).forEach(([k, v]) => {\n      if (both(v !== undefined, both(v !== null, v !== ''))) params.set(k, String(v));\n    });\n    return params.toString() ? `${url}?${params.toString()}` : url;\n  };\n\n  try {\n    const xhrPayload = await requestViaXhr('GET', url, payload);\n    if (shouldAcceptResponse(xhrPayload)) return xhrPayload;\n  } catch (e) {}\n\n  try {\n    const postRes = await fetch(url, {\n      method: 'POST',\n      headers: getHeaders(),\n      body: JSON.stringify(payload)\n    });\n    if (postRes.ok) {\n      const postPayload = await postRes.json();\n      if (shouldAcceptResponse(postPayload)) return postPayload;\n    }\n  } catch (e) {}\n\n  const getUrl = buildQueryUrl();\n  const getRes = await fetch(getUrl, { method: 'GET', headers: getHeaders() });\n  return await getRes.json();\n}\n\n\/\/ BOOT\nasync function init(){\n  await loadAccountList();\n  await Promise.all([loadExecutiveLists(), loadEntityAndCategoryLists()]);\n  switchTab('executive');\n}\n\nasync function loadAccountList(){\n  try {\n    const r = await fetch(\n      ENDPOINTS.TABLE_LIST, { \n        method:'GET', \n        headers:getHeaders() \n      });\n    const d = await r.json();\n    accountList = extractRows(d);\n  } catch(e){ accountList = []; }\n}\n\nasync function loadExecutiveLists(){\n  try {\n    const [de, dq, ddw] = await Promise.all([\n      fetch(`${ENDPOINTS.INDEX_EXECUTIVE}?page=1&limit=500`, { method:'GET', headers:getHeaders() }).then(r=>r.json()),\n      fetch(`${ENDPOINTS.USER_ALL}?page=1&limit=500`,        { method:'GET', headers:getHeaders() }).then(r=>r.json()),\n      fetch(`${ENDPOINTS.USER_TEAM}?page=1&limit=500`,       { method:'GET', headers:getHeaders() }).then(r=>r.json()),\n    ]);\n    executiveList         = extractRows(de);\n    qcExecutiveList       = extractRows(dq);\n    dataWiseExecutiveList = extractRows(ddw);\n  } catch(e){ executiveList=[]; qcExecutiveList=[]; dataWiseExecutiveList=[]; }\n}\n\nasync function loadEntityAndCategoryLists(){\n  try {\n    const [de, dc, dcl] = await Promise.all([\n      fetch(`${ENDPOINTS.ENTITY}?page=1&limit=500`, { method:'GET', headers:getHeaders() }).then(r=>r.json()),\n      fetch(`${ENDPOINTS.CATEGORY}?page=1&limit=500`, { method:'GET', headers:getHeaders() }).then(r=>r.json()),\n      fetch(`${ENDPOINTS.CLIENT_ALL}?page=1&limit=500`, { method:'GET', headers:getHeaders() }).then(r=>r.json()),\n    ]);\n    const eRows = de?.data?.data || de?.data || [];\n    entityList = Array.isArray(eRows) ? eRows.filter(e=>e.is_active===1||e.is_active===true) : [];\n    const cRows = dc?.data?.data || dc?.data || [];\n    categoryList = Array.isArray(cRows) ? cRows.filter(c=>c.is_active===true||c.is_active===1) : [];\n    \/\/ \/client\/all \u2014 try common response shapes\n    const clRows = dcl?.data?.data || dcl?.data || dcl || [];\n    clientAllList = Array.isArray(clRows) ? clRows : [];\n  } catch(e){ entityList=[]; categoryList=[]; clientAllList=[]; }\n}\n\n\/\/ TAB SWITCHING\nfunction switchTab(tab){\n  activeTab = tab;\n  pagination = { page:1, limit:10, total:0, pages:0 };\n  filterState = getDefaultFilterState();\n\n  document.querySelectorAll('.tab-item').forEach(t=>t.classList.toggle('active', t.dataset.tab===tab));\n\n  const titles = {\n    executive:    'EXECUTIVE WISE-QUALITY',\n    qc_executive: 'QC EXECUTIVE WISE-QUALITY',\n    client:       'CLIENT WISE-QUALITY',\n    data_wise:    'Data Wise - Quality',\n  };\n  document.getElementById('pageTitle').textContent = titles[tab];\n\n  renderFilterForm();\n  fetchData();\n}\n\n\/\/ FILTER FORMS\nfunction monthSelHTML(id='fMonth'){\n  return `<div class=\"sel-wrap\"><select id=\"${id}\">\n    <option value=\"\">Select Month<\/option>\n    ${MONTHS.map((m,i)=>`<option value=\"${i+1}\">${m}<\/option>`).join('')}\n  <\/select><\/div>`;\n}\nfunction yearSelHTML(id='fYear'){\n  return `<div class=\"sel-wrap\"><select id=\"${id}\">\n    <option value=\"\">Year<\/option>\n    ${YEARS.map(y=>`<option value=\"${y}\">${y}<\/option>`).join('')}\n  <\/select><\/div>`;\n}\nfunction accountSelHTML(id='fAccount'){\n  const opts = accountList.map(a=>`\n    <div class=\"custom-select-option\" data-value=\"${a.id}\" onclick=\"csSelect('${id}', '${String(a.id).replace(\/'\/g,\"\\\\'\")}', this, true)\">\n      <div class=\"cs-checkbox\"><\/div><span class=\"opt-label\">${a.name}<\/span>\n    <\/div>`).join('');\n  return `<div class=\"cs-wrap wide\" id=\"csWrapper_${id}\">\n    <input type=\"hidden\" id=\"${id}\" value=\"\">\n    <div class=\"custom-select-trigger placeholder-shown\" onclick=\"csTriggerClick('${id}', event)\">\n      <div class=\"cs-label\">\n        <input type=\"text\" class=\"cs-search-input\" id=\"csInput_${id}\" placeholder=\"Select Accounts\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${id}', this.value)\" onkeydown=\"csKeyDown(event, '${id}')\" onclick=\"csOpenDropdown('${id}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${id}')\">\n      <\/div>\n      <svg class=\"cs-arrow\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg>\n    <\/div>\n    <div class=\"custom-select-dropdown\" id=\"csDrop_${id}\">\n      <div class=\"custom-select-options\">\n        <div class=\"custom-select-option placeholder-option\" data-value=\"\" onclick=\"csSelect('${id}', '', this, true)\"><span class=\"opt-label\">Select Accounts<\/span><\/div>\n        ${opts}\n      <\/div>\n    <\/div>\n  <\/div>`;\n}\nfunction clientSelHTML(id='fClient', clients=[]){\n  \/\/ supports both {client_id, client_name} (from index-client) and {id, name} (from \/client\/all)\n  const opts = clients.map(c=>{\n    const val  = c.id   ?? c.client_id   ?? '';\n    const label= c.name ?? c.client_name ?? '';\n    return `<div class=\"custom-select-option\" data-value=\"${val}\" onclick=\"csSelect('${id}', '${String(val).replace(\/'\/g,\"\\\\'\")}', this, true)\">\n      <div class=\"cs-checkbox\"><\/div><span class=\"opt-label\">${label}<\/span>\n    <\/div>`;\n  }).join('');\n  return `<div class=\"cs-wrap wide\" id=\"csWrapper_${id}\">\n    <input type=\"hidden\" id=\"${id}\" value=\"\">\n    <div class=\"custom-select-trigger placeholder-shown\" onclick=\"csTriggerClick('${id}', event)\">\n      <div class=\"cs-label\">\n        <input type=\"text\" class=\"cs-search-input\" id=\"csInput_${id}\" placeholder=\"Select Clients\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${id}', this.value)\" onkeydown=\"csKeyDown(event, '${id}')\" onclick=\"csOpenDropdown('${id}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${id}')\">\n      <\/div>\n      <svg class=\"cs-arrow\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg>\n    <\/div>\n    <div class=\"custom-select-dropdown\" id=\"csDrop_${id}\">\n      <div class=\"custom-select-options\">\n        <div class=\"custom-select-option placeholder-option\" data-value=\"\" onclick=\"csSelect('${id}', '', this, true)\"><span class=\"opt-label\">Select Clients<\/span><\/div>\n        ${opts}\n      <\/div>\n    <\/div>\n  <\/div>`;\n}\nfunction executiveSelHTML(id='fExecutive', list=[], placeholder='Select Executive'){\n  const opts = list.map(e=>`\n    <div class=\"custom-select-option\" data-value=\"${e.user_id}\" onclick=\"csSelect('${id}', '${String(e.user_id).replace(\/'\/g,\"\\\\'\")}', this, true)\">\n      <div class=\"cs-checkbox\"><\/div><span class=\"opt-label\">${e.pesudo_name}<\/span>\n    <\/div>`).join('');\n  return `<div class=\"cs-wrap\" id=\"csWrapper_${id}\">\n    <input type=\"hidden\" id=\"${id}\" value=\"\">\n    <div class=\"custom-select-trigger placeholder-shown\" onclick=\"csTriggerClick('${id}', event)\">\n      <div class=\"cs-label\">\n        <input type=\"text\" class=\"cs-search-input\" id=\"csInput_${id}\" placeholder=\"${placeholder}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${id}', this.value)\" onkeydown=\"csKeyDown(event, '${id}')\" onclick=\"csOpenDropdown('${id}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${id}')\">\n      <\/div>\n      <svg class=\"cs-arrow\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg>\n    <\/div>\n    <div class=\"custom-select-dropdown\" id=\"csDrop_${id}\">\n      <div class=\"custom-select-options\">\n        <div class=\"custom-select-option placeholder-option\" data-value=\"\" onclick=\"csSelect('${id}', '', this, true)\"><span class=\"opt-label\">${placeholder}<\/span><\/div>\n        ${opts}\n      <\/div>\n    <\/div>\n  <\/div>`;\n}\nfunction dataWiseSelHTML(id='fDataExec', list=[], placeholder='Select Data Wise'){\n  const opts = list.map(e=>{\n    const val = e.id || e.user_id || '';\n    return `<div class=\"custom-select-option\" data-value=\"${val}\" onclick=\"csSelect('${id}', '${String(val).replace(\/'\/g,\"\\\\'\")}', this, true)\">\n      <div class=\"cs-checkbox\"><\/div><span class=\"opt-label\">${e.pesudo_name}<\/span>\n    <\/div>`;\n  }).join('');\n  return `<div class=\"cs-wrap\" id=\"csWrapper_${id}\">\n    <input type=\"hidden\" id=\"${id}\" value=\"\">\n    <div class=\"custom-select-trigger placeholder-shown\" onclick=\"csTriggerClick('${id}', event)\">\n      <div class=\"cs-label\">\n        <input type=\"text\" class=\"cs-search-input\" id=\"csInput_${id}\" placeholder=\"${placeholder}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${id}', this.value)\" onkeydown=\"csKeyDown(event, '${id}')\" onclick=\"csOpenDropdown('${id}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${id}')\">\n      <\/div>\n      <svg class=\"cs-arrow\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg>\n    <\/div>\n    <div class=\"custom-select-dropdown\" id=\"csDrop_${id}\">\n      <div class=\"custom-select-options\">\n        <div class=\"custom-select-option placeholder-option\" data-value=\"\" onclick=\"csSelect('${id}', '', this, true)\"><span class=\"opt-label\">${placeholder}<\/span><\/div>\n        ${opts}\n      <\/div>\n    <\/div>\n  <\/div>`;\n}\nfunction qcExecutiveSelHTML(id='fQCExecutive', list=[], placeholder='Select QC Executive'){\n  const opts = list.map(e=>`\n    <div class=\"custom-select-option\" data-value=\"${e.id || e.user_id}\" onclick=\"csSelect('${id}', '${String(e.id || e.user_id).replace(\/'\/g,\"\\\\'\")}', this, true)\">\n      <div class=\"cs-checkbox\"><\/div><span class=\"opt-label\">${e.pesudo_name}<\/span>\n    <\/div>`).join('');\n  return `<div class=\"cs-wrap\" id=\"csWrapper_${id}\">\n    <input type=\"hidden\" id=\"${id}\" value=\"\">\n    <div class=\"custom-select-trigger placeholder-shown\" onclick=\"csTriggerClick('${id}', event)\">\n      <div class=\"cs-label\">\n        <input type=\"text\" class=\"cs-search-input\" id=\"csInput_${id}\" placeholder=\"${placeholder}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${id}', this.value)\" onkeydown=\"csKeyDown(event, '${id}')\" onclick=\"csOpenDropdown('${id}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${id}')\">\n      <\/div>\n      <svg class=\"cs-arrow\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg>\n    <\/div>\n    <div class=\"custom-select-dropdown\" id=\"csDrop_${id}\">\n      <div class=\"custom-select-options\">\n        <div class=\"custom-select-option placeholder-option\" data-value=\"\" onclick=\"csSelect('${id}', '', this, true)\"><span class=\"opt-label\">${placeholder}<\/span><\/div>\n        ${opts}\n      <\/div>\n    <\/div>\n  <\/div>`;\n}\nfunction entitySelHTML(id='fEntity', list=[]){\n  const opts = list.map(e=>`\n    <div class=\"custom-select-option\" data-value=\"${e.id}\" onclick=\"csSelect('${id}', '${String(e.id).replace(\/'\/g,\"\\\\'\")}', this, false)\">\n      <div class=\"cs-checkbox\"><\/div><span class=\"opt-label\">${e.entity}<\/span>\n    <\/div>`).join('');\n  return `<div class=\"cs-wrap wide\" id=\"csWrapper_${id}\">\n    <input type=\"hidden\" id=\"${id}\" value=\"\">\n    <div class=\"custom-select-trigger placeholder-shown\" onclick=\"csTriggerClick('${id}', event)\">\n      <div class=\"cs-label\">\n        <input type=\"text\" class=\"cs-search-input\" id=\"csInput_${id}\" placeholder=\"Select Entity\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${id}', this.value)\" onkeydown=\"csKeyDown(event, '${id}')\" onclick=\"csOpenDropdown('${id}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${id}')\">\n      <\/div>\n      <svg class=\"cs-arrow\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg>\n    <\/div>\n    <div class=\"custom-select-dropdown\" id=\"csDrop_${id}\">\n      <div class=\"custom-select-options\">\n        <div class=\"custom-select-option placeholder-option\" data-value=\"\" onclick=\"csSelect('${id}', '', this, false)\"><span class=\"opt-label\">Select Entity<\/span><\/div>\n        ${opts}\n      <\/div>\n    <\/div>\n  <\/div>`;\n}\nfunction categorySelHTML(id='fCategory', list=[]){\n  const opts = list.map(c=>`\n    <div class=\"custom-select-option\" data-value=\"${c.id}\" onclick=\"csSelect('${id}', '${String(c.id).replace(\/'\/g,\"\\\\'\")}', this, false)\">\n      <div class=\"cs-checkbox\"><\/div><span class=\"opt-label\">${c.category}<\/span>\n    <\/div>`).join('');\n  return `<div class=\"cs-wrap wide\" id=\"csWrapper_${id}\">\n    <input type=\"hidden\" id=\"${id}\" value=\"\">\n    <div class=\"custom-select-trigger placeholder-shown\" onclick=\"csTriggerClick('${id}', event)\">\n      <div class=\"cs-label\">\n        <input type=\"text\" class=\"cs-search-input\" id=\"csInput_${id}\" placeholder=\"Select Category\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${id}', this.value)\" onkeydown=\"csKeyDown(event, '${id}')\" onclick=\"csOpenDropdown('${id}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${id}')\">\n      <\/div>\n      <svg class=\"cs-arrow\" width=\"14\" height=\"14\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\"><polyline points=\"6 9 12 15 18 9\"\/><\/svg>\n    <\/div>\n    <div class=\"custom-select-dropdown\" id=\"csDrop_${id}\">\n      <div class=\"custom-select-options\">\n        <div class=\"custom-select-option placeholder-option\" data-value=\"\" onclick=\"csSelect('${id}', '', this, false)\"><span class=\"opt-label\">Select Category<\/span><\/div>\n        ${opts}\n      <\/div>\n    <\/div>\n  <\/div>`;\n}\nfunction actionBtnsHTML(leftAlign=false){\n  const cls = leftAlign ? 'btn-group' : 'btn-group btn-group-right';\n  return `<div class=\"${cls}\">\n    <button class=\"btn btn-clear\" onclick=\"clearFilters()\">Clear<\/button>\n    <button class=\"btn btn-primary\" onclick=\"applyFilters()\">Filter<\/button>\n    <button class=\"btn btn-csv\" onclick=\"downloadCSV()\">Download CSV<\/button>\n  <\/div>`;\n}\n\nasync function renderFilterForm(){\n  const card = document.getElementById('filterCard');\n  if(activeTab==='executive'){\n    card.innerHTML = `\n      <div class=\"filter-row\">\n        ${monthSelHTML()} ${yearSelHTML()}\n        ${executiveSelHTML('fExecutive', executiveList)}\n        ${actionBtnsHTML(false)}\n      <\/div>`;\n  } else if(activeTab==='qc_executive'){\n    card.innerHTML = `\n      <div class=\"filter-row\">\n        ${monthSelHTML()} ${yearSelHTML()}\n        ${qcExecutiveSelHTML('fQCExecutive', qcExecutiveList)}\n        ${actionBtnsHTML(false)}\n      <\/div>`;\n  } else if(activeTab==='client'){\n    \/\/ Use \/client\/all data; fall back to index-client if empty\n    const clients = clientAllList.length ? clientAllList : await fetchClientList();\n    card.innerHTML = `\n      <div class=\"filter-row\">\n        ${monthSelHTML()} ${yearSelHTML()}\n        ${clientSelHTML('fClient', clients)}\n        ${categorySelHTML('fCategory', categoryList)}\n        ${entitySelHTML('fEntity', entityList)}\n        <div class=\"btn-group btn-group-right\">\n          <button class=\"btn btn-clear\" onclick=\"clearFilters()\">Clear<\/button>\n          <button class=\"btn btn-primary\" onclick=\"applyFilters()\">Filter<\/button>\n        <\/div>\n      <\/div>\n      <div class=\"filter-row\" style=\"margin-top:12px;\">\n        <button class=\"btn btn-csv\" onclick=\"downloadCSV()\">Download CSV<\/button>\n      <\/div>`;\n  } else if(activeTab==='data_wise'){\n    card.innerHTML = `\n      <div class=\"filter-row\">\n        ${monthSelHTML()} ${yearSelHTML()}\n        ${dataWiseSelHTML('fDataExec', dataWiseExecutiveList, 'Select Data Wise')}\n        ${actionBtnsHTML(false)}\n      <\/div>`;\n  }\n  restoreFilterState();\n}\n\nasync function fetchClientList(){\n  try {\n    const d = await fetch(`${ENDPOINTS.INDEX_CLIENT}?page=1&limit=200`, { method:'GET', headers:getHeaders() }).then(r=>r.json());\n    const rows = extractRows(d);\n    const seen = new Set();\n    return rows.filter(r=>{\n      const key = r.id ?? r.client_id;\n      if(seen.has(key)) return false; seen.add(key); return true;\n    });\n  } catch(e){ return []; }\n}\n\n\/\/ \u2500\u2500 CUSTOM MULTI-SELECT LOGIC \u2500\u2500\nfunction csBuildSearchInput(selectId, placeholder) {\n  const ph = placeholder || '';\n  return `<input type=\"text\" class=\"cs-search-input\" id=\"csInput_${selectId}\" placeholder=\"${ph}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${selectId}', this.value)\" onkeydown=\"csKeyDown(event, '${selectId}')\" onclick=\"csOpenDropdown('${selectId}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${selectId}')\">`;\n}\nfunction csGetPlaceholderText(wrapper) {\n  const ph = wrapper.querySelector('.placeholder-option .opt-label');\n  return ph ? ph.textContent.trim() : 'Select';\n}\nfunction csToggle(selectId, e) {\n  if (e) e.stopPropagation();\n  const wrapper = document.getElementById('csWrapper_' + selectId);\n  const isOpen = wrapper.classList.contains('open');\n  document.querySelectorAll('.cs-wrap.open').forEach(w => { if (w !== wrapper) w.classList.remove('open'); });\n  if (isOpen) {\n    wrapper.classList.remove('open');\n  } else {\n    wrapper.classList.add('open');\n    const searchInput = document.getElementById('csInput_' + selectId);\n    if (searchInput) {\n      searchInput.value = '';\n      csIntegratedFilter(selectId, '');\n      setTimeout(() => searchInput.focus(), 50);\n    } else {\n      csIntegratedFilter(selectId, '');\n    }\n    csHighlightFirst(selectId);\n  }\n}\nfunction csTriggerClick(selectId, e) {\n  e.stopPropagation();\n  csToggle(selectId, e);\n}\nfunction csOpenDropdown(selectId) {\n  const wrapper = document.getElementById('csWrapper_' + selectId);\n  if (!wrapper || wrapper.classList.contains('open')) return;\n  document.querySelectorAll('.cs-wrap.open').forEach(w => { if (w !== wrapper) w.classList.remove('open'); });\n  wrapper.classList.add('open');\n  csHighlightFirst(selectId);\n}\nfunction csFilter(selectId, query) {\n  csIntegratedFilter(selectId, query);\n}\nfunction csIntegratedFilter(selectId, query) {\n  const drop = document.getElementById('csDrop_' + selectId);\n  if (!drop) return;\n  const options = drop.querySelectorAll('.custom-select-option');\n  const q = (query || '').toLowerCase();\n  options.forEach(opt => {\n    const text = opt.textContent.toLowerCase();\n    if (text.includes(q) || opt.classList.contains('placeholder-option')) {\n      opt.style.display = '';\n    } else {\n      opt.style.display = 'none';\n    }\n  });\n  const wrapper = document.getElementById('csWrapper_' + selectId);\n  if (both(wrapper, !wrapper.classList.contains('open'))) {\n    wrapper.classList.add('open');\n  }\n  csHighlightFirst(selectId);\n}\nfunction csHighlightFirst(selectId) {\n  const drop = document.getElementById('csDrop_' + selectId);\n  if (!drop) return;\n  drop.querySelectorAll('.custom-select-option').forEach(o => o.classList.remove('highlighted'));\n  const visible = Array.from(drop.querySelectorAll('.custom-select-option'))\n    .filter(o => both(o.style.display !== 'none', !o.classList.contains('placeholder-option')));\n  if (visible.length > 0) {\n    visible[0].classList.add('highlighted');\n  }\n}\nfunction csKeyDown(e, selectId) {\n  const wrapper = document.getElementById('csWrapper_' + selectId);\n  const drop = document.getElementById('csDrop_' + selectId);\n  if (!wrapper || !drop) return;\n  const isOpen = wrapper.classList.contains('open');\n\n  if (e.key === 'Enter') {\n    e.preventDefault();\n    if (!isOpen) {\n      csToggle(selectId, e);\n    } else {\n      const highlighted = drop.querySelector('.custom-select-option.highlighted');\n      if (highlighted) {\n        const multi = !!wrapper.querySelector('.cs-chips') || wrapper.querySelectorAll('.custom-select-option.selected').length > 1\n          || (highlighted.getAttribute('onclick') || '').includes(', true)');\n        const value = highlighted.dataset.value;\n        \/\/ Determine multi from the option's onclick signature (passed in selHTML)\n        const onclickStr = highlighted.getAttribute('onclick') || '';\n        const isMulti = \/,\\s*true\\s*\\)\/.test(onclickStr);\n        csSelect(selectId, value, highlighted, isMulti);\n      } else {\n        csToggle(selectId, e);\n      }\n    }\n    return;\n  }\n\n  if (e.key === 'ArrowDown') {\n    e.preventDefault();\n    if (!isOpen) {\n      csToggle(selectId, e);\n      return;\n    }\n    const visibleOptions = Array.from(drop.querySelectorAll('.custom-select-option'))\n      .filter(o => both(o.style.display !== 'none', !o.classList.contains('placeholder-option')));\n    if (visibleOptions.length === 0) return;\n    let currentIdx = visibleOptions.findIndex(o => o.classList.contains('highlighted'));\n    visibleOptions.forEach(o => o.classList.remove('highlighted'));\n    currentIdx = (currentIdx + 1) % visibleOptions.length;\n    visibleOptions[currentIdx].classList.add('highlighted');\n    visibleOptions[currentIdx].scrollIntoView({ block: 'nearest' });\n    return;\n  }\n\n  if (e.key === 'ArrowUp') {\n    e.preventDefault();\n    if (!isOpen) {\n      csToggle(selectId, e);\n      return;\n    }\n    const visibleOptions = Array.from(drop.querySelectorAll('.custom-select-option'))\n      .filter(o => both(o.style.display !== 'none', !o.classList.contains('placeholder-option')));\n    if (visibleOptions.length === 0) return;\n    let currentIdx = visibleOptions.findIndex(o => o.classList.contains('highlighted'));\n    visibleOptions.forEach(o => o.classList.remove('highlighted'));\n    if (currentIdx <= 0) currentIdx = visibleOptions.length - 1;\n    else currentIdx -= 1;\n    visibleOptions[currentIdx].classList.add('highlighted');\n    visibleOptions[currentIdx].scrollIntoView({ block: 'nearest' });\n    return;\n  }\n\n  if (e.key === 'Escape') {\n    wrapper.classList.remove('open');\n    return;\n  }\n}\nfunction csSelect(selectId, value, optionEl, multi) {\n  const wrapper = document.getElementById('csWrapper_' + selectId);\n  const input   = document.getElementById(selectId);\n  const trigger = wrapper.querySelector('.custom-select-trigger');\n  const labelEl = trigger.querySelector('.cs-label');\n  const phText = csGetPlaceholderText(wrapper);\n  const hadIntegratedInput = !!document.getElementById('csInput_' + selectId);\n\n  if (value === '') {\n    input.value = '';\n    if (hadIntegratedInput) {\n      labelEl.innerHTML = csBuildSearchInput(selectId, phText);\n    } else {\n      labelEl.innerHTML = optionEl.querySelector('.opt-label').textContent.trim();\n    }\n    trigger.classList.add('placeholder-shown');\n    wrapper.querySelectorAll('.custom-select-option').forEach(o => o.classList.remove('selected'));\n    if (!multi) wrapper.classList.remove('open');\n    return;\n  }\n  if (!multi) {\n    input.value = value;\n    const selectedText = optionEl.querySelector('.opt-label').textContent.trim();\n    if (hadIntegratedInput) {\n      labelEl.innerHTML = csBuildSearchInput(selectId, selectedText);\n    } else {\n      labelEl.textContent = selectedText;\n    }\n    trigger.classList.remove('placeholder-shown');\n    wrapper.querySelectorAll('.custom-select-option').forEach(o => o.classList.remove('selected'));\n    optionEl.classList.add('selected');\n    wrapper.classList.remove('open');\n  } else {\n    let values = input.value ? input.value.split(',') : [];\n    const idx = values.indexOf(String(value));\n    if (idx > -1) { values.splice(idx, 1); optionEl.classList.remove('selected'); }\n    else { values.push(String(value)); optionEl.classList.add('selected'); }\n    input.value = values.join(',');\n    if (values.length === 0) {\n      if (hadIntegratedInput) {\n        labelEl.innerHTML = csBuildSearchInput(selectId, phText);\n      } else {\n        labelEl.innerHTML = phText;\n      }\n      trigger.classList.add('placeholder-shown');\n    } else {\n      trigger.classList.remove('placeholder-shown');\n      const selectedLabels = Array.from(wrapper.querySelectorAll('.custom-select-option.selected'))\n        .map(o => ({ val: o.dataset.value, label: o.querySelector('.opt-label').textContent.trim() }));\n      const chipsHtml = selectedLabels.map(item =>\n        `<div class=\"cs-chip\"><span>${item.label}<\/span><span class=\"cs-chip-remove\" onclick=\"csRemoveChip(event,'${selectId}','${item.val}')\">&times;<\/span><\/div>`\n      ).join('');\n      if (hadIntegratedInput) {\n        labelEl.innerHTML = chipsHtml + csBuildSearchInput(selectId, '');\n      } else {\n        labelEl.innerHTML = `<div class=\"cs-chips\">${chipsHtml}<\/div>`;\n      }\n    }\n    if (wrapper.classList.contains('open')) {\n      const newInput = document.getElementById('csInput_' + selectId);\n      if (newInput) setTimeout(() => newInput.focus(), 0);\n    }\n  }\n}\nfunction csRemoveChip(e, selectId, value) {\n  e.stopPropagation();\n  const wrapper = document.getElementById('csWrapper_' + selectId);\n  const optionEl = wrapper.querySelector(`.custom-select-option[data-value=\"${value}\"]`);\n  if (optionEl) csSelect(selectId, value, optionEl, true);\n}\ndocument.addEventListener('click', function(e){\n  if (!e.target.closest('.cs-wrap')) {\n    document.querySelectorAll('.cs-wrap.open').forEach(w => w.classList.remove('open'));\n  }\n});\n\nfunction restoreFilterState(){\n  if(filterState.month){     const el=document.getElementById('fMonth');      if(el) el.value=filterState.month; }\n  if(filterState.year){      const el=document.getElementById('fYear');       if(el) el.value=filterState.year;  }\n  if(filterState.executive){ const el=document.getElementById('fExecutive');  if(el) el.value=filterState.executive; }\n  if(filterState.qcExec){    const el=document.getElementById('fQCExecutive');if(el) el.value=filterState.qcExec; }\n  if(filterState.dataExec){  const el=document.getElementById('fDataExec');   if(el) el.value=filterState.dataExec; }\n  if(filterState.client){    const el=document.getElementById('fClient');     if(el) el.value=filterState.client; }\n  if(filterState.account){   const el=document.getElementById('fAccount');    if(el) el.value=filterState.account; }\n  if(filterState.category){  const el=document.getElementById('fCategory');   if(el) el.value=filterState.category; }\n  if(filterState.entity){    const el=document.getElementById('fEntity');     if(el) el.value=filterState.entity; }\n}\nfunction readFilterState(){\n  const v = id=>{ const el=document.getElementById(id); return el?el.value:''; };\n  filterState = {\n    month:     v('fMonth'),\n    year:      v('fYear'),\n    executive: v('fExecutive'),\n    qcExec:    v('fQCExecutive'),\n    dataExec:  v('fDataExec'),\n    client:    v('fClient'),\n    account:   v('fAccount'),\n    category:  v('fCategory'),\n    entity:    v('fEntity'),\n  };\n}\nfunction applyFilters(){ readFilterState(); pagination.page=1; fetchData(); }\nfunction clearFilters(){\n  filterState=getDefaultFilterState();\n  ['fMonth','fYear'].forEach(id=>{ const el=document.getElementById(id); if(el) el.value=''; });\n  ['fExecutive','fQCExecutive','fDataExec','fClient','fAccount','fCategory','fEntity'].forEach(id=>{\n    const input = document.getElementById(id);\n    if(input){ input.value=''; }\n    const wrapper = document.getElementById('csWrapper_'+id);\n    if(wrapper){\n      const trigger = wrapper.querySelector('.custom-select-trigger');\n      const labelEl = trigger ? trigger.querySelector('.cs-label') : null;\n      const ph = wrapper.querySelector('.placeholder-option');\n      const phText = ph ? ph.querySelector('.opt-label').textContent.trim() : 'Select';\n      const hadIntegratedInput = !!document.getElementById('csInput_'+id);\n      if(labelEl){\n        if(hadIntegratedInput){\n          labelEl.innerHTML = csBuildSearchInput(id, phText);\n        } else {\n          labelEl.innerHTML = phText;\n        }\n      }\n      if(trigger) trigger.classList.add('placeholder-shown');\n      wrapper.querySelectorAll('.custom-select-option').forEach(o => o.classList.remove('selected'));\n    }\n  });\n  restoreFilterState();\n  pagination.page=1; fetchData();\n}\n\n\/\/ PARSE COMMA-SEPARATED IDS FROM MULTI-SELECT\nfunction parseIds(val){\n  if(!val) return [];\n  return val.split(',').map(v=>parseInt(v.trim())).filter(n=>!isNaN(n));\n}\nfunction idsPayload(ids){ return ids.length===1 ? ids[0] : ids; }\n\n\/\/ BUILDS A QUERY STRING URL \u2014 only appends keys whose values are non-empty\nfunction buildGetUrl(base, params){\n  const qs = new URLSearchParams();\n  Object.entries(params).forEach(([k,v])=>{\n    if(both(v !== '', both(v !== null, v !== undefined))) qs.set(k, String(v));\n  });\n  const q = qs.toString();\n  return q ? `${base}?${q}` : base;\n}\n\n\/\/ API FETCH\nfunction buildActiveTabUrl(page, limit) {\n  if(activeTab==='executive'){\n    const execIds = parseIds(filterState.executive);\n    return buildGetUrl(ENDPOINTS.INDEX_EXECUTIVE, {\n      year:        filterState.year  || '',\n      month:       filterState.month || '',\n      assigned_to: execIds.length ? execIds.join(',') : '',\n      page,\n      limit,\n    });\n  }\n  if(activeTab==='qc_executive'){\n    const qcIds = parseIds(filterState.qcExec);\n    return buildGetUrl(ENDPOINTS.QC_EXECUTIVE, {\n      year:        filterState.year  || '',\n      month:       filterState.month || '',\n      assigned_to: qcIds.length ? qcIds.join(',') : '',\n      page,\n      limit,\n    });\n  }\n  if(activeTab==='client'){\n    const clientIds = parseIds(filterState.client);\n    return buildGetUrl(ENDPOINTS.INDEX_CLIENT, {\n      year:        filterState.year     || '',\n      month:       filterState.month    || '',\n      page,\n      limit,\n      category_id: filterState.category || '',\n      client_id:   clientIds.length ? clientIds.join(',') : '',\n    });\n  }\n  if(activeTab==='data_wise'){\n    const dataExecIds = parseIds(filterState.dataExec);\n    return buildGetUrl(ENDPOINTS.DATA_INDEX, {\n      year:        filterState.year  || '',\n      month:       filterState.month || '',\n      assigned_to: dataExecIds.length ? dataExecIds.join(',') : '',\n      page,\n      limit,\n    });\n  }\n  return '';\n}\n\nasync function fetchAllExportRows() {\n  const CSV_LIMIT = 500;\n  let page = 1;\n  let totalPages = 1;\n  let allRows = [];\n\n  do {\n    const url = buildActiveTabUrl(page, CSV_LIMIT);\n    if (!url) break;\n    const d = await fetch(url, { method:'GET', headers:getHeaders() }).then(r => r.json());\n    const rows = extractRows(d);\n    allRows = allRows.concat(rows);\n    const pg = extractPagination(d, CSV_LIMIT, rows.length);\n    totalPages = pg.pages || 1;\n    page++;\n  } while (page <= totalPages);\n\n  const search = (filterState.search || '').toLowerCase();\n  if (search) {\n    allRows = allRows.filter(r => JSON.stringify(r).toLowerCase().includes(search));\n  }\n  return allRows;\n}\n\nasync function fetchData(){\n  setLoading();\n  try {\n    const url = buildActiveTabUrl(pagination.page, pagination.limit);\n    if (!url) return;\n    const d = await fetch(url, { method:'GET', headers:getHeaders() }).then(r=>r.json());\n    const rows = extractRows(d);\n    pagination = { ...pagination, ...extractPagination(d, pagination.limit, rows.length) };\n    renderTable(rows);\n    renderPagination();\n  } catch(e){\n    console.error(e);\n    document.getElementById('tableBody').innerHTML = `<tr class=\"state-row\"><td colspan=\"20\">Error loading data. Please try again.<\/td><\/tr>`;\n  }\n}\n\nfunction setLoading(){\n  document.getElementById('tableBody').innerHTML = `<tr class=\"state-row\"><td colspan=\"20\"><span class=\"spinner\"><\/span>Loading\u2026<\/td><\/tr>`;\n}\n\n\/** PHP productivityexecutive\/data-list.blade.php \u2014 productivity % *\/\nfunction phpDataListProductivity(row) {\n  const bench = parseFloat(row.benchMarkHrs ?? 0);\n  if (!Number.isFinite(bench) || bench <= 0) return '0.00';\n  const adHoc = parseFloat(row.adHochrs ?? 0) || 0;\n  const completed = parseFloat(row.completedHrs ?? 0) || 0;\n  return (((adHoc + completed) \/ bench) * 100).toFixed(2);\n}\n\n\/** PHP quality\/client-wise.blade.php \u2014 WTG columns CR\u00d72, Total Error % \/ Quality use CR\u00d73 *\/\nfunction phpClientWiseRowMetrics(row) {\n  const MI = parseInt(row.MI ?? row.minor_errors ?? row.minor ?? 0, 10) || 0;\n  const CR = parseInt(row.CR ?? row.critical_errors ?? row.critical ?? 0, 10) || 0;\n  const ZTE = parseInt(row.ZTE ?? row.zte_errors ?? row.zte ?? 0, 10) || 0;\n  const qcDos = parseFloat(row.qcCompletedDos ?? row.qc_completed ?? 0) || 0;\n  const minor_wtg = row.minor_wtg ?? row.minorWtg ?? MI * 1;\n  const critical_wtg = row.critical_wtg ?? row.criticalWtg ?? CR * 2;\n  const zte_wtg = row.zte_wtg ?? row.zteWtg ?? ZTE * 5;\n  let totalErrPct = parseFloat(row.total_error_percentage ?? row.totalErrorPercentage);\n  let qualityPct = parseFloat(row.quality_percentage ?? row.qualityPercentage);\n  if (qcDos > 0) {\n    totalErrPct = ((MI * 1 + CR * 3 + ZTE * 5) \/ qcDos) * 100;\n    qualityPct = 100 - totalErrPct;\n  }\n  return {\n    minor_wtg,\n    critical_wtg,\n    zte_wtg,\n    totalErrPct: Number.isFinite(totalErrPct) ? totalErrPct : 0,\n    qualityPct: Number.isFinite(qualityPct) ? qualityPct : 100,\n  };\n}\n\n\/** PHP data-list.blade.php \u2014 quality % from MI\/CR\/ZTE (same as API quality fields) *\/\nfunction phpDataListQuality(row) {\n  const mi = parseFloat(row.MI ?? 0) || 0;\n  const cr = parseFloat(row.CR ?? 0) || 0;\n  const zte = parseFloat(row.ZTE ?? 0) || 0;\n  const qcDos = parseFloat(row.qcCompletedDos ?? 0) || 0;\n  if (qcDos <= 0) {\n    const fallback = row.quality ?? row.quality_percentage ?? row.qaulity ?? 100;\n    return parseFloat(fallback).toFixed(2);\n  }\n  const totalError = ((mi * 1 + cr * 2 + zte * 5) \/ qcDos) * 100;\n  return (100 - totalError).toFixed(2);\n}\n\nfunction resolveRowQuality(row) {\n  const candidates = [row.quality, row.quality_percentage, row.qaulity];\n  for (const val of candidates) {\n    if (both(val !== undefined, both(val !== null, val !== ''))) {\n      return parseFloat(val).toFixed(2);\n    }\n  }\n  return phpDataListQuality(row);\n}\n\n\/\/ TABLE HEADERS\nconst HEADS = {\n  executive: ['A. Manager','T. Lead','Pseudo Name','DOS Completed','QC Completed','QC %','Minor','Critical','ZTE','Total Errors','Minor WTG','Critical WTG','ZTE WTG','Total Error %','Quality'],\n  qc_executive: ['A. Manager','T. Lead','Pseudo Name','DOS Assign','DOS Completed','DOS %','Minor','Critical','ZTE','Total Errors','Minor WTG','Critical WTG','ZTE WTG','Total Error Ratio','Gernal Error Ratio','Quality'],\n  client:  ['Client','Account','DOS Completed','QC Completed','QC %','Minor','Critical','ZTE','Total Errors','Minor WTG','Critical WTG','ZTE WTG','Total Error %','Quality'],\n  data_wise: ['A. Manager','T. Lead','Pseudo Name','Assigned DOS','Completed DOS','Productivity %','QC Completed DOS','QC Completed Hrs','Assigned Hrs','Completed Hrs','Ad Hoc Hrs','Benchmark Hrs','Productivity','Quality','Quality %'],\n};\n\nfunction renderTable(rows){\n  const safeRows = Array.isArray(rows) ? rows : [];\n  const heads = HEADS[activeTab];\n  document.getElementById('tableHead').innerHTML = `<tr>${heads.map(h=>`<th>${h}<\/th>`).join('')}<\/tr>`;\n\n  const search = (filterState.search||'').toLowerCase();\n  const filtered = search\n    ? safeRows.filter(r=>JSON.stringify(r).toLowerCase().includes(search))\n    : safeRows;\n\n  if(!filtered.length){\n    document.getElementById('tableBody').innerHTML = `<tr class=\"state-row\"><td colspan=\"${heads.length}\">No data found.<\/td><\/tr>`;\n    updateEntryInfo(0,0,0);\n    return;\n  }\n\n  const start = (pagination.page-1)*pagination.limit+1;\n  const end   = Math.min(pagination.page*pagination.limit, pagination.total);\n  updateEntryInfo(start, end, pagination.total);\n\n  let html='';\n  filtered.forEach(row=>{\n    if(activeTab==='executive'){\n      html+=`<tr>\n        <td>${row.manager||'-'}<\/td>\n        <td>${row.team_lead||'-'}<\/td>\n        <td><span class=\"name-pill\">${row.pesudo_name||'-'}<\/span><\/td>\n        <td>${row.dos_completed??row.assigned_dos??row.dos_assign??'-'}<\/td>\n        <td>${row.qc_completed??0}<\/td>\n        <td>${fmt(row.qc_percentage)}%<\/td>\n        <td><span class=\"badge-mi\">MI (${row.minor_errors??0})<\/span><\/td>\n        <td><span class=\"badge-cr\">CR (${row.critical_errors??0})<\/span><\/td>\n        <td><span class=\"badge-zte\">ZTE(${row.zte_errors??0})<\/span><\/td>\n        <td>${row.total_errors??0}<\/td>\n        <td>${fmt(row.minor_wtg)}<\/td>\n        <td>${fmt(row.critical_wtg)}<\/td>\n        <td>${fmt(row.zte_wtg)}<\/td>\n        <td>${fmt(row.total_error_percentage??row.total_error_ratio)}%<\/td>\n        <td class=\"${qClass(row.quality_percentage)}\">${fmt(row.quality_percentage)}%<\/td>\n      <\/tr>`;\n    } else if(activeTab==='qc_executive'){\n      \/\/ PHP qc-executive-wise.blade.php: WTG columns use the DOUBLED weightage\n      \/\/   MINOR WTG    = MIWtg  = (reverse_error_count * 1 * 2) \/ qc_submit_dos\n      \/\/   CRITICAL WTG = CRWtg  = (reverse_error_count * 2 * 2) \/ qc_submit_dos\n      \/\/   ZTE WTG      = ZTEWtg = (reverse_error_count * 5 * 2) \/ qc_submit_dos\n      \/\/ (minor_wtg\/critical_wtg\/zte_wtg are the non-doubled Executive-Wise values; do NOT use here)\n      html+=`<tr>\n        <td>${row.manager||'-'}<\/td>\n        <td>${row.team_lead||'-'}<\/td>\n        <td><span class=\"name-pill\">${row.pesudo_name||'-'}<\/span><\/td>\n        <td>${row.dos_assign??row.assigned_dos??'-'}<\/td>\n        <td>${row.dos_completed??'-'}<\/td>\n        <td>${fmt(row.dos_percentage??0)}%<\/td>\n        <td><span class=\"badge-mi\">MI (${row.minor_errors??0})<\/span><\/td>\n        <td><span class=\"badge-cr\">CR (${row.critical_errors??0})<\/span><\/td>\n        <td><span class=\"badge-zte\">ZTE(${row.zte_errors??0})<\/span><\/td>\n        <td>${row.total_errors??0}<\/td>\n        <td>${fmt(row.MIWtg??row.minor_wtg)}<\/td>\n        <td>${fmt(row.CRWtg??row.critical_wtg)}<\/td>\n        <td>${fmt(row.ZTEWtg??row.zte_wtg)}<\/td>\n        <td>${fmt(row.total_error_ratio??row.total_error_percentage)}<\/td>\n        <td>${fmt(row.general_error_ratio??0)}<\/td>\n        <td class=\"${qClass(row.quality_percentage)}\">${fmt(row.quality_percentage)}%<\/td>\n      <\/tr>`;\n    } else if(activeTab==='client'){\n      const cw = phpClientWiseRowMetrics(row);\n      html+=`<tr>\n        <td>${row.name??row.client_name??row.clientName??'-'}<\/td>\n        <td>${row.account_name??row.accountName??row.account??'-'}<\/td>\n        <td>${row.completedDos??row.dos_completed??row.dosCompleted??row.no_of_dos??row.noOfDos??'-'}<\/td>\n        <td>${row.qcCompletedDos??row.qc_completed??row.qcCompleted??row.qc_dos??'-'}<\/td>\n        <td>${fmt(row.qc_percentage??row.qcPercentage??0)}%<\/td>\n        <td><span class=\"badge-mi\">MI (${row.MI??row.minor_errors??row.minorErrors??row.minor??0})<\/span><\/td>\n        <td><span class=\"badge-cr\">CR (${row.CR??row.critical_errors??row.criticalErrors??row.critical??0})<\/span><\/td>\n        <td><span class=\"badge-zte\">ZTE(${row.ZTE??row.zte_errors??row.zteErrors??row.zte??0})<\/span><\/td>\n        <td>${row.total_errors??row.totalErrors??row.total_error??0}<\/td>\n        <td>${fmt(cw.minor_wtg)}<\/td>\n        <td>${fmt(cw.critical_wtg)}<\/td>\n        <td>${fmt(cw.zte_wtg)}<\/td>\n        <td>${fmt(cw.totalErrPct)}%<\/td>\n        <td class=\"${qClass(cw.qualityPct)}\">${fmt(cw.qualityPct)}%<\/td>\n      <\/tr>`;\n    } else if(activeTab==='data_wise'){\n      const prodPct = phpDataListProductivity(row);\n      const qualPct = resolveRowQuality(row);\n      html+=`<tr>\n        <td>${row.a_manager||row.manager||'-'}<\/td>\n        <td>${row.team_lead||'-'}<\/td>\n        <td><span class=\"name-pill\">${row.pesudo_name||'-'}<\/span><\/td>\n        <td>${row.assignedDos??row.dos_assign??row.assigned_dos??'-'}<\/td>\n        <td>${row.completedDos??row.dos_completed??'-'}<\/td>\n        <td>${prodPct}%<\/td>\n        <td>${row.qcCompletedDos??row.qc_completed??0}<\/td>\n        <td>${fmt(row.qcCompletedHrs??0)}<\/td>\n        <td>${fmt(row.assignedHrs??0)}<\/td>\n        <td>${fmt(row.completedHrs??0)}<\/td>\n        <td>${fmt(row.adHochrs??0)}<\/td>\n        <td>${fmt(row.benchMarkHrs??0)}<\/td>\n        <td>${prodPct}<\/td>\n        <td>${qualPct}%<\/td>\n        <td class=\"${qClass(qualPct)}\">${qualPct}%<\/td>\n      <\/tr>`;\n    }\n  });\n  document.getElementById('tableBody').innerHTML = html;\n}\n\n\/\/  PAGINATION\nfunction renderPagination(){\n  const { page, pages } = pagination;\n  const prev = document.getElementById('prevBtn');\n  const next = document.getElementById('nextBtn');\n  prev.className = page<=1 ? 'nav-btn disabled' : 'nav-btn';\n  next.className = page>=pages ? 'nav-btn disabled' : 'nav-btn';\n\n  const container = document.getElementById('pageNumbers');\n  container.innerHTML='';\n\n  \/\/ show max 7 page buttons with ellipsis\n  let nums=[];\n  if(pages<=7){ for(let i=1;i<=pages;i++) nums.push(i); }\n  else {\n    nums=[1];\n    if(page>3) nums.push('\u2026');\n    for(let i=Math.max(2,page-1);i<=Math.min(pages-1,page+1);i++) nums.push(i);\n    if(page<pages-2) nums.push('\u2026');\n    nums.push(pages);\n  }\n  nums.forEach(n=>{\n    if(n==='\u2026'){\n      const s=document.createElement('span');\n      s.textContent='\u2026'; s.style.cssText='display:flex;align-items:center;padding:0 4px;color:#aaa;';\n      container.appendChild(s);\n    } else {\n      const s=document.createElement('span');\n      s.className=n===page?'page-num active':'page-num';\n      s.textContent=n;\n      s.onclick=()=>goToPage(n);\n      container.appendChild(s);\n    }\n  });\n}\n\nfunction goToPage(n){ pagination.page=n; fetchData(); }\nfunction changePage(dir){\n  const np=pagination.page+dir;\n  if(np<1||np>pagination.pages) return;\n  pagination.page=np; fetchData();\n}\nfunction updateEntryInfo(s,e,t){\n  document.getElementById('entryInfo').textContent=`Showing ${s} to ${e} of ${t} entries`;\n}\n\n\/\/ CSV DOWNLOAD\nfunction csvEscape(val) {\n  const s = val === null || val === undefined ? '' : String(val);\n  return '\"' + s.replace(\/\"\/g, '\"\"') + '\"';\n}\n\nfunction rowToCsvLine(row, tab) {\n  let cells = [];\n  if (tab === 'executive') {\n    cells = [\n      row.manager||'-', row.team_lead||'-', row.pesudo_name||'-',\n      row.dos_completed??row.assigned_dos??row.dos_assign??'-',\n      row.qc_completed??0, fmt(row.qc_percentage)+'%',\n      `MI (${row.minor_errors??0})`, `CR (${row.critical_errors??0})`, `ZTE(${row.zte_errors??0})`,\n      row.total_errors??0, fmt(row.minor_wtg), fmt(row.critical_wtg), fmt(row.zte_wtg),\n      fmt(row.total_error_percentage??row.total_error_ratio)+'%', fmt(row.quality_percentage)+'%',\n    ];\n  } else if (tab === 'qc_executive') {\n    cells = [\n      row.manager||'-', row.team_lead||'-', row.pesudo_name||'-',\n      row.dos_assign??row.assigned_dos??'-', row.dos_completed??'-', fmt(row.dos_percentage??0)+'%',\n      `MI (${row.minor_errors??0})`, `CR (${row.critical_errors??0})`, `ZTE(${row.zte_errors??0})`,\n      row.total_errors??0, fmt(row.MIWtg??row.minor_wtg), fmt(row.CRWtg??row.critical_wtg), fmt(row.ZTEWtg??row.zte_wtg),\n      fmt(row.total_error_ratio??row.total_error_percentage), fmt(row.general_error_ratio??0),\n      fmt(row.quality_percentage)+'%',\n    ];\n  } else if (tab === 'client') {\n    const cw = phpClientWiseRowMetrics(row);\n    cells = [\n      row.name??row.client_name??row.clientName??'-',\n      row.account_name??row.accountName??row.account??'-',\n      row.completedDos??row.dos_completed??row.dosCompleted??row.no_of_dos??row.noOfDos??'-',\n      row.qcCompletedDos??row.qc_completed??row.qcCompleted??row.qc_dos??'-',\n      fmt(row.qc_percentage??row.qcPercentage??0)+'%',\n      `MI (${row.MI??row.minor_errors??row.minorErrors??row.minor??0})`,\n      `CR (${row.CR??row.critical_errors??row.criticalErrors??row.critical??0})`,\n      `ZTE(${row.ZTE??row.zte_errors??row.zteErrors??row.zte??0})`,\n      row.total_errors??row.totalErrors??row.total_error??0,\n      fmt(cw.minor_wtg), fmt(cw.critical_wtg), fmt(cw.zte_wtg),\n      fmt(cw.totalErrPct)+'%', fmt(cw.qualityPct)+'%',\n    ];\n  } else if (tab === 'data_wise') {\n    const prodPct = phpDataListProductivity(row);\n    const qualPct = resolveRowQuality(row);\n    cells = [\n      row.a_manager||row.manager||'-', row.team_lead||'-', row.pesudo_name||'-',\n      row.assignedDos??row.dos_assign??row.assigned_dos??'-',\n      row.completedDos??row.dos_completed??'-',\n      prodPct+'%', row.qcCompletedDos??row.qc_completed??0,\n      fmt(row.qcCompletedHrs??0), fmt(row.assignedHrs??0), fmt(row.completedHrs??0),\n      fmt(row.adHochrs??0), fmt(row.benchMarkHrs??0), prodPct,\n      qualPct+'%', qualPct+'%',\n    ];\n  }\n  return cells.map(csvEscape).join(',');\n}\n\nasync function downloadCSV(){\n  const btn = document.querySelector('.btn-csv');\n  const orig = btn ? btn.textContent : '';\n  if (btn) { btn.disabled = true; btn.textContent = 'Downloading...'; }\n  try {\n    const rows = await fetchAllExportRows();\n    if (!rows.length) { alert('No data to download.'); return; }\n    const heads = HEADS[activeTab];\n    let csv = heads.map(csvEscape).join(',') + '\\n';\n    rows.forEach(row => { csv += rowToCsvLine(row, activeTab) + '\\n'; });\n    const a = document.createElement('a');\n    a.href = 'data:text\/csv;charset=utf-8,' + encodeURIComponent(csv);\n    a.download = `quality_${activeTab}_${Date.now()}.csv`;\n    a.click();\n  } catch (e) {\n    console.error(e);\n    alert('Failed to download CSV. Please try again.');\n  } finally {\n    if (btn) { btn.disabled = false; btn.textContent = orig; }\n  }\n}\n\n\/\/ HELPERS\nfunction fmt(v){ \n  if(v===null||v===undefined||v==='') \n  return '0.00'; const n=parseFloat(v); \n  return isNaN(n)?v:n.toFixed(2); \n}\nfunction qClass(v){ \n  const n=parseFloat(v)||0; \n  return n>=99?'q-high':n>=90?'q-mid':'q-low'; \n}\n\n\/\/ BOOT \n  init();\n<\/script>\n<\/div><\/div>\n\n<\/div><\/div><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>EXECUTIVE WISE-QUALITY Executive Wise QC Executive Wise Data Wise Client Wise Loading\u2026 \u00ab Previous Next \u00bb Showing 0 to 0 of 0 entries<\/p>\n","protected":false},"author":2,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"_kad_post_transparent":"disable","_kad_post_title":"hide","_kad_post_layout":"fullwidth","_kad_post_sidebar_id":"","_kad_post_content_style":"unboxed","_kad_post_vertical_padding":"hide","_kad_post_feature":"hide","_kad_post_feature_position":"","_kad_post_header":false,"_kad_post_footer":false,"_kad_post_classname":"","footnotes":""},"class_list":["post-159","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages\/159","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/comments?post=159"}],"version-history":[{"count":28,"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages\/159\/revisions"}],"predecessor-version":[{"id":1243,"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages\/159\/revisions\/1243"}],"wp:attachment":[{"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/media?parent=159"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}