{"id":202,"date":"2026-03-31T11:28:09","date_gmt":"2026-03-31T11:28:09","guid":{"rendered":"https:\/\/ph-taskportal.zyneventures.com\/?page_id=202"},"modified":"2026-07-09T06:15:13","modified_gmt":"2026-07-09T06:15:13","slug":"assigned-assignment","status":"publish","type":"page","link":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/assigned-assignment\/","title":{"rendered":"Assigned Assigment"},"content":{"rendered":"<style>.kadence-column202_177a44-6f > .kt-inside-inner-col,.kadence-column202_177a44-6f > .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-column202_177a44-6f > .kt-inside-inner-col{column-gap:var(--global-kb-gap-sm, 1rem);}.kadence-column202_177a44-6f > .kt-inside-inner-col{flex-direction:column;}.kadence-column202_177a44-6f > .kt-inside-inner-col > .aligncenter{width:100%;}.kadence-column202_177a44-6f > .kt-inside-inner-col:before{opacity:0.3;}.kadence-column202_177a44-6f{position:relative;}@media all and (max-width: 1024px){.kadence-column202_177a44-6f > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}@media all and (max-width: 767px){.kadence-column202_177a44-6f > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}<\/style>\n<div class=\"wp-block-kadence-column kadence-column202_177a44-6f\"><div class=\"kt-inside-inner-col\"><style>.kb-row-layout-id202_2879f3-e7 > .kt-row-column-wrap{align-content:start;}:where(.kb-row-layout-id202_2879f3-e7 > .kt-row-column-wrap) > .wp-block-kadence-column{justify-content:start;}.kb-row-layout-id202_2879f3-e7 > .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-id202_2879f3-e7 > .kt-row-layout-overlay{opacity:0.30;}@media all and (max-width: 1024px){.kb-row-layout-id202_2879f3-e7 > .kt-row-column-wrap{grid-template-columns:minmax(0, 1fr);}}@media all and (max-width: 767px){.kb-row-layout-id202_2879f3-e7 > .kt-row-column-wrap{grid-template-columns:minmax(0, 1fr);}}<\/style><div class=\"kb-row-layout-wrap kb-row-layout-id202_2879f3-e7 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-column202_aeb9ae-02 > .kt-inside-inner-col,.kadence-column202_aeb9ae-02 > .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-column202_aeb9ae-02 > .kt-inside-inner-col{column-gap:var(--global-kb-gap-sm, 1rem);}.kadence-column202_aeb9ae-02 > .kt-inside-inner-col{flex-direction:column;}.kadence-column202_aeb9ae-02 > .kt-inside-inner-col > .aligncenter{width:100%;}.kadence-column202_aeb9ae-02 > .kt-inside-inner-col:before{opacity:0.3;}.kadence-column202_aeb9ae-02{position:relative;}@media all and (max-width: 1024px){.kadence-column202_aeb9ae-02 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}@media all and (max-width: 767px){.kadence-column202_aeb9ae-02 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}<\/style>\n<div class=\"wp-block-kadence-column kadence-column202_aeb9ae-02\"><div class=\"kt-inside-inner-col\">\n<style data-wp-block-html=\"css\">\n:root {\n    --primary-blue: #0180FF;\n    --hover-blue: #3499FF;\n    --text-dark: #212529;\n    --text-muted: #8D8C9C;\n    --border-color: #EFEFEF;\n    --success-green: #1E8E3E;\n    --bg-light: #F7F8FA;\n    --white: #ffffff;\n}\n\n*, *::before, *::after {\n    box-sizing: border-box;\n}\n\nhtml, body {\n    overflow-x: hidden;\n    max-width: 100%;\n}\n    \nbody {\n    font-family: 'Sora', sans-serif;\n    background-color: var(--white);\n    color: var(--text-dark);\n}\n\n.ph-title,\n.filter-grid,\n.action-row,\n.tabs-nav,\n.table-container,\n.pagination-container {\n    max-width: 100%;\n}\n    \n.ph-title {\n    font-size: 21px;\n    font-weight: 500;\n    text-transform: uppercase;\n    margin-bottom: 21px;\n    letter-spacing: 0.5px;\n}\n    \n\/* Form Grid *\/\n.filter-grid {\n    display: grid;\n    grid-template-columns: repeat(4, minmax(0, 1fr));\n    gap: 15px;\n    margin-bottom: 20px;\n    max-width: 100%;\n}\n    \n.form-group {\n    display: flex;\n    flex-direction: column;\n}\n    \n.form-group label {\n    font-size: 12px;\n    margin-bottom: 6px;\n    color: var(--text-dark);\n}\n    \n.form-control {\n    height: 38px;\n    padding: 0 12px;\n    border: 1px solid #ced4da;\n    border-radius: 6px;\n    font-family: 'Sora';\n    font-size: 12px;\n    outline: none;\n    box-sizing: border-box;\n    width: 100%;\n    transition: all 0.2s;\n}\n    \n.form-control:focus {\n    background-color: #fff;\n    border-color: var(--primary-blue);\n    box-shadow: 0 0 0 3px rgba(1, 128, 255, 0.1);\n}\n\nselect.form-control {\n    appearance: auto;\n    -webkit-appearance: menulist;\n    -moz-appearance: menulist;\n    padding-right: 28px;\n    cursor: pointer;\n    background-color: #fff;\n}\n\nselect.form-control option {\n    color: var(--text-dark);\n    font-weight: 400;\n}\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    \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    \n.cs-search-input::placeholder {\n    color: #70757a;\n}\n    \n.custom-select-trigger:has(.cs-search-input) {\n    cursor: text;\n}\n    \n\/* Custom Select *\/\n.custom-select-wrapper {\n    position: relative;\n    width: 100%;\n}\n    \n.custom-select-trigger {\n    height: 38px;\n    padding: 0 36px 0 12px;\n    border: 1px solid #ced4da;\n    background-color: #fff;\n    border-radius: 6px;\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: all 0.2s;\n    overflow: hidden;\n    white-space: nowrap;\n}\n    \n.custom-select-trigger:hover {\n    border-color: var(--primary-blue);\n}\n    \n.custom-select-wrapper.open .custom-select-trigger {\n    border-color: var(--primary-blue);\n    border-radius: 6px 6px 0 0;\n    box-shadow: 0 0 0 3px rgba(1, 128, 255, 0.1);\n}\n    \n.custom-select-trigger.placeholder-shown {\n    color: #70757a;\n}\n    \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    \n.custom-select-wrapper.open .custom-select-trigger .cs-arrow {\n    transform: translateY(-50%) rotate(180deg);\n}\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 6px 6px;\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    \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    \n.cs-label::-webkit-scrollbar {\n    display: block;\n    height: 4px;\n}\n    \n.cs-label::-webkit-scrollbar-thumb {\n    background: #ccc;\n    border-radius: 4px;\n}\n    \n.custom-select-wrapper.open .custom-select-dropdown {\n    display: block;\n}\n    \n\/* Chips\/Badges styling *\/\n.cs-chips {\n    display: flex;\n    align-items: center;\n    gap: 4px;\n}\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    \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    \n.cs-chip-remove:hover {\n    background: #dadce0;\n    color: #202124;\n}\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    \n.custom-select-option:hover {\n    background: #f0f6ff;\n    color: var(--primary-blue);\n}\n    \n.custom-select-option.selected {\n    background: #e8f1ff;\n    color: var(--primary-blue);\n    font-weight: 500;\n}\n    \n.custom-select-option.highlighted {\n    background: #f0f6ff;\n    color: var(--primary-blue);\n}\n    \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: none;\n}\n    \n.custom-select-wrapper.multi .custom-select-option .cs-checkbox {\n    display: block;\n}\n    \n.custom-select-option.selected .cs-checkbox {\n    background: var(--primary-blue);\n    border-color: var(--primary-blue);\n}\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    \n.custom-select-option.placeholder-option {\n    color: #999;\n}\n    \n\/* Search input in dropdown *\/\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    \n.custom-select-search input {\n    width: 100%;\n    height: 30px;\n    padding: 0 10px;\n    border: 1px solid #ced4da;\n    border-radius: 4px;\n    font-family: 'Sora', sans-serif;\n    font-size: 11px;\n    outline: none;\n    box-sizing: border-box;\n}\n    \n.custom-select-search input:focus {\n    border-color: var(--primary-blue);\n}\n    \n\/* Buttons Row \u00e2\u20ac\u201d fills full width with equal flex *\/\n.action-row {\n    display: flex;\n    flex-wrap: wrap;\n    gap: 10px;\n    margin-bottom: 25px;\n    width: 100%;\n}\n    \n.action-row .btn {\n    flex: 1 1 0;\n    min-width: 90px;\n}\n    \n.btn {\n    height: 38px;\n    padding: 0 12px;\n    border-radius: 6px;\n    font-size: 12px;\n    cursor: pointer;\n    border: none;\n    transition: 0.2s;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    white-space: nowrap;\n    box-sizing: border-box;\n}\n    \n.btn-clear {\n    background: #D0D7F3;\n    color: #555;\n}\n    \n.btn-filter {\n    background: var(--primary-blue);\n    color: white;\n}\n    \n.btn-blue {\n    background: var(--primary-blue);\n    color: white;\n}\n    \n.btn:hover {\n    opacity: 0.88;\n}\n    \n\/* Tabs *\/\n.tabs-nav {\n    border-bottom: 1px solid var(--border-color);\n    margin-bottom: 20px;\n    display: flex;\n    flex-wrap: wrap;\n    gap: 20px;\n    max-width: 100%;\n}\n    \n.tab-link {\n    padding: 12px 5px;\n    font-size: 15px;\n    color: var(--text-muted);\n    cursor: pointer;\n    position: relative;\n    white-space: normal;\n}\n    \n.tab-link.active {\n    color: var(--text-dark);\n    font-weight: 500;\n}\n    \n.tab-link.active::after {\n    content: '';\n    position: absolute;\n    bottom: -1px;\n    left: 0;\n    width: 100%;\n    height: 3px;\n    background: var(--primary-blue);\n}\n    \n\/* Table *\/\n.table-container {\n    overflow-x: hidden;\n    max-width: 100%;\n    border: 1px solid var(--border-color);\n    border-radius: 6px;\n}\n    \ntable {\n    width: 100%;\n    max-width: 100%;\n    border-collapse: collapse;\n    font-size: 11px;\n    table-layout: fixed;\n    white-space: normal;\n}\n    \nth {\n    background: var(--bg-light);\n    font-size: 11px;\n    font-weight: 500;\n    padding: 10px 8px;\n    text-align: left;\n    color: var(--text-dark);\n    border-bottom: 1px solid var(--border-color);\n    text-transform: uppercase;\n    white-space: normal;\n    word-break: break-word;\n    line-height: 1.3;\n}\n    \ntd {\n    font-size: 11px;\n    font-weight: 400;\n    padding: 10px 8px;\n    border-bottom: 1px solid #f2f2f2;\n    color: #8D8C9C;\n    white-space: normal;\n    word-break: break-word;\n    overflow-wrap: anywhere;\n    line-height: 1.35;\n    vertical-align: middle;\n}\n    \n\/* Pencil Edit icon button *\/\n.edit-icon-btn {\n    background: none;\n    border: none;\n    cursor: pointer;\n    padding: 5px 8px;\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    gap: 5px;\n    color: var(--text-muted);\n    border-radius: 4px;\n    transition: background 0.15s, color 0.15s;\n    line-height: 1;\n    font-family: 'Sora', sans-serif;\n    font-size: 12px;\n    font-weight: 400;\n}\n    \n.edit-icon-btn:hover {\n    background: #eef3ff;\n    color: var(--primary-blue);\n}\n    \n.edit-icon-btn svg {\n    width: 15px;\n    height: 15px;\n    stroke: currentColor;\n    fill: none;\n    stroke-width: 1.8;\n    stroke-linecap: round;\n    stroke-linejoin: round;\n    display: block;\n}\n    \n.edit-icon-btn .edit-label {\n    font-size: 12px;\n    line-height: 1;\n}\n    \n.action-stack {\n    display: flex;\n    flex-direction: column;\n    gap: 8px;\n    align-items: flex-start;\n}\n    \n.status-pill {\n    display: inline-flex;\n    align-items: center;\n    justify-content: center;\n    border-radius: 999px;\n    padding: 4px 12px;\n    font-size: 12px;\n    line-height: 1;\n}\n    \n.status-pill.approved {\n    background: #D3EFE8;\n    color: #268A76;\n}\n    \n.status-pill.not-approved {\n    background: #FDE4E4;\n    color: #B91C1C;\n}\n    \n.status-pill.pending {\n    background: transparent;\n    color: var(--text-muted);\n    padding: 0;\n    border-radius: 0;\n}\n    \n\/* Table entity\/client colored badge *\/\n.entity-badge {\n    display: inline-block;\n    padding: 4px 10px;\n    font-size: 11px;\n    font-weight: 500;\n    line-height: 1.2;\n    white-space: normal;\n    word-break: break-word;\n    border-radius: 20px;\n    background: #D0FDF5;\n    color: #0E7F6E;\n}\n    \n\/* Pagination *\/\n.pagination-container {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-top: 30px;\n    padding-bottom: 40px;\n    gap: 20px;\n    flex-wrap: wrap;\n}\n    \n.pagination-controls {\n    display: flex;\n    align-items: center;\n    gap: 5px;\n    flex-wrap: wrap;\n}\n    \n.page-item {\n    min-width: 32px;\n    height: 32px;\n    padding: 0 6px;\n    box-sizing: border-box;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    cursor: pointer;\n    border-radius: 16px;\n    font-size: 12px;\n    color: var(--text-muted);\n    transition: background 0.2s;\n}\n    \n.page-item.active {\n    background-color: var(--primary-blue);\n    color: white;\n}\n    \n.nav-link {\n    cursor: pointer;\n    color: var(--text-dark);\n    font-size: 12px;\n    padding: 5px 8px;\n    user-select: none;\n}\n    \n.nav-link.disabled {\n    color: #ccc;\n    pointer-events: none;\n}\n    \n\/* Modal Overlays *\/\n.modal-overlay {\n    position: fixed;\n    top: 0;\n    left: 0;\n    width: 100%;\n    height: 100%;\n    background: rgba(0, 0, 0, 0.5);\n    display: none;\n    justify-content: center;\n    align-items: flex-start;\n    z-index: 1000;\n    padding: 40px 20px;\n    overflow-y: auto;\n    box-sizing: border-box;\n}\n    \n.modal-content {\n    background: white;\n    width: 100%;\n    max-width: 900px;\n    border-radius: 6px;\n    padding: 25px;\n    position: relative;\n    margin-bottom: 20px;\n}\n    \n.modal-header {\n    font-size: 21px;\n    font-weight: 500;\n    margin-bottom: 20px;\n    color: #333;\n}\n    \n.modal-grid {\n    display: grid;\n    grid-template-columns: repeat(4, 1fr);\n    gap: 15px;\n}\n    \n.modal-footer {\n    margin-top: 25px;\n    display: flex;\n    justify-content: flex-end;\n    gap: 15px;\n}\n    \n.required::after {\n    content: \" *\";\n    color: red;\n}\n    \n\/* Hidden CSV file input *\/\n#csvImportInput {\n    display: none;\n}\n    \n\/* Custom Date Picker *\/\n.date-wrapper {\n    position: relative;\n}\n    \n.date-wrapper input[type=\"text\"] {\n    width: 100%;\n    padding: 10px 36px 10px 14px;\n    border: 1px solid #E0E0E0;\n    border-radius: 6px;\n    font-family: 'Sora', sans-serif;\n    font-size: 12px;\n    color: var(--text-dark);\n    outline: none;\n    cursor: pointer;\n    background: #fff;\n    transition: border-color 0.2s;\n    user-select: none;\n    height: 38px;\n    box-sizing: border-box;\n}\n    \n.date-wrapper input[type=\"text\"]:focus {\n    border-color: var(--primary-blue);\n}\n    \n.date-wrapper input[type=\"text\"]::placeholder {\n    color: #aaa;\n}\n    \n.date-wrapper .cal-icon {\n    position: absolute;\n    right: 12px;\n    top: 50%;\n    transform: translateY(-50%);\n    pointer-events: none;\n    color: #8D8C9C;\n}\n    \n.dp-dropdown {\n    display: none;\n    position: absolute;\n    top: 100%;\n    left: 0;\n    background: #fff;\n    border: 1px solid #EFEFEF;\n    border-radius: 12px;\n    z-index: 9999;\n    margin-top: 8px;\n    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);\n    overflow: hidden;\n    min-width: 0;\n    max-width: min(600px, calc(100vw - 32px));\n    width: min(600px, calc(100vw - 32px));\n}\n    \n.dp-dropdown.open {\n    display: flex;\n}\n    \n.dp-dropdown.align-right {\n    left: auto;\n    right: 0;\n}\n    \n.dp-backdrop {\n    display: none;\n    position: fixed;\n    inset: 0;\n    z-index: 1999;\n}\n    \n.dp-backdrop.show {\n    display: block;\n}\n    \n.dp-presets {\n    width: 140px;\n    border-right: 1px solid #EFEFEF;\n    display: flex;\n    flex-direction: column;\n    background: #fff;\n    padding: 8px 0;\n}\n    \n.dp-preset-item {\n    padding: 10px 16px;\n    font-size: 13px;\n    color: #3c4043;\n    cursor: pointer;\n    transition: all 0.2s;\n    white-space: nowrap;\n}\n    \n.dp-preset-item:hover {\n    background: #F1F3F4;\n}\n    \n.dp-preset-item.active {\n    background: var(--primary-blue);\n    color: #fff;\n    font-weight: 500;\n}\n    \n\/* Two-month panel container *\/\n.dp-calendars-wrap {\n    flex: 1;\n    display: flex;\n    flex-direction: column;\n    padding: 8px 10px 8px;\n    min-width: 0;\n}\n    \n.dp-months-row {\n    display: flex;\n    gap: 0;\n    flex: 1;\n}\n    \n.dp-calendar {\n    flex: 1;\n    padding: 0 6px;\n    min-width: 0;\n}\n    \n.dp-calendar+.dp-calendar {\n    border-left: 1px solid #EFEFEF;\n}\n    \n.dp-cal-header {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    margin-bottom: 6px;\n}\n    \n.dp-cal-title {\n    font-size: 14px;\n    font-weight: 600;\n    color: #3c4043;\n    margin: 0;\n    text-align: center;\n    flex: 1;\n}\n    \n.dp-nav-btn {\n    background: none;\n    border: none;\n    cursor: pointer;\n    padding: 6px;\n    color: #5f6368;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    border-radius: 50%;\n    transition: background 0.2s;\n}\n    \n.dp-nav-btn:hover {\n    background: #F1F3F4;\n}\n    \n.dp-nav-btn.dp-nav-hidden {\n    visibility: hidden;\n    pointer-events: none;\n}\n    \n.dp-weekdays {\n    display: grid;\n    grid-template-columns: repeat(7, 1fr);\n    margin-bottom: 2px;\n}\n    \n.dp-weekday {\n    text-align: center;\n    font-size: 11px;\n    font-weight: 500;\n    color: #8D8C9C;\n    padding: 2px 0;\n}\n    \n.dp-days {\n    display: grid;\n    grid-template-columns: repeat(7, 1fr);\n    gap: 1px;\n}\n    \n.dp-day {\n    text-align: center;\n    padding: 2px 0;\n    font-size: 11px;\n    border-radius: 50%;\n    cursor: pointer;\n    color: var(--text-dark);\n    transition: background 0.15s, color 0.15s;\n    aspect-ratio: 1;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n}\n    \n.dp-day:hover {\n    background: #e8f1ff;\n    color: var(--primary-blue);\n}\n    \n.dp-day.today {\n    background: #F1F3F4;\n    border-radius: 50% !important;\n    font-weight: 600;\n}\n    \n.dp-day.selected {\n    background: var(--primary-blue) !important;\n    color: #fff !important;\n    font-weight: 600;\n    border-radius: 4px !important;\n    z-index: 2;\n}\n    \n.dp-day.in-range,\n.dp-day.hover-range {\n    background: #E8F0FE !important;\n    color: #3c4043;\n    border-radius: 0;\n}\n    \n.dp-day.selected-start,\n.dp-day.row-start,\n.dp-day.hover-start {\n    border-top-left-radius: 4px !important;\n    border-bottom-left-radius: 4px !important;\n}\n    \n.dp-day.selected-end,\n.dp-day.row-end,\n.dp-day.hover-end {\n    border-top-right-radius: 4px !important;\n    border-bottom-right-radius: 4px !important;\n}\n    \n.dp-day.selected-start.selected-end {\n    border-radius: 4px !important;\n}\n    \n.dp-weekday {\n    text-align: center;\n    font-size: 11px;\n    font-weight: 600;\n    color: #333;\n    padding: 4px 0;\n}\n    \n.dp-day.other-month {\n    color: #ccc;\n}\n    \n.dp-day.other-month:hover {\n    background: #f5f5f5;\n    color: #aaa;\n}\n    \n.dp-footer {\n    display: flex;\n    justify-content: space-between;\n    align-items: center;\n    gap: 12px;\n    margin-top: 10px;\n    padding: 12px 16px;\n    border-top: 1px solid #EFEFEF;\n}\n    \n.dp-range-display {\n    font-size: 12px;\n    color: #333;\n    font-weight: 500;\n}\n    \n.dp-btn-clear {\n    padding: 8px 16px;\n    border-radius: 8px;\n    font-size: 12px;\n    font-family: 'Sora', sans-serif;\n    background: #F1F3F4;\n    color: #3c4043;\n    border: none;\n    cursor: pointer;\n    font-weight: 500;\n    transition: background 0.2s;\n}\n    \n.dp-btn-clear:hover {\n    background: #E8EAED;\n}\n    \n.dp-btn-apply {\n    padding: 8px 24px;\n    border-radius: 8px;\n    font-size: 12px;\n    font-family: 'Sora', sans-serif;\n    background: var(--primary-blue);\n    color: #fff;\n    border: none;\n    cursor: pointer;\n    font-weight: 500;\n    transition: background 0.2s;\n}\n    \n.dp-btn-apply:hover {\n    background: var(--hover-blue);\n}\n    \n@media (max-width: 750px) {\n    .dp-dropdown {\n        flex-direction: column;\n        min-width: 0;\n        width: calc(100vw - 32px);\n        left: 50%;\n        transform: translateX(-50%);\n        max-height: 85vh;\n        overflow-y: auto;\n    }\n    \n    .dp-presets {\n        width: 100%;\n        border-right: none;\n        border-bottom: 1px solid #EFEFEF;\n        padding: 4px 0;\n        display: flex;\n        flex-wrap: wrap;\n    }\n    \n    .dp-preset-item {\n        padding: 6px 10px;\n        font-size: 11px;\n        flex: 1 1 auto;\n        text-align: center;\n        min-width: 80px;\n    }\n    \n    .dp-months-row {\n        flex-direction: column;\n        gap: 10px;\n    }\n    \n    .dp-calendar+.dp-calendar {\n        border-left: none;\n        border-top: 1px solid #EFEFEF;\n        padding-top: 8px;\n    }\n    \n    .dp-calendars-wrap {\n        padding: 6px 8px 8px;\n    }\n    \n    .dp-cal-header {\n        margin-bottom: 6px;\n    }\n    \n    .dp-day {\n        padding: 5px 0;\n        font-size: 11px;\n    }\n    \n    .dp-footer {\n        margin-top: 8px;\n        padding-top: 8px;\n    }\n}\n    \n@media (max-width: 480px) {\n    .dp-dropdown {\n        position: fixed;\n        top: 50%;\n        left: 50% !important;\n        transform: translate(-50%, -50%) !important;\n        width: calc(100vw - 24px);\n        max-width: 400px;\n        max-height: 92vh;\n        overflow-y: auto;\n        z-index: 3000;\n    }\n    \n    .dp-calendars-wrap {\n        padding: 6px 6px 6px;\n    }\n    \n    .dp-day {\n        font-size: 11px;\n        padding: 4px 0;\n    }\n    \n    .dp-cal-title {\n        font-size: 12px;\n    }\n    \n    .dp-footer {\n        margin-top: 6px;\n        padding-top: 6px;\n    }\n    \n    .dp-btn-clear,\n    .dp-btn-apply {\n        padding: 5px 10px;\n        font-size: 11px;\n    }\n}\n    \n\/* Responsive *\/\n@media (max-width: 1200px) {\n    .filter-grid {\n        grid-template-columns: repeat(3, minmax(0, 1fr));\n    }\n\n    .modal-grid {\n        grid-template-columns: repeat(3, 1fr);\n    }\n}\n\n@media (max-width: 1024px) {\n    .modal-grid {\n        grid-template-columns: repeat(3, 1fr);\n    }\n}\n    \n@media (max-width: 768px) {\n    body {\n        padding: 12px;\n    }\n    \n    .modal-grid {\n        grid-template-columns: repeat(2, 1fr);\n    }\n    \n    .filter-grid {\n        grid-template-columns: repeat(2, 1fr);\n    }\n    \n    .pagination-container {\n        justify-content: center;\n    }\n    \n    .action-row {\n        gap: 8px;\n    }\n    \n    .btn {\n        font-size: 11px;\n    }\n    \n    .tabs-nav {\n        gap: 16px;\n    }\n}\n    \n@media (max-width: 480px) {\n    .modal-grid {\n        grid-template-columns: 1fr 1fr;\n    }\n    \n    .filter-grid {\n        grid-template-columns: 1fr;\n    }\n    \n    .tabs-nav {\n        gap: 12px;\n    }\n    \n    .action-row .btn {\n        flex: 1 1 calc(50% - 5px);\n    }\n    \n    \/* Pagination Optimization for Mobile *\/\n    .pagination-controls {\n        flex-direction: column;\n        gap: 12px;\n        width: 100%;\n    }\n    \n    #prevBtn {\n        order: 1;\n        width: 100%;\n        text-align: center;\n        border: 1px solid var(--border-color);\n        border-radius: 6px;\n        padding: 8px 12px;\n        box-sizing: border-box;\n    }\n    \n    #pageNumbers {\n        order: 2;\n        justify-content: center;\n    }\n    \n    #nextBtn {\n        order: 3;\n        width: 100%;\n        text-align: center;\n        border: 1px solid var(--border-color);\n        border-radius: 6px;\n        padding: 8px 12px;\n        box-sizing: border-box;\n    }\n    \n    #entryInfo {\n        width: 100% !important;\n        text-align: center;\n    }\n}\n\n.adhoc-modal-content {\n    background: white;\n    width: 100%;\n    max-width: 460px;\n    border-radius: 12px;\n    padding: 32px 28px 28px;\n    position: relative;\n    margin-bottom: 20px;\n}\n.adhoc-modal-title {\n    font-size: 18px;\n    font-weight: 600;\n    margin-bottom: 22px;\n    color: #212529;\n}\n.adhoc-form-group {\n    display: flex;\n    flex-direction: column;\n    margin-bottom: 16px;\n}\n.adhoc-form-group label {\n    font-size: 13px;\n    font-weight: 500;\n    margin-bottom: 6px;\n    color: #212529;\n}\n.adhoc-form-group label .req {\n    color: red;\n    margin-left: 2px;\n}\n.adhoc-form-control {\n    height: 42px;\n    padding: 0 12px;\n    border: 1px solid #ced4da;\n    border-radius: 8px;\n    font-family: 'Sora', sans-serif;\n    font-size: 13px;\n    outline: none;\n    box-sizing: border-box;\n    width: 100%;\n    color: #212529;\n    background: #fff;\n}\n.adhoc-form-control:focus {\n    border-color: var(--primary-blue);\n    box-shadow: 0 0 0 3px rgba(1,128,255,0.1);\n}\n.adhoc-form-control:disabled {\n    background: #f5f5f5;\n    color: #aaa;\n    cursor: not-allowed;\n}\n.adhoc-form-control.select-control {\n    appearance: none;\n    -webkit-appearance: none;\n    background-image: url(\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='14' height='14' fill='none' stroke='%238D8C9C' stroke-width='2' viewBox='0 0 24 24'%3E%3Cpolyline points='6 9 12 15 18 9'\/%3E%3C\/svg%3E\");\n    background-repeat: no-repeat;\n    background-position: right 12px center;\n    padding-right: 36px;\n}\n.adhoc-modal-footer {\n    display: flex;\n    justify-content: flex-end;\n    gap: 12px;\n    margin-top: 24px;\n}\n.adhoc-btn-close {\n    height: 40px;\n    padding: 0 24px;\n    border-radius: 8px;\n    font-size: 13px;\n    cursor: pointer;\n    border: none;\n    background: transparent;\n    color: #555;\n    font-family: 'Sora', sans-serif;\n    font-weight: 500;\n}\n.adhoc-btn-close:hover { background: #f0f0f0; }\n.adhoc-btn-submit {\n    height: 40px;\n    padding: 0 32px;\n    border-radius: 8px;\n    font-size: 13px;\n    cursor: pointer;\n    border: none;\n    background: var(--primary-blue);\n    color: white;\n    font-family: 'Sora', sans-serif;\n    font-weight: 500;\n}\n.adhoc-btn-submit:hover { opacity: 0.88; }\n\n\/* Ad hoc bulk approve \u2014 PHP list.blade.php checkbox column *\/\n.adhoc-select-col {\n    width: 44px;\n    text-align: center;\n    vertical-align: middle;\n}\n\n.adhoc-bulk-checkbox {\n    width: 16px;\n    height: 16px;\n    cursor: pointer;\n    accent-color: var(--primary-blue);\n}\n<\/style>\n\n<script data-wp-block-html=\"js\">\n\/\/ Helpers to avoid logical-and escaping issues in WordPress\nfunction both(a, b) {\n  if (a) return b;\n  return a;\n}\n\nfunction every() {\n  const args = Array.prototype.slice.call(arguments);\n  for (let i = 0; i < args.length; i++) {\n    if (!args[i]) return args[i];\n  }\n  return args[args.length - 1];\n}\n\nfunction formatTableHours(hours) {\n  if (!every(hours !== null, hours !== undefined, hours !== \"\", !isNaN(parseFloat(hours)))) {\n    return \"-\";\n  }\n  return parseFloat(hours).toFixed(2);\n}\n\nfunction isWpEditorPreview() {\n  try {\n    if (both(document.body, document.body.classList.contains(\"block-editor-iframe__body\"))) {\n      return true;\n    }\n    if (document.querySelector(\".editor-styles-wrapper\")) {\n      return true;\n    }\n    if (both(window.frameElement, window.frameElement.classList.contains(\"wp-block-iframe-sandbox\"))) {\n      return true;\n    }\n    if (window.parent !== window) {\n      try {\n        if (window.parent.document.querySelector(\".block-editor-page\")) {\n          return true;\n        }\n      } catch (e) {\n        return true;\n      }\n    }\n  } catch (e) {}\n  return false;\n}\n\nfunction safeGetStorage(key) {\n  try {\n    return localStorage.getItem(key);\n  } catch (e) {\n    return null;\n  }\n}\n\nfunction safeRemoveStorage(key) {\n  try {\n    localStorage.removeItem(key);\n  } catch (e) {}\n}\n\nfunction getAuthToken() {\n  const fromStorage = safeGetStorage(\"TOKEN\");\n  if (fromStorage) return fromStorage;\n  const match = document.cookie.match(\/(?:^|;\\s*)TOKEN=([^;]+)\/);\n  return match ? decodeURIComponent(match[1].trim()) : \"\";\n}\n  \n  \/** ENDPOINTS CONFIGURATION **\/\n  const BASE_URL = \"https:\/\/api-ph-portal.zyneventures.com\/api\/v1\";\n  const LOGIN_URL = \"https:\/\/portal.precisionhub.com\/index.php\/login\/\";\n  const ENDPOINTS = {\n    UNSUBMITTED: `${BASE_URL}\/work_assignment\/un-submitted`,\n    ADHOC_ALL: `${BASE_URL}\/ad_hoc_assignment\/all`,\n    USERS: `${BASE_URL}\/user\/table\/list`,\n    USERS_ALL: `${BASE_URL}\/user\/all`,\n    CLIENTS: `${BASE_URL}\/client\/all`,\n    ENTITIES: `${BASE_URL}\/entity\/all`,\n    CATEGORIES: `${BASE_URL}\/category\/table\/list`,\n    PROJECTS: `${BASE_URL}\/project\/all`,\n    ACCOUNTS: `${BASE_URL}\/accountandbenchmark\/tableList`,\n    UPDATE_ASSIGNMENT: `${BASE_URL}\/work_assignment\/update`,\n    UPDATE_ADHOC: `${BASE_URL}\/ad_hoc_assignment\/update`,\n    GET_ASSIGNMENT: `${BASE_URL}\/work_assignment\/detail`,\n    GET_ADHOC: `${BASE_URL}\/ad_hoc_assignment\/detail`,\n    INSURANCES: `${BASE_URL}\/insurance\/all`,\n    PROJECT_TYPES: `${BASE_URL}\/projecttype\/all`,\n    ACCOUNT_DETAIL: `${BASE_URL}\/accountandbenchmark\/detail`,\n    SUBMIT_LOG: `${BASE_URL}\/work_assignment_log\/add`,\n    TEAM_MEMBERS: `${BASE_URL}\/user\/team-members`,\n    ADHOC_ADD: `${BASE_URL}\/ad_hoc_assignment\/add`,\n    ADHOC_APPROVE_BULK: `${BASE_URL}\/ad_hoc_assignment\/approve_bulk`,\n    ADHOC_RESET_BULK: `${BASE_URL}\/ad_hoc_assignment\/reset_bulk`,\n    ASSIGNED_EXPORT: `${BASE_URL}\/work_assignment\/export`,\n    ADHOC_EXPORT: `${BASE_URL}\/ad_hoc_assignment\/export`,\n  };\n  \n  \/\/ \u00e2\u201d\u20ac\u00e2\u201d\u20ac TOKEN VALIDATION (top-of-page gate) \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\n  (function enforceAuth() {\n    if (isWpEditorPreview()) return;\n    if (!getAuthToken()) {\n      window.location.href = LOGIN_URL;\n    }\n  })();\n  \n  let activeView = \"assigned\";\n  let currentPage = 1;\n  let totalPages = 1;\n  let currentTotalRecords = 0;\n  let currentPerPage = 25;\n  let lastFetchedRows = [];\n  let lastFetchedHeaders = [];\n  \n  let dropDownData = {\n    users: [],\n    teamMembers: [],\n    entities: [],\n    clients: [],\n    accounts: [],\n    categories: [],\n    projects: [],\n    insurances: [],\n    projectTypes: [],\n  };\n  \n  \/\/ \u00e2\u201d\u20ac\u00e2\u201d\u20ac ROLE-BASED ACCESS CONTROL \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\n  \/\/ Source: login.html \u00e2\u20ac\u201c PERMISSION_TIER &#038; USER_DATA set on login.\n  \/\/ These values are UI hints ONLY. Backend re-validates every request\n  \/\/ against the authenticated user derived from the Bearer token.\n  const PERMISSION_TIER = (\n    safeGetStorage(\"PERMISSION_TIER\") || \"none\"\n  ).toLowerCase();\n  const CURRENT_USER_DATA = (() => {\n    try {\n      return JSON.parse(safeGetStorage(\"USER_DATA\") || \"{}\");\n    } catch (e) {\n      return {};\n    }\n  })();\n  const CURRENT_USER_ID =\n    safeGetStorage(\"USER_ID\") ||\n    (CURRENT_USER_DATA.id ? String(CURRENT_USER_DATA.id) : null);\n  const USER_ROLE = (\n    safeGetStorage(\"USER_ROLE\") ||\n    CURRENT_USER_DATA.role ||\n    CURRENT_USER_DATA.role_name ||\n    \"\"\n  )\n    .trim()\n    .toLowerCase();\n  \n  \/\/ PHP Helpers.php teamLeadAndAbove(): manage | director | team lead in role name\n  function teamLeadAndAbovePhp(role = USER_ROLE) {\n    const r = String(role || \"\").toLowerCase();\n    if (!r) return false;\n    return (\n      r.includes(\"manage\") || r.includes(\"director\") || r.includes(\"team lead\")\n    );\n  }\n  \/\/   associate \u00e2\u2020\u2019 read-only (personal), no add\/edit\/approve\/revert\n  \/\/   teamlead  \u00e2\u2020\u2019 read team + edit, no approve\/revert\n  \/\/   manager   \u00e2\u2020\u2019 add\/edit\/approve\/revert on team data\n  \/\/   admin     \u00e2\u2020\u2019 everything\n  const IS_ASSOCIATE = PERMISSION_TIER === \"associate\";\n  const IS_TEAMLEAD = PERMISSION_TIER === \"teamlead\";\n  const IS_MANAGER = PERMISSION_TIER === \"manager\";\n  const IS_ADMIN = PERMISSION_TIER === \"admin\";\n  const USER_PERMISSIONS = (() => {\n    try {\n      const raw = safeGetStorage(\"USER_PERMISSIONS\");\n      if (!raw) return [];\n      const parsed = JSON.parse(raw);\n      return Array.isArray(parsed) ? parsed : [];\n    } catch (e) {\n      return [];\n    }\n  })();\n  function hasUserRight(name) {\n    return USER_PERMISSIONS.some((p) => {\n      if (typeof p === \"string\") return p === name;\n      return p?.right === name || p?.name === name;\n    });\n  }\n  \/\/ PHP list1.blade.php: administrator OR assignment-editing right\n  const HAS_ASSIGNMENT_EDITING = hasUserRight(\"assignment-editing\");\n  const CAN_ADD = IS_MANAGER || IS_ADMIN;\n  const CAN_EDIT =\n    IS_TEAMLEAD || IS_MANAGER || IS_ADMIN || HAS_ASSIGNMENT_EDITING;\n  const CAN_APPROVE =\n    IS_MANAGER || IS_ADMIN || IS_TEAMLEAD || teamLeadAndAbovePhp();\n  const CAN_REVERT = IS_MANAGER || IS_ADMIN;\n  \/\/ PHP list.blade.php teamLeadAndAbove(): bulk approve\/reset + row checkboxes (incl. Deputy Manager)\n  const CAN_BULK_ADHOC = IS_TEAMLEAD || IS_MANAGER || teamLeadAndAbovePhp();\n  \n  function getAdhocTableColspan() {\n    return CAN_BULK_ADHOC ? 13 : 12;\n  }\n  \n  function getSelectedAdhocIds() {\n    return Array.from(document.querySelectorAll(\".adhoc-id-checkbox:checked\"))\n      .map((cb) => parseInt(cb.value, 10))\n      .filter((id) => id > 0);\n  }\n  \n  function toggleSelectAllAdhoc(master) {\n    document.querySelectorAll(\".adhoc-id-checkbox\").forEach((cb) => {\n      cb.checked = !!master.checked;\n    });\n    if (master) master.indeterminate = false;\n  }\n  \n  function syncAdhocSelectAll() {\n    const all = document.querySelectorAll(\".adhoc-id-checkbox\");\n    const master = document.getElementById(\"adhocSelectAll\");\n    if (!master || all.length === 0) return;\n    const checked = document.querySelectorAll(\n      \".adhoc-id-checkbox:checked\",\n    ).length;\n    master.checked = both(checked > 0, checked === all.length);\n    master.indeterminate = both(checked > 0, checked < all.length);\n  }\n  \n  \/\/ \u00e2\u201d\u20ac\u00e2\u201d\u20ac AD HOC PER-ROW RIGHTS (PHP parity) \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\n  \/\/ Mirrors workassignmentteam\/list.blade.php action column:\n  \/\/   is_approved == 2 (Not Approved) \u00e2\u2020\u2019 edit only for administrator\n  \/\/   is_approved != 1 (Pending)      \u00e2\u2020\u2019 edit for administrator OR the record creator\n  \/\/                                      (so a user always edits their OWN pending ad hoc)\n  \/\/   is_approved == 1 (Approved)     \u00e2\u2020\u2019 edit only for administrator\n  \/\/   Approve button (pending only)   \u00e2\u2020\u2019 administrator OR someone who has reports (lead+)\n  function getAdhocApprovalState(row) {\n    const rawStatus = String(row?.status_text || row?.status || \"\")\n      .trim()\n      .toLowerCase();\n    const isApproved =\n      rawStatus === \"approved\" ||\n      rawStatus === \"approve\" ||\n      Number(row?.is_approved) === 1;\n    const isNotApproved =\n      rawStatus === \"not approved\" ||\n      rawStatus === \"not approve\" ||\n      Number(row?.is_approved) === 2;\n    return {\n      isApproved,\n      isNotApproved,\n      isPending: both(!isApproved, !isNotApproved),\n    };\n  }\n  function isOwnAdhocRow(row) {\n    const createdBy = String(row?.created_by ?? row?.created_by_id ?? \"\");\n    return every(\n      !!createdBy,\n      !!CURRENT_USER_ID,\n      createdBy === String(CURRENT_USER_ID),\n    );\n  }\n  function canEditAdhocRow(row) {\n    const { isPending } = getAdhocApprovalState(row);\n    if (isPending) return IS_ADMIN || isOwnAdhocRow(row);\n    return IS_ADMIN;\n  }\n  function canApproveAdhocRow(row) {\n    const { isPending } = getAdhocApprovalState(row);\n    return both(isPending, IS_ADMIN || CAN_APPROVE);\n  }\n  \n  \/\/ Data scope for reads\n  function getScope() {\n    if (IS_ADMIN) return \"all\";\n    if (IS_MANAGER || IS_TEAMLEAD || teamLeadAndAbovePhp()) return \"team\";\n    return \"personal\";\n  }\n  function withScope(url) {\n    if (IS_ADMIN) return url;\n    const sep = (typeof url === \"string\" ? url : url.toString()).includes(\"?\")\n      ? \"&#038;\"\n      : \"?\";\n    return `${url}${sep}scope=${encodeURIComponent(getScope())}`;\n  }\n  \/\/ \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\n  \n  const getHeaders = () => ({\n    \"Content-Type\": \"application\/json\",\n    Authorization: `Bearer ${getAuthToken()}`,\n  });\n  \n  \/\/ Token expiry: only explicit 401 logs the user out (403 = stay logged in).\n  function handleAuthError(res, { logoutOnUnauthorized = true } = {}) {\n    const unauthorized = both(res, res.status === 401);\n    if (!unauthorized) return false;\n    if (!logoutOnUnauthorized) return true;\n    safeRemoveStorage(\"TOKEN\");\n    safeRemoveStorage(\"USER_NAME\");\n    safeRemoveStorage(\"USER_DATA\");\n    safeRemoveStorage(\"USER_ID\");\n    safeRemoveStorage(\"USER_ROLE\");\n    safeRemoveStorage(\"PERMISSION_TIER\");\n    safeRemoveStorage(\"USER_PERMISSIONS\");\n    document.cookie = \"TOKEN=; path=\/; expires=Thu, 01 Jan 1970 00:00:00 GMT;\";\n    window.location.href = LOGIN_URL;\n    return true;\n  }\n  \n  async function fetchWorkAssignmentDetail(id) {\n    return fetch(ENDPOINTS.GET_ASSIGNMENT, {\n      method: \"POST\",\n      headers: getHeaders(),\n      body: JSON.stringify({ id, work_assignment_id: id }),\n    });\n  }\n  \n  async function fetchAdHocDetail(id) {\n    return fetch(ENDPOINTS.GET_ADHOC, {\n      method: \"POST\",\n      headers: getHeaders(),\n      body: JSON.stringify({ id }),\n    });\n  }\n  \n  const extractListData = (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?.data?.data)) return payload.data.data.data;\n    return [];\n  };\n  \n  const extractPaginationInfo = (payload, fallbackLimit) => {\n    const directPages = Number(\n      payload?.pagination?.pages ||\n        payload?.data?.pagination?.pages ||\n        payload?.last_page ||\n        payload?.data?.last_page ||\n        0,\n    );\n  \n    const limit = Number(\n      payload?.pagination?.limit ||\n        payload?.data?.pagination?.limit ||\n        payload?.per_page ||\n        payload?.data?.per_page ||\n        payload?.data?.perPage ||\n        fallbackLimit,\n    );\n  \n    if (both(Number.isFinite(directPages), directPages > 0)) {\n      return {\n        pages: directPages,\n        limit: both(Number.isFinite(limit), limit > 0) ? limit : fallbackLimit,\n      };\n    }\n  \n    const total = Number(\n      payload?.pagination?.total ||\n        payload?.data?.pagination?.total ||\n        payload?.total ||\n        payload?.data?.total ||\n        0,\n    );\n  \n    const safeLimit = both(Number.isFinite(limit), limit > 0) ? limit : fallbackLimit;\n    const derivedPages = total > 0 ? Math.ceil(total \/ safeLimit) : 1;\n  \n    return { pages: Math.max(1, derivedPages), limit: safeLimit };\n  };\n  \n  async function fetchAllPages(endpoint) {\n    const defaultLimit = 500;\n    const buildUrl = (page, limit = defaultLimit) => {\n      \/\/ RBAC: attach scope so backend filters lookup data by user's access\n      const url = new URL(withScope(endpoint));\n      url.searchParams.set(\"page\", String(page));\n      url.searchParams.set(\"limit\", String(limit));\n      return url.toString();\n    };\n  \n    const firstRes = await fetch(buildUrl(1, defaultLimit), {\n      headers: getHeaders(),\n    });\n    const firstJson = await firstRes.json();\n  \n    let allItems = extractListData(firstJson);\n    const { pages, limit } = extractPaginationInfo(firstJson, defaultLimit);\n  \n    if (pages > 1) {\n      const pageRequests = [];\n      for (let page = 2; page <= pages; page++) {\n        pageRequests.push(\n          fetch(buildUrl(page, limit), { headers: getHeaders() })\n            .then((r) => r.json())\n            .catch(() => null),\n        );\n      }\n  \n      const otherPages = await Promise.all(pageRequests);\n      otherPages.forEach((pageData) => {\n        if (pageData) allItems = allItems.concat(extractListData(pageData));\n      });\n    }\n  \n    return allItems;\n  }\n  \n  function isActiveItem(item) {\n    return item?.is_active === true || item?.is_active === 1;\n  }\n  \n  \/\/ Initialize App\n  async function init() {\n    \/\/ Guard: if this script is loaded on a page without the expected markup,\n    \/\/ skip initialization instead of throwing null element errors.\n    if (!document.getElementById(\"filterForm\")) return;\n    await fetchDropdownData();\n    renderUI();\n    fetchTableData();\n  }\n  \n  async function fetchDropdownData() {\n    try {\n      const [u, uAll, e, c, a, cat, p, ins, pt, tm] = await Promise.all([\n        fetchAllPages(ENDPOINTS.USERS),\n        fetchAllPages(ENDPOINTS.USERS_ALL).catch(() => []),\n        fetchAllPages(ENDPOINTS.ENTITIES),\n        fetchAllPages(ENDPOINTS.CLIENTS),\n        fetch(withScope(ENDPOINTS.ACCOUNTS), { headers: getHeaders() }).then(\n          (r) => r.json(),\n        ),\n        fetchAllPages(ENDPOINTS.CATEGORIES),\n        fetchAllPages(ENDPOINTS.PROJECTS),\n        fetch(ENDPOINTS.INSURANCES, { headers: getHeaders() }).then((r) =>\n          r.json(),\n        ),\n        fetchAllPages(ENDPOINTS.PROJECT_TYPES),\n        fetch(ENDPOINTS.TEAM_MEMBERS, { headers: getHeaders() })\n          .then((r) => r.json())\n          .catch(() => ({})),\n      ]);\n      dropDownData.users = buildUserDirectory([\n        Array.isArray(u) ? u : [],\n        Array.isArray(uAll) ? uAll : [],\n      ]);\n      dropDownData.teamMembers = enrichTeamMembersWithHierarchy(\n        Array.isArray(tm?.data)\n          ? tm.data\n          : Array.isArray(tm?.data?.data)\n            ? tm.data.data\n            : dropDownData.users,\n        dropDownData.users,\n      );\n      dropDownData.entities = Array.isArray(e) ? e : [];\n      dropDownData.clients = Array.isArray(c) ? c : [];\n      dropDownData.accounts = Array.isArray(a) ? a : extractListData(a);\n      dropDownData.categories = Array.isArray(cat) ? cat : [];\n      dropDownData.projects = Array.isArray(p) ? p : [];\n      dropDownData.insurances = Array.isArray(ins?.data?.data)\n        ? ins.data.data\n        : Array.isArray(ins?.data)\n          ? ins.data\n          : [];\n      dropDownData.projectTypes = Array.isArray(pt)\n        ? pt.filter(isActiveItem)\n        : [];\n    } catch (err) {\n      console.error(\"Dropdown fetch error\", err);\n    }\n  }\n  \n  \/* Pencil SVG \u00e2\u20ac\u201d inline so it inherits stroke color *\/\n  const editIconSVG = `<svg viewBox=\"0 0 24 24\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\"><path d=\"M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7\"\/><path d=\"M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z\"\/><\/svg>`;\n  \n  function renderUI() {\n    const isAssigned = activeView === \"assigned\";\n    const headingEl = document.getElementById(\"pageHeading\");\n    if (headingEl)\n      headingEl.innerText = isAssigned\n        ? \"Assigned Assignment\"\n        : \"Ad Hoc Assignments\";\n  \n    \/\/ Render Filters\n    const form = document.getElementById(\"filterForm\");\n    if (!form) return;\n    \/\/ Always reset inline style so CSS grid class controls layout\n    form.style.gridTemplateColumns = \"\";\n    if (isAssigned) {\n      form.innerHTML = `\n                  ${renderSelect(\"Assigned to\", \"filterAssignedTo\", dropDownData.teamMembers, \"pesudo_name\", \"id\", true)}\n                  ${renderSelect(\"Entity\", \"filterEntity\", dropDownData.entities, \"entity\", \"id\", true)}\n                  ${renderSelect(\"Client\", \"filterClient\", dropDownData.clients, \"name\", \"id\", true)}\n                  ${renderSelect(\"Account\", \"filterAccount\", dropDownData.accounts, \"name\", \"id\", true)}\n                  ${renderSelect(\"Category\", \"filterCategory\", dropDownData.categories, \"category\", \"id\", true)}\n                  ${renderSelect(\"Project\", \"filterProject\", dropDownData.projects, \"name\", \"id\", true)}\n                  <div class=\"form-group\"><label>Select Date<\/label>\n                      <div class=\"date-wrapper\" id=\"dpWrapperAssigned\">\n                          <input type=\"text\" id=\"filterDate\" placeholder=\"Select Date range\" readonly onclick=\"toggleDatePicker(event,'assigned')\">\n                          <svg class=\"cal-icon\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\">\n                              <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"\/>\n                              <line x1=\"16\" y1=\"2\" x2=\"16\" y2=\"6\"\/>\n                              <line x1=\"8\"  y1=\"2\" x2=\"8\"  y2=\"6\"\/>\n                              <line x1=\"3\"  y1=\"10\" x2=\"21\" y2=\"10\"\/>\n                          <\/svg>\n                          <div class=\"dp-backdrop\" id=\"dpBackdropAssigned\" onclick=\"closeDatePicker('assigned')\"><\/div>\n                          <div class=\"dp-dropdown\" id=\"dpDropdownAssigned\">\n                              <div class=\"dp-presets\">\n                                  <div class=\"dp-preset-item active\" data-preset=\"today\"     onclick=\"selectPreset(event,'today','assigned')\">Today<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"yesterday\"  onclick=\"selectPreset(event,'yesterday','assigned')\">Yesterday<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"last7\"      onclick=\"selectPreset(event,'last7','assigned')\">Last 7 Days<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"last30\"     onclick=\"selectPreset(event,'last30','assigned')\">Last 30 Days<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"thisMonth\"  onclick=\"selectPreset(event,'thisMonth','assigned')\">This Month<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"lastMonth\"  onclick=\"selectPreset(event,'lastMonth','assigned')\">Last Month<\/div>\n                              <\/div>\n                              <div class=\"dp-calendars-wrap\">\n                                  <div class=\"dp-months-row\">\n                                      <div class=\"dp-calendar\">\n                                          <div class=\"dp-cal-header\">\n                                              <button class=\"dp-nav-btn\" onclick=\"dpChangeMonth(event,-1,'assigned')\">&#8249;<\/button>\n                                              <span class=\"dp-cal-title\" id=\"dpCalTitleAssigned\"><\/span>\n                                              <button class=\"dp-nav-btn dp-nav-hidden\">&#8250;<\/button>\n                                          <\/div>\n                                          <div class=\"dp-weekdays\">\n                                              <div class=\"dp-weekday\">Su<\/div><div class=\"dp-weekday\">Mo<\/div>\n                                              <div class=\"dp-weekday\">Tu<\/div><div class=\"dp-weekday\">We<\/div>\n                                              <div class=\"dp-weekday\">Th<\/div><div class=\"dp-weekday\">Fr<\/div>\n                                              <div class=\"dp-weekday\">Sa<\/div>\n                                          <\/div>\n                                          <div class=\"dp-days\" id=\"dpDaysAssigned\"><\/div>\n                                      <\/div>\n                                      <div class=\"dp-calendar\">\n                                          <div class=\"dp-cal-header\">\n                                              <button class=\"dp-nav-btn dp-nav-hidden\">&#8249;<\/button>\n                                              <span class=\"dp-cal-title\" id=\"dpCalTitleAssigned2\"><\/span>\n                                              <button class=\"dp-nav-btn\" onclick=\"dpChangeMonth(event,1,'assigned')\">&#8250;<\/button>\n                                          <\/div>\n                                          <div class=\"dp-weekdays\">\n                                              <div class=\"dp-weekday\">Su<\/div><div class=\"dp-weekday\">Mo<\/div>\n                                              <div class=\"dp-weekday\">Tu<\/div><div class=\"dp-weekday\">We<\/div>\n                                              <div class=\"dp-weekday\">Th<\/div><div class=\"dp-weekday\">Fr<\/div>\n                                              <div class=\"dp-weekday\">Sa<\/div>\n                                          <\/div>\n                                          <div class=\"dp-days\" id=\"dpDaysAssigned2\"><\/div>\n                                      <\/div>\n                                  <\/div>\n                                  <div class=\"dp-footer\">\n                                      <div class=\"dp-range-display\" id=\"dpRangeDisplayAssigned\">Select Date Range<\/div>\n                                      <div class=\"dp-footer-btns\">\n                                          <button class=\"dp-btn-clear\" onclick=\"dpClear(event,'assigned')\">Cancel<\/button>\n                                          <button class=\"dp-btn-apply\" onclick=\"dpApply(event,'assigned')\">Apply<\/button>\n                                      <\/div>\n                                  <\/div>\n                              <\/div>\n                          <\/div>\n                      <\/div>\n                  <\/div>\n                  <div class=\"form-group\"><label>Per Page<\/label><select id=\"filterPerPage\" class=\"form-control\" onchange=\"fetchTableData(1)\"><option value=\"\" disabled selected>Per Page<\/option><option value=\"10\">10<\/option><option value=\"15\">15<\/option><option value=\"25\" >25<\/option><option value=\"50\">50<\/option><option value=\"100\">100<\/option><\/select><\/div>\n              `;\n    } else {\n      form.style.display = \"grid\";\n      form.style.gridTemplateColumns = \"\";\n      form.innerHTML = `\n                  ${renderSelect(\"Assigned to\", \"filterAssignedToAdhoc\", dropDownData.teamMembers, \"pesudo_name\", \"id\", true)}\n                  <div class=\"form-group\">\n                      <label>Status<\/label>\n                      <select id=\"filterStatusAdhoc\" class=\"form-control\" onchange=\"fetchAdhocTableData(1)\">\n                          <option value=\"all\">All<\/option>\n                          <option value=\"pending\">Pending<\/option>\n                          <option value=\"approve\">Approve<\/option>\n                          <option value=\"not approve\">Not Approve<\/option>\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label>Select Date<\/label>\n                      <div class=\"date-wrapper\" id=\"dpWrapperAdhoc\">\n                          <input type=\"text\" id=\"filterAdhocDate\" placeholder=\"Select Date range\" readonly onclick=\"toggleDatePicker(event,'adhoc')\">\n                          <svg class=\"cal-icon\" width=\"16\" height=\"16\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" viewBox=\"0 0 24 24\">\n                              <rect x=\"3\" y=\"4\" width=\"18\" height=\"18\" rx=\"2\" ry=\"2\"\/>\n                              <line x1=\"16\" y1=\"2\" x2=\"16\" y2=\"6\"\/>\n                              <line x1=\"8\"  y1=\"2\" x2=\"8\"  y2=\"6\"\/>\n                              <line x1=\"3\"  y1=\"10\" x2=\"21\" y2=\"10\"\/>\n                          <\/svg>\n                          <div class=\"dp-backdrop\" id=\"dpBackdropAdhoc\" onclick=\"closeDatePicker('adhoc')\"><\/div>\n                          <div class=\"dp-dropdown\" id=\"dpDropdownAdhoc\">\n                              <div class=\"dp-presets\">\n                                  <div class=\"dp-preset-item active\" data-preset=\"today\"     onclick=\"selectPreset(event,'today','adhoc')\">Today<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"yesterday\"  onclick=\"selectPreset(event,'yesterday','adhoc')\">Yesterday<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"last7\"      onclick=\"selectPreset(event,'last7','adhoc')\">Last 7 Days<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"last30\"     onclick=\"selectPreset(event,'last30','adhoc')\">Last 30 Days<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"thisMonth\"  onclick=\"selectPreset(event,'thisMonth','adhoc')\">This Month<\/div>\n                                  <div class=\"dp-preset-item\"       data-preset=\"lastMonth\"  onclick=\"selectPreset(event,'lastMonth','adhoc')\">Last Month<\/div>\n                              <\/div>\n                              <div class=\"dp-calendars-wrap\">\n                                  <div class=\"dp-months-row\">\n                                      <div class=\"dp-calendar\">\n                                          <div class=\"dp-cal-header\">\n                                              <button class=\"dp-nav-btn\" onclick=\"dpChangeMonth(event,-1,'adhoc')\">&#8249;<\/button>\n                                              <span class=\"dp-cal-title\" id=\"dpCalTitleAdhoc\"><\/span>\n                                              <button class=\"dp-nav-btn\" dp-nav-hidden=\"\">&#8250;<\/button>\n                                          <\/div>\n                                          <div class=\"dp-weekdays\">\n                                              <div class=\"dp-weekday\">Su<\/div><div class=\"dp-weekday\">Mo<\/div>\n                                              <div class=\"dp-weekday\">Tu<\/div><div class=\"dp-weekday\">We<\/div>\n                                              <div class=\"dp-weekday\">Th<\/div><div class=\"dp-weekday\">Fr<\/div>\n                                              <div class=\"dp-weekday\">Sa<\/div>\n                                          <\/div>\n                                          <div class=\"dp-days\" id=\"dpDaysAdhoc\"><\/div>\n                                      <\/div>\n                                      <div class=\"dp-calendar\">\n                                          <div class=\"dp-cal-header\">\n                                              <button class=\"dp-nav-btn dp-nav-hidden\">&#8249;<\/button>\n                                              <span class=\"dp-cal-title\" id=\"dpCalTitleAdhoc2\"><\/span>\n                                              <button class=\"dp-nav-btn\" onclick=\"dpChangeMonth(event,1,'adhoc')\">&#8250;<\/button>\n                                          <\/div>\n                                          <div class=\"dp-weekdays\">\n                                              <div class=\"dp-weekday\">Su<\/div><div class=\"dp-weekday\">Mo<\/div>\n                                              <div class=\"dp-weekday\">Tu<\/div><div class=\"dp-weekday\">We<\/div>\n                                              <div class=\"dp-weekday\">Th<\/div><div class=\"dp-weekday\">Fr<\/div>\n                                              <div class=\"dp-weekday\">Sa<\/div>\n                                          <\/div>\n                                          <div class=\"dp-days\" id=\"dpDaysAdhoc2\"><\/div>\n                                      <\/div>\n                                  <\/div>\n                                  <div class=\"dp-footer\">\n                                      <div class=\"dp-range-display\" id=\"dpRangeDisplayAdhoc\">Select Date Range<\/div>\n                                      <div class=\"dp-footer-btns\">\n                                          <button class=\"dp-btn-clear\" onclick=\"dpClear(event,'adhoc')\">Cancel<\/button>\n                                          <button class=\"dp-btn-apply\" onclick=\"dpApply(event,'adhoc')\">Apply<\/button>\n                                      <\/div>\n                                  <\/div>\n                              <\/div>\n                          <\/div>\n                      <\/div>\n                  <\/div>\n                  <div class=\"form-group\"><label>Per Page<\/label><select id=\"filterPerPageAdhoc\" class=\"form-control\" onchange=\"fetchAdhocTableData(1)\"><option value=\"\" disabled selected>Per Page<\/option><option value=\"10\">10<\/option><option value=\"15\">15<\/option><option value=\"25\" selected>25<\/option><option value=\"50\">50<\/option><option value=\"100\">100<\/option><\/select><\/div>\n              `;\n    }\n  \n    \/\/ Render Buttons \u00e2\u20ac\u201d flex:1 on each fills full row width\n    let btns = [];\n    if (isAssigned) {\n      \/\/ Assign Assignment Tab\n      if (IS_ADMIN) {\n        btns = [\n          \"Close\",\n          \"Filter\",\n          \"+ Add New Assignment\",\n          \"+ CSV Import\",\n          \"+ CSV Download\",\n        ];\n      } else if (IS_MANAGER) {\n        btns = [\"Close\", \"Filter\", \"+ CSV Download\"];\n      } else {\n        \/\/ Team Lead and Associate\n        btns = [\"Close\", \"Filter\"];\n      }\n    } else {\n      \/\/ Adhoc Tab\n      if (IS_ASSOCIATE) {\n        btns = [\"Close\", \"Filter\", \"+ CSV Download\", \"+ Add Adhoc\"];\n      } else if (IS_ADMIN) {\n        btns = [\"Close\", \"Filter\", \"+ CSV Download\", \"+ CSV Import\"];\n      } else if (IS_TEAMLEAD) {\n        btns = [\n          \"Close\",\n          \"Filter\",\n          \"+ CSV Download\",\n          \"+ Add Adhoc\",\n          \"Approve All\",\n          \"Reset All\",\n        ];\n      } else {\n        \/\/ Manager \/ Deputy Manager (PHP teamLeadAndAbove)\n        btns = [\n          \"Close\",\n          \"Filter\",\n          \"+ CSV Download\",\n          \"+ CSV Import\",\n          \"+ Add Adhoc\",\n        ];\n        if (CAN_BULK_ADHOC) {\n          btns.push(\"Approve All\", \"Reset All\");\n        }\n      }\n      if (both(CAN_BULK_ADHOC, !btns.includes(\"Approve All\"))) {\n        btns.push(\"Approve All\", \"Reset All\");\n      }\n    }\n  \n    document.getElementById(\"btnGroup\").innerHTML = btns\n      .map(\n        (b) =>\n          `<button class=\"btn ${b === \"Filter\" ? \"btn-filter\" : b === \"Close\" ? \"btn-clear\" : \"btn-blue\"}\" onclick=\"handleActionClick('${b}')\">${b}<\/button>`,\n      )\n      .join(\"\");\n  \n    \/\/ Table Headers\n    const headers = isAssigned\n      ? [\n          \"Assigned Date\",\n          \"Hrs\",\n          \"Assigned To\",\n          \"Pseudo Name\",\n          \"File Name\",\n          \"Received On\",\n          \"Insurance\",\n          \"Account\",\n          \"Project\",\n          \"Entity\",\n          \"Client\",\n          \"Category\",\n          \"Assigned DOS\",\n          \"Action\",\n        ]\n      : [\n          \"Date\",\n          \"Client\",\n          \"Project\",\n          \"Work Type\",\n          \"Desc.\",\n          \"Comments\",\n          \"Time Utilized\",\n          \"Time Approved\",\n          \"Created By\",\n          \"Updated By\",\n          \"Updated At\",\n          \"Action\",\n        ];\n  \n    lastFetchedHeaders = headers.filter((h) => h !== \"Action\");\n    let headHtml = headers.map((h) => `<th>${h}<\/th>`).join(\"\");\n    if (both(!isAssigned, CAN_BULK_ADHOC)) {\n      headHtml += `<th class=\"adhoc-select-col\"><input type=\"checkbox\" id=\"adhocSelectAll\" class=\"adhoc-bulk-checkbox\" title=\"Select all\" onchange=\"toggleSelectAllAdhoc(this)\"><\/th>`;\n    }\n    document.getElementById(\"tblHead\").innerHTML = `<tr>${headHtml}<\/tr>`;\n  \n    const perPageEl = document.getElementById(\"filterPerPage\");\n    if (perPageEl) {\n      perPageEl.onchange = () => fetchTableData(1);\n    }\n  \n    const perPageAdhocEl = document.getElementById(\"filterPerPageAdhoc\");\n    if (perPageAdhocEl) {\n      perPageAdhocEl.onchange = () => fetchAdhocTableData(1);\n    }\n  }\n  \n  function renderSelect(\n    label,\n    selectId,\n    data,\n    labelKey,\n    valueKey = \"id\",\n    multi = false,\n  ) {\n    const optionsData = (data || []).map((item) => ({\n      _val: item[valueKey] ?? \"\",\n      _label: item[labelKey] ?? \"\",\n    }));\n    const optionsHtml =\n      `\n          <div class=\"custom-select-option placeholder-option\" style=\"display:none;\" data-value=\"\" onclick=\"csSelect('${selectId}', '', this, ${multi})\">\n              <div class=\"cs-checkbox\"><\/div>\n              <span class=\"opt-label\">Select ${label}<\/span>\n          <\/div>\n      ` +\n      optionsData\n        .map(\n          (o, i) =>\n            `<div class=\"custom-select-option\" data-value=\"${o._val}\" onclick=\"csSelect('${selectId}', '${o._val.toString().replace(\/'\/g, \"\\\\'\")}', this, ${multi})\">\n                  <div class=\"cs-checkbox\"><\/div>\n                  <span class=\"opt-label\">${o._label}<\/span>\n              <\/div>`,\n        )\n        .join(\"\");\n    return `\n              <div class=\"form-group\">\n                  <label>${label}<\/label>\n                  <div class=\"custom-select-wrapper${multi ? \" multi\" : \"\"}\" id=\"csWrapper_${selectId}\">\n                      <input type=\"hidden\" id=\"${selectId}\" value=\"\">\n                      <div class=\"custom-select-trigger placeholder-shown\" onclick=\"csTriggerClick('${selectId}', event)\">\n                          <div class=\"cs-label\">\n                              <input type=\"text\" class=\"cs-search-input\" id=\"csInput_${selectId}\" placeholder=\"Select ${label}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${selectId}', this.value)\" onkeydown=\"csKeyDown(event, '${selectId}')\" onclick=\"csOpenDropdown('${selectId}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${selectId}')\">\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_${selectId}\">\n                          <div class=\"custom-select-options\">\n                              ${optionsHtml}\n                          <\/div>\n                      <\/div>\n                  <\/div>\n              <\/div>\n          `;\n  }\n  \n  function 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(\".custom-select-wrapper.open\").forEach((w) => {\n      if (w !== wrapper) w.classList.remove(\"open\");\n    });\n    if (isOpen) {\n      wrapper.classList.remove(\"open\");\n    } else {\n      wrapper.classList.add(\"open\");\n      \/\/ Reset filter state and focus the integrated search input if present\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  }\n  \n  function csTriggerClick(selectId, e) {\n    e.stopPropagation();\n    csToggle(selectId, e);\n  }\n  \n  function csOpenDropdown(selectId) {\n    const wrapper = document.getElementById(\"csWrapper_\" + selectId);\n    if (!wrapper || wrapper.classList.contains(\"open\")) return;\n    document.querySelectorAll(\".custom-select-wrapper.open\").forEach((w) => {\n      if (w !== wrapper) w.classList.remove(\"open\");\n    });\n    wrapper.classList.add(\"open\");\n    csHighlightFirst(selectId);\n  }\n  \n  function csFilter(selectId, query) {\n    csIntegratedFilter(selectId, query);\n  }\n  \n  function 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    \/\/ Open dropdown automatically whenever the user types in the field\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  }\n  \n  function csHighlightFirst(selectId) {\n    const drop = document.getElementById(\"csDrop_\" + selectId);\n    if (!drop) return;\n    drop\n      .querySelectorAll(\".custom-select-option\")\n      .forEach((o) => o.classList.remove(\"highlighted\"));\n    const visible = Array.from(\n      drop.querySelectorAll(\".custom-select-option\"),\n    ).filter(\n      (o) =>\n        both(\n          o.style.display !== \"none\",\n          !o.classList.contains(\"placeholder-option\"),\n        ),\n    );\n    if (visible.length > 0) {\n      visible[0].classList.add(\"highlighted\");\n    }\n  }\n  \n  function 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(\n          \".custom-select-option.highlighted\",\n        );\n        if (highlighted) {\n          const multi = wrapper.classList.contains(\"multi\");\n          const value = highlighted.dataset.value;\n          csSelect(selectId, value, highlighted, multi);\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(\n        drop.querySelectorAll(\".custom-select-option\"),\n      ).filter(\n        (o) =>\n          both(\n            o.style.display !== \"none\",\n            !o.classList.contains(\"placeholder-option\"),\n          ),\n      );\n      if (visibleOptions.length === 0) return;\n      let currentIdx = visibleOptions.findIndex((o) =>\n        o.classList.contains(\"highlighted\"),\n      );\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(\n        drop.querySelectorAll(\".custom-select-option\"),\n      ).filter(\n        (o) =>\n          both(\n            o.style.display !== \"none\",\n            !o.classList.contains(\"placeholder-option\"),\n          ),\n      );\n      if (visibleOptions.length === 0) return;\n      let currentIdx = visibleOptions.findIndex((o) =>\n        o.classList.contains(\"highlighted\"),\n      );\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  }\n  \n  function csSelect(selectId, value, optionEl, multi = false) {\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  \n    if (value === \"\") {\n      input.value = \"\";\n      \/\/ If trigger has an integrated search input, restore it; otherwise show option label\n      const placeholderLabel = wrapper.querySelector(\n        \".placeholder-option .opt-label\",\n      );\n      const hadIntegratedInput = !!document.getElementById(\"csInput_\" + selectId);\n      if (hadIntegratedInput) {\n        const phText = placeholderLabel\n          ? placeholderLabel.textContent.trim()\n          : \"\";\n        labelEl.innerHTML = `<input type=\"text\" class=\"cs-search-input\" id=\"csInput_${selectId}\" placeholder=\"${phText}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${selectId}', this.value)\" onkeydown=\"csKeyDown(event, '${selectId}')\" onclick=\"csOpenDropdown('${selectId}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${selectId}')\">`;\n      } else {\n        labelEl.innerHTML = optionEl\n          .querySelector(\".opt-label\")\n          .textContent.trim();\n      }\n      trigger.classList.add(\"placeholder-shown\");\n      wrapper\n        .querySelectorAll(\".custom-select-option\")\n        .forEach((o) => o.classList.remove(\"selected\"));\n      if (!multi) wrapper.classList.remove(\"open\");\n      handleActionClick(\"Filter\");\n      return;\n    }\n  \n    if (!multi) {\n      input.value = value;\n      const selectedText = optionEl\n        .querySelector(\".opt-label\")\n        .textContent.trim();\n      const hadIntegratedInput = !!document.getElementById(\"csInput_\" + selectId);\n      if (hadIntegratedInput) {\n        labelEl.innerHTML = `<input type=\"text\" class=\"cs-search-input\" id=\"csInput_${selectId}\" placeholder=\"${selectedText}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${selectId}', this.value)\" onkeydown=\"csKeyDown(event, '${selectId}')\" onclick=\"csOpenDropdown('${selectId}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${selectId}')\">`;\n      } else {\n        labelEl.textContent = selectedText;\n      }\n      trigger.classList.remove(\"placeholder-shown\");\n      wrapper\n        .querySelectorAll(\".custom-select-option\")\n        .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(value);\n      if (idx > -1) {\n        values.splice(idx, 1);\n        optionEl.classList.remove(\"selected\");\n      } else {\n        values.push(value);\n        optionEl.classList.add(\"selected\");\n      }\n      input.value = values.join(\",\");\n  \n      const placeholderLabel = wrapper.querySelector(\n        \".placeholder-option .opt-label\",\n      );\n      const phText = placeholderLabel ? placeholderLabel.textContent.trim() : \"\";\n  \n      if (values.length === 0) {\n        labelEl.innerHTML = `<input type=\"text\" class=\"cs-search-input\" id=\"csInput_${selectId}\" placeholder=\"${phText}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${selectId}', this.value)\" onkeydown=\"csKeyDown(event, '${selectId}')\" onclick=\"csOpenDropdown('${selectId}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${selectId}')\">`;\n        trigger.classList.add(\"placeholder-shown\");\n      } else {\n        trigger.classList.remove(\"placeholder-shown\");\n        const selectedLabels = Array.from(\n          wrapper.querySelectorAll(\".custom-select-option.selected\"),\n        ).map((opt) => ({\n          val: opt.dataset.value,\n          label: opt.querySelector(\".opt-label\").textContent.trim(),\n        }));\n  \n        const chipsHtml = selectedLabels\n          .map(\n            (item) => `\n                  <div class=\"cs-chip\">\n                      <span>${item.label}<\/span>\n                      <span class=\"cs-chip-remove\" onclick=\"csRemoveChip(event, '${selectId}', '${item.val}')\">&times;<\/span>\n                  <\/div>\n              `,\n          )\n          .join(\"\");\n  \n        labelEl.innerHTML =\n          chipsHtml +\n          `<input type=\"text\" class=\"cs-search-input\" id=\"csInput_${selectId}\" placeholder=\"\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${selectId}', this.value)\" onkeydown=\"csKeyDown(event, '${selectId}')\" onclick=\"csOpenDropdown('${selectId}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${selectId}')\">`;\n      }\n  \n      \/\/ Keep dropdown open and refocus the integrated input so user can continue searching\n      if (wrapper.classList.contains(\"open\")) {\n        const newInput = document.getElementById(\"csInput_\" + selectId);\n        if (newInput) setTimeout(() => newInput.focus(), 0);\n      }\n    }\n    handleActionClick(\"Filter\");\n  }\n  \n  function csRemoveChip(e, selectId, value) {\n    e.stopPropagation();\n    const wrapper = document.getElementById(\"csWrapper_\" + selectId);\n    const optionEl = wrapper.querySelector(\n      `.custom-select-option[data-value=\"${value}\"]`,\n    );\n    if (optionEl) {\n      csSelect(selectId, value, optionEl, true);\n    }\n  }\n  \n  function csGetValue(selectId) {\n    const el = document.getElementById(selectId);\n    return el ? el.value : \"\";\n  }\n  \n  \/\/ Close custom selects when clicking outside\n  document.addEventListener(\"click\", function (e) {\n    if (!e.target.closest(\".custom-select-wrapper\")) {\n      document\n        .querySelectorAll(\".custom-select-wrapper.open\")\n        .forEach((w) => w.classList.remove(\"open\"));\n    }\n  });\n  \n  function safeText(value) {\n    if (value === null || value === undefined || value === \"\") return \"-\";\n    return String(value)\n      .replaceAll(\"&\", \"&amp;\")\n      .replaceAll(\"<\", \"&lt;\")\n      .replaceAll(\">\", \"&gt;\")\n      .replaceAll('\"', \"&quot;\")\n      .replaceAll(\"'\", \"&#039;\");\n  }\n  \n  function getOnlyDate(val) {\n    if (!val) return \"\";\n    const str = String(val).trim();\n    if (str.includes(\"T\")) return str.split(\"T\")[0];\n    if (str.includes(\" \")) return str.split(\" \")[0];\n    return str;\n  }\n  \n  function formatAdhocDecimal(val) {\n    if (val === null || val === undefined || val === \"\") return \"-\";\n    const str = String(val).trim();\n    if (str.includes(\":\")) return str;\n    const num = parseFloat(str);\n    if (!isNaN(num)) {\n      return num.toFixed(2);\n    }\n    return str;\n  }\n  \n  function formatDate(dStr) {\n    if (!dStr) return \"\";\n    const str = String(dStr).trim();\n    if (str.includes(\"T\")) return str.split(\"T\")[0];\n    if (str.includes(\" \")) return str.split(\" \")[0];\n    if (str.includes(\"\/\")) {\n      const parts = str.split(\"\/\");\n      if (parts.length === 3) {\n        const mm = parts[0].padStart(2, \"0\");\n        const dd = parts[1].padStart(2, \"0\");\n        const yyyy = parts[2];\n        return `${yyyy}-${mm}-${dd}`;\n      }\n    }\n    return str;\n  }\n  function normalizeAssignmentRow(row) {\n    if (!row) return row;\n    return {\n      ...row,\n      file_id: row.file_id ?? row.file?.id ?? null,\n      account_id:\n        row.account_id ?? row.account?.id ?? row.account_relation_id ?? null,\n      assigned_to:\n        row.assigned_to ?? row.assigned_to_user_id ?? row.assignedTo?.id ?? null,\n      received_on: getOnlyDate(row.received_on ?? row.file_received_on),\n      assigned_date: getOnlyDate(row.assigned_date),\n      file_name: row.file_name ?? row.file?.file_name ?? \"\",\n      project_type_id: row.project_type_id ?? row.project_type?.id ?? null,\n      insurance_id: row.insurance_id ?? row.insurance?.id ?? null,\n    };\n  }\n \n  function buildSelectOptions(\n    data,\n    valueKey,\n    labelKey,\n    selectedValue,\n    fallbackLabel = \"\",\n  ) {\n    const selected = String(selectedValue ?? \"\");\n    const options = (data || [])\n      .map(\n        (item) =>\n          `<option value=\"${item[valueKey] ?? \"\"}\" ${String(item[valueKey]) === selected ? \"selected\" : \"\"}>${item[labelKey] ?? \"\"}<\/option>`,\n      )\n      .join(\"\");\n    if (\n      selected &&\n      !(data || []).some((item) => String(item[valueKey]) === selected)\n    ) {\n      const label = fallbackLabel || `Selected (#${selected})`;\n      return `<option value=\"${selected}\" selected>${safeText(label)}<\/option>${options}`;\n    }\n    return options;\n  }\n\n  function escapeAttr(value) {\n    return String(value ?? \"\")\n      .replace(\/&\/g, \"&amp;\")\n      .replace(\/\"\/g, \"&quot;\")\n      .replace(\/<\/g, \"&lt;\");\n  }\n\n  function buildUserDirectory(sources) {\n    const map = new Map();\n    (sources || []).forEach((batch) => {\n      (batch || []).forEach((user) => {\n        if (!user || user.id == null) return;\n        const key = String(user.id);\n        map.set(key, { ...(map.get(key) || {}), ...user });\n      });\n    });\n    return [...map.values()];\n  }\n\n  function getUserTeamLabel(user) {\n    return (\n      user?.team_name ||\n      user?.team ||\n      user?.department_name ||\n      user?.department ||\n      \"Other\"\n    );\n  }\n\n  function getUserReportToLabel(user) {\n    return (\n      user?.report_to_name ||\n      user?.report_to ||\n      user?.manager_name ||\n      user?.team_lead ||\n      \"\"\n    );\n  }\n\n  function getUserPseudoName(user) {\n    if (!user) return \"\";\n    return (\n      user.pesudo_name ||\n      user.pseudo_name ||\n      user.pesudoName ||\n      user.name ||\n      \"\"\n    );\n  }\n\n  function enrichTeamMembersWithHierarchy(teamMembers, userDirectory) {\n    const directory = new Map();\n    (userDirectory || []).forEach((user) => {\n      if (user && user.id != null) directory.set(String(user.id), user);\n    });\n\n    return (teamMembers || []).map((member) => {\n      const info = directory.get(String(member.id)) || {};\n      const merged = { ...info, ...member };\n      return {\n        ...merged,\n        pesudo_name: getUserPseudoName(member) || getUserPseudoName(info),\n        team_name: getUserTeamLabel(merged),\n        report_to_name: getUserReportToLabel(merged),\n      };\n    });\n  }\n\n  function sortUsersByTeamHierarchy(users) {\n    return [...(users || [])].sort((a, b) => {\n      const teamCompare = getUserTeamLabel(a)\n        .toLowerCase()\n        .localeCompare(getUserTeamLabel(b).toLowerCase());\n      if (teamCompare !== 0) return teamCompare;\n\n      const reportCompare = getUserReportToLabel(a)\n        .toLowerCase()\n        .localeCompare(getUserReportToLabel(b).toLowerCase());\n      if (reportCompare !== 0) return reportCompare;\n\n      return getUserPseudoName(a)\n        .toLowerCase()\n        .localeCompare(getUserPseudoName(b).toLowerCase());\n    });\n  }\n\n  function buildGroupedUserSelectOptions(selectedValue, fallbackLabel = \"\") {\n    const members = sortUsersByTeamHierarchy(dropDownData.teamMembers || []);\n    const selected = String(selectedValue ?? \"\");\n\n    let html = members\n      .map((user) => {\n        const val = String(user.id ?? \"\");\n        return `<option value=\"${escapeAttr(val)}\" ${val === selected ? \"selected\" : \"\"}>${safeText(getUserPseudoName(user))}<\/option>`;\n      })\n      .join(\"\");\n\n    if (selected && !members.some((user) => String(user.id) === selected)) {\n      const label = fallbackLabel || `Selected (#${selected})`;\n      html =\n        `<option value=\"${escapeAttr(selected)}\" selected>${safeText(label)}<\/option>` + html;\n    }\n\n    return html;\n  }\n  function calcAdhocEditHrs() {\n    const mins =\n      parseInt(document.getElementById(\"editAdhocMinsUtilized\")?.value, 10) || 0;\n    const hrsEl = document.getElementById(\"editAdhocHrsUtilized\");\n    if (hrsEl) {\n      hrsEl.value = Math.floor(mins \/ 60);\n    }\n  }\n  \n  \/\/ PHP parity: public\/assets\/js\/custom.js timeConvert(n)\n  \/\/ Treats n as TOTAL minutes and splits into { hour, minutes }.\n  function timeConvert(n) {\n    const num = parseInt(n, 10) || 0;\n    const hours = num \/ 60;\n    const rhours = Math.floor(hours);\n    const rminutes = Math.round((hours - rhours) * 60);\n    return { hour: rhours, minutes: rminutes };\n  }\n  \n  \/\/ Holds the utilized hrs\/mins of the row currently open in the approval modal\n  let _approvalUtilized = { hrs: 0, mins: 0 };\n  \n  \/\/ PHP parity: custom.js blur handler on #minute_approved.\n  \/\/ The Mins Approved field is entered as TOTAL minutes and split into hrs + remainder.\n  function recalcApproveHrs() {\n    const minsEl = document.getElementById(\"approveMins\");\n    const hrsEl = document.getElementById(\"approveHrs\");\n    if (!minsEl || !hrsEl) return;\n    const t = timeConvert(minsEl.value);\n    hrsEl.value = t.hour;\n    minsEl.value = t.minutes;\n  }\n  \n  \/\/ PHP parity: custom.js change handler on #approveStatus.\n  \/\/   Approved     \u00e2\u2020\u2019 approved time = utilized time, comment \"Approved\"\n  \/\/   Not Approved \u00e2\u2020\u2019 approved time = 0, comment \"Not Approved\"\n  function onApproveStatusChange() {\n    const statusEl = document.getElementById(\"approveStatus\");\n    const minsEl = document.getElementById(\"approveMins\");\n    const hrsEl = document.getElementById(\"approveHrs\");\n    const commentEl = document.getElementById(\"approveComment\");\n    if (!statusEl) return;\n    const label = (statusEl.options[statusEl.selectedIndex]?.text || \"\").trim();\n    if (label === \"Approved\") {\n      if (minsEl) minsEl.value = _approvalUtilized.mins;\n      if (hrsEl) hrsEl.value = _approvalUtilized.hrs;\n      if (commentEl) commentEl.value = \"Approved\";\n    } else if (label === \"Not Approved\") {\n      if (minsEl) minsEl.value = 0;\n      if (hrsEl) hrsEl.value = 0;\n      if (commentEl) commentEl.value = \"Not Approved\";\n    }\n  }\n  \n  function getFilterValue(id) {\n    const el = document.getElementById(id);\n    return el ? el.value : \"\";\n  }\n  \n  function getAssignedFilters() {\n    return {\n      entity_id: getFilterValue(\"filterEntity\"),\n      category_id: getFilterValue(\"filterCategory\"),\n      account_id: getFilterValue(\"filterAccount\"),\n      client_id: getFilterValue(\"filterClient\"),\n      project_id: getFilterValue(\"filterProject\"),\n      assigned_to: getFilterValue(\"filterAssignedTo\"),\n      assigned_date: getFilterValue(\"filterDate\"),\n      perPage: getFilterValue(\"filterPerPage\") || \"25\",\n    };\n  }\n  \n  function buildUnsubmittedUrl(page = 1) {\n    const filters = getAssignedFilters();\n    \/\/ RBAC: scope tells backend whether to return personal \/ team \/ all\n    const url = new URL(withScope(ENDPOINTS.UNSUBMITTED));\n    url.searchParams.set(\"page\", String(page));\n    url.searchParams.set(\"perPage\", String(filters.perPage));\n  \n    Object.entries(filters).forEach(([key, value]) => {\n      if (every(key !== \"perPage\", key !== \"assigned_date\", value !== \"\")) {\n        url.searchParams.set(key, value);\n      }\n    });\n  \n    if (filters.assigned_date) {\n      const datesParam = formatDatesParam(filters.assigned_date);\n      if (datesParam) {\n        url.searchParams.set(\"dates\", datesParam);\n      }\n    }\n  \n    return url;\n  }\n  \n  function appendAssignedExportFilters(url) {\n    const filters = getAssignedFilters();\n    Object.entries({\n      assigned_to: filters.assigned_to,\n      entity_id: filters.entity_id,\n      client_id: filters.client_id,\n      account_id: filters.account_id,\n      category_id: filters.category_id,\n      project_id: filters.project_id,\n    }).forEach(([key, value]) => {\n      if (value !== \"\") url.searchParams.set(key, value);\n    });\n    if (filters.assigned_date) {\n      const datesParam = formatDatesParam(filters.assigned_date);\n      if (datesParam) url.searchParams.set(\"dates\", datesParam);\n    }\n  }\n  \n  function buildAssignedExportUrl() {\n    const url = new URL(withScope(ENDPOINTS.ASSIGNED_EXPORT));\n    appendAssignedExportFilters(url);\n    return url;\n  }\n  \n  function appendAdhocExportFilters(url) {\n    const filters = getAdhocFilters();\n    if (filters.assigned_to) {\n      url.searchParams.set(\"assigned_to\", filters.assigned_to);\n    }\n    const allowedStatus = new Set([\n      \"pending\",\n      \"approve\",\n      \"not approve\",\n      \"0\",\n      \"1\",\n      \"all\",\n    ]);\n    if (both(allowedStatus.has(filters.status), filters.status !== \"all\")) {\n      url.searchParams.set(\"status\", filters.status);\n    }\n    if (filters.date) {\n      const datesParam = formatDatesParam(filters.date);\n      if (datesParam) url.searchParams.set(\"dates\", datesParam);\n    }\n  }\n  \n  function buildAdhocExportUrl() {\n    const url = new URL(withScope(ENDPOINTS.ADHOC_EXPORT));\n    appendAdhocExportFilters(url);\n    return url;\n  }\n  \n  function getAdhocFilters() {\n    return {\n      assigned_to: getFilterValue(\"filterAssignedToAdhoc\"),\n      status: getFilterValue(\"filterStatusAdhoc\") || \"all\",\n      date: getFilterValue(\"filterAdhocDate\"),\n      perPage: getFilterValue(\"filterPerPageAdhoc\") || \"25\",\n    };\n  }\n  \n  function isPositiveIntegerString(value) {\n    return both(\/^\\d+$\/.test(String(value)), Number(value) > 0);\n  }\n  \n  \/\/ Validates a date string is in YYYY-MM-DD format\n  function isValidISODate(str) {\n    return \/^\\d{4}-\\d{2}-\\d{2}$\/.test(str.trim());\n  }\n  \n  \/\/ Formats the dates filter value for the API.\n  \/\/ Picker outputs: \"YYYY-MM-DD - YYYY-MM-DD\" (range) or \"YYYY-MM-DD\" (single).\n  \/\/ API expects:    \"YYYY-MM-DD - YYYY-MM-DD\" (range) or \"YYYY-MM-DD\" (single).\n  function formatDatesParam(rawValue) {\n    if (!rawValue) return \"\";\n    const val = rawValue.trim();\n  \n    \/\/ Range format: \"YYYY-MM-DD - YYYY-MM-DD\"\n    if (val.includes(\" - \")) {\n      const parts = val.split(\" - \");\n      if (\n        every(\n          parts.length === 2,\n          isValidISODate(parts[0]),\n          isValidISODate(parts[1]),\n        )\n      ) {\n        return `${parts[0].trim()} to ${parts[1].trim()}`;\n      }\n      return \"\";\n    }\n  \n    \/\/ Already in \"YYYY-MM-DD to YYYY-MM-DD\" format (e.g. typed manually)\n    if (val.includes(\" to \")) {\n      const parts = val.split(\" to \");\n      if (\n        every(\n          parts.length === 2,\n          isValidISODate(parts[0]),\n          isValidISODate(parts[1]),\n        )\n      ) {\n        return `${parts[0].trim()} to ${parts[1].trim()}`;\n      }\n      return \"\";\n    }\n  \n    \/\/ Single date format: \"YYYY-MM-DD\"\n    if (isValidISODate(val)) {\n      return val;\n    }\n  \n    return \"\";\n  }\n  \n  function buildAdhocUrl(page = 1) {\n    const filters = getAdhocFilters();\n    \/\/ RBAC: scope tells backend whether to return personal \/ team \/ all\n    const url = new URL(withScope(ENDPOINTS.ADHOC_ALL));\n    const pageValue = isPositiveIntegerString(page) ? String(page) : \"1\";\n    const perPageValue = isPositiveIntegerString(filters.perPage)\n      ? String(filters.perPage)\n      : \"25\";\n  \n    url.searchParams.set(\"page\", pageValue);\n    url.searchParams.set(\"perPage\", perPageValue);\n  \n    if (filters.assigned_to) {\n      url.searchParams.set(\"assigned_to\", filters.assigned_to);\n    }\n  \n    const allowedStatus = new Set([\n      \"pending\",\n      \"approve\",\n      \"not approve\",\n      \"0\",\n      \"1\",\n      \"all\",\n    ]);\n    if (both(allowedStatus.has(filters.status), filters.status !== \"all\")) {\n      url.searchParams.set(\"status\", filters.status);\n    }\n  \n    if (filters.date) {\n      const datesParam = formatDatesParam(filters.date);\n      if (datesParam) {\n        url.searchParams.set(\"dates\", datesParam);\n      }\n    }\n    return url;\n  }\n  \n  function clearAssignedFilters() {\n    const selectIds = [\n      \"filterAssignedTo\",\n      \"filterEntity\",\n      \"filterClient\",\n      \"filterAccount\",\n      \"filterCategory\",\n      \"filterProject\",\n    ];\n    selectIds.forEach((id) => {\n      const el = document.getElementById(id);\n      if (el) el.value = \"\";\n  \n      const wrapper = document.getElementById(\"csWrapper_\" + id);\n      if (wrapper) {\n        const trigger = wrapper.querySelector(\".custom-select-trigger\");\n        const labelEl = trigger.querySelector(\".cs-label\");\n        const placeholder = wrapper.querySelector(\".placeholder-option\");\n        const phText = placeholder\n          ? placeholder.querySelector(\".opt-label\").textContent.trim()\n          : \"Select\";\n        \/\/ Rebuild integrated search input so the field stays searchable after reset\n        labelEl.innerHTML = `<input type=\"text\" class=\"cs-search-input\" id=\"csInput_${id}\" placeholder=\"${phText}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('${id}', this.value)\" onkeydown=\"csKeyDown(event, '${id}')\" onclick=\"csOpenDropdown('${id}'); event.stopPropagation();\" onfocus=\"csOpenDropdown('${id}')\">`;\n        trigger.classList.add(\"placeholder-shown\");\n        wrapper\n          .querySelectorAll(\".custom-select-option\")\n          .forEach((o) => o.classList.remove(\"selected\"));\n        \/\/ Make sure all options are visible again after a reset\n        wrapper.querySelectorAll(\".custom-select-option\").forEach((o) => {\n          o.style.display = \"\";\n        });\n      }\n    });\n  \n    const dateEl = document.getElementById(\"filterDate\");\n    if (dateEl) dateEl.value = \"\";\n  \n    \/\/ Also clear the date picker state\n    [\"assigned\", \"adhoc\"].forEach((inst) => {\n      if (both(dpState, dpState[inst])) {\n        dpState[inst].startDate = null;\n        dpState[inst].endDate = null;\n        dpState[inst].hoverDate = null;\n        dpState[inst].activePreset = null;\n        dpState[inst].selectedDate = null;\n        try {\n          dpUpdateFooterRange(inst);\n        } catch (e) {}\n        try {\n          dpRenderCalendar(inst);\n        } catch (e) {}\n      }\n    });\n  \n    const perPageEl = document.getElementById(\"filterPerPage\");\n    if (perPageEl) perPageEl.value = \"25\";\n  \n    currentPage = 1;\n    fetchTableData(1);\n  }\n  \n  function clearAdhocFilters() {\n    const assignedEl = document.getElementById(\"filterAssignedToAdhoc\");\n    if (assignedEl) {\n      assignedEl.value = \"\";\n      const wrapper = document.getElementById(\"csWrapper_filterAssignedToAdhoc\");\n      if (wrapper) {\n        const trigger = wrapper.querySelector(\".custom-select-trigger\");\n        const labelEl = trigger.querySelector(\".cs-label\");\n        const placeholder = wrapper.querySelector(\".placeholder-option\");\n        const phText = placeholder\n          ? placeholder.querySelector(\".opt-label\").textContent.trim()\n          : \"Select\";\n        \/\/ Rebuild integrated search input so the field stays searchable after reset\n        labelEl.innerHTML = `<input type=\"text\" class=\"cs-search-input\" id=\"csInput_filterAssignedToAdhoc\" placeholder=\"${phText}\" autocomplete=\"off\" oninput=\"csIntegratedFilter('filterAssignedToAdhoc', this.value)\" onkeydown=\"csKeyDown(event, 'filterAssignedToAdhoc')\" onclick=\"csOpenDropdown('filterAssignedToAdhoc'); event.stopPropagation();\" onfocus=\"csOpenDropdown('filterAssignedToAdhoc')\">`;\n        trigger.classList.add(\"placeholder-shown\");\n        wrapper\n          .querySelectorAll(\".custom-select-option\")\n          .forEach((o) => o.classList.remove(\"selected\"));\n        \/\/ Make sure all options are visible again after a reset\n        wrapper.querySelectorAll(\".custom-select-option\").forEach((o) => {\n          o.style.display = \"\";\n        });\n      }\n    }\n  \n    const statusEl = document.getElementById(\"filterStatusAdhoc\");\n    if (statusEl) statusEl.value = \"all\";\n  \n    const dateEl = document.getElementById(\"filterAdhocDate\");\n    if (dateEl) dateEl.value = \"\";\n  \n    \/\/ Also clear the date picker state\n    [\"assigned\", \"adhoc\"].forEach((inst) => {\n      if (both(dpState, dpState[inst])) {\n        dpState[inst].startDate = null;\n        dpState[inst].endDate = null;\n        dpState[inst].hoverDate = null;\n        dpState[inst].activePreset = null;\n        dpState[inst].selectedDate = null;\n        try {\n          dpUpdateFooterRange(inst);\n        } catch (e) {}\n        try {\n          dpRenderCalendar(inst);\n        } catch (e) {}\n      }\n    });\n  \n    const perPageEl = document.getElementById(\"filterPerPageAdhoc\");\n    if (perPageEl) perPageEl.value = \"25\";\n  \n    currentPage = 1;\n    fetchAdhocTableData(1);\n  }\n  \n  function handleActionClick(action) {\n    if (action === \"Filter\") {\n      if (activeView === \"assigned\") {\n        fetchTableData(1);\n      } else {\n        fetchAdhocTableData(1);\n      }\n      return;\n    }\n  \n    if (action === \"Clear\" || action === \"Close\") {\n      if (activeView === \"assigned\") {\n        clearAssignedFilters();\n      } else {\n        clearAdhocFilters();\n      }\n      return;\n    }\n  \n    if (action === \"+ Add New Assignment\") {\n      if (!CAN_ADD) {\n        alert(\"Access denied: you do not have permission to add assignments.\");\n        return;\n      }\n      window.location.href =\n        \"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/assign-work\/\";\n      return;\n    }\n  \n    if (action === \"+ CSV Import\") {\n      if (activeView === \"assigned\") {\n        window.location.href =\n          \"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/import-assignment-data\/\";\n      } else {\n        window.location.href =\n          \"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/import-adhoc-data\/\";\n      }\n      return;\n    }\n  \n    if (action === \"+ CSV Download\") {\n      downloadCSV();\n      return;\n    }\n  \n    if (action === \"+ Add Adhoc\" || action === \"+ Add Ad Hoc\") {\n      openAddAdHocModal();\n      return;\n    }\n  \n    if (action === \"Approve All\") {\n      if (!CAN_BULK_ADHOC) {\n        alert(\n          \"Access denied: you do not have permission to bulk approve ad hoc assignments.\",\n        );\n        return;\n      }\n      approveAllAdhoc();\n      return;\n    }\n  \n    if (action === \"Reset All\") {\n      if (!CAN_BULK_ADHOC) {\n        alert(\n          \"Access denied: you do not have permission to bulk reset ad hoc assignments.\",\n        );\n        return;\n      }\n      resetAllAdhoc();\n      return;\n    }\n  }\n  \n  \/* \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac CSV IMPORT \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac *\/\n  function handleCSVImport(event) {\n    const file = event.target.files[0];\n    if (!file) return;\n    if (!file.name.toLowerCase().endsWith(\".csv\")) {\n      alert(\"Please select a valid .csv file.\");\n      return;\n    }\n  \n    const reader = new FileReader();\n    reader.onload = function (e) {\n      const text = e.target.result;\n      const lines = text.trim().split(\"\\n\");\n      if (lines.length < 2) {\n        alert(\"CSV file is empty or has no data rows.\");\n        return;\n      }\n  \n      const headerRow = lines[0]\n        .split(\",\")\n        .map((h) => h.trim().replace(\/^\"|\"$\/g, \"\"));\n      const dataRows = lines\n        .slice(1)\n        .map((line) => {\n          return line.split(\",\").map((cell) => cell.trim().replace(\/^\"|\"$\/g, \"\"));\n        })\n        .filter((row) => row.some((cell) => cell !== \"\"));\n  \n      if (dataRows.length === 0) {\n        alert(\"No data rows found in CSV.\");\n        return;\n      }\n  \n      document.getElementById(\"tblHead\").innerHTML =\n        `<tr>${headerRow.map((h) => `<th>${h}<\/th>`).join(\"\")}<\/tr>`;\n      document.getElementById(\"tblBody\").innerHTML = dataRows\n        .map(\n          (row) =>\n            `<tr>${row.map((cell) => `<td>${cell || \"-\"}<\/td>`).join(\"\")}<\/tr>`,\n        )\n        .join(\"\");\n  \n      updatePaginationDisplay(\n        { total: dataRows.length, pages: 1, perPage: dataRows.length },\n        1,\n      );\n      alert(`CSV imported successfully: ${dataRows.length} row(s) loaded.`);\n    };\n    reader.onerror = function () {\n      alert(\"Failed to read the CSV file.\");\n    };\n    reader.readAsText(file);\n  }\n  \n  \/* \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac CSV DOWNLOAD (PHP parity: work_assignment\/export + ad_hoc_assignment\/export) \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac *\/\n  async function downloadCSV() {\n    const btn =\n      document.querySelector(\".action-bar .btn-primary:last-of-type\") ||\n      Array.from(document.querySelectorAll(\".action-bar button\")).find((b) =>\n        (b.textContent || \"\").includes(\"CSV Download\"),\n      );\n    const origHtml = btn ? btn.innerHTML : \"\";\n  \n    if (btn) {\n      btn.disabled = true;\n      btn.innerHTML = \"Downloading...\";\n    }\n  \n    try {\n      const token = getAuthToken();\n      if (!token) {\n        alert(\"You are not logged in. Please login again.\");\n        return;\n      }\n  \n      const exportUrl =\n        activeView === \"assigned\"\n          ? buildAssignedExportUrl()\n          : buildAdhocExportUrl();\n  \n      const res = await fetch(exportUrl.toString(), {\n        method: \"GET\",\n        headers: { Authorization: \"Bearer \" + token },\n      });\n  \n      if (handleAuthError(res)) return;\n  \n      if (!res.ok) {\n        let message = \"Failed to download CSV.\";\n        try {\n          const errJson = await res.json();\n          message =\n            errJson.message ||\n            (both(errJson.messages, errJson.messages[0])) ||\n            message;\n        } catch (_) {\n          message = message + \" (HTTP \" + res.status + \")\";\n        }\n        alert(message);\n        return;\n      }\n  \n      const blob = await res.blob();\n      if (!blob || blob.size === 0) {\n        alert(\"No data available to export for the selected filters.\");\n        return;\n      }\n  \n      let filename =\n        activeView === \"assigned\"\n          ? \"work-assignment-\" + Date.now() + \".csv\"\n          : \"allAdHocAssignment_\" +\n            new Date().toLocaleString(\"en-US\", { month: \"short\" }) +\n            \".csv\";\n      const disposition = res.headers.get(\"Content-Disposition\");\n      if (disposition) {\n        const match = disposition.match(\/filename=\"?([^\";\\n]+)\"?\/i);\n        if (both(match, match[1])) filename = match[1].trim();\n      }\n  \n      const objectUrl = URL.createObjectURL(blob);\n      const link = document.createElement(\"a\");\n      link.href = objectUrl;\n      link.download = filename;\n      document.body.appendChild(link);\n      link.click();\n      document.body.removeChild(link);\n      URL.revokeObjectURL(objectUrl);\n    } catch (err) {\n      console.error(\"CSV Download Error:\", err);\n      alert(\"Failed to download CSV. Please try again.\");\n    } finally {\n      if (btn) {\n        btn.disabled = false;\n        btn.innerHTML = origHtml;\n      }\n    }\n  }\n  \n  function headerToKey(header) {\n    const map = {\n      \"Assigned Date\": \"assigned_date\",\n      Hrs: \"hours\",\n      \"Assigned To\": \"assigned_to_name\",\n      \"Pseudo Name\": \"pesudo_name\",\n      \"File Name\": \"file_name\",\n      \"Received On\": \"received_on\",\n      Insurance: \"insurance_name\",\n      Account: \"account_name\",\n      Project: \"project_name\",\n      Entity: \"entity_name\",\n      Client: \"client_name\",\n      Category: \"category_name\",\n      \"Assigned DOS\": \"assigned_dos\",\n      Pages: \"pages\",\n      DOS: \"dos_count\",\n      Amount: \"amount\",\n      \"DOS Completed\": \"dos_completed\",\n      \"Pending DOS\": \"pending_dos\",\n      Remarks: \"remarks\",\n      Date: \"date\",\n      \"Work Type\": \"ad_hoc_work_type\",\n      \"Desc.\": \"description\",\n      Comments: \"comments\",\n      \"Time Utilized\": \"time_utilized_display\",\n      \"Time Approved\": \"time_approved_display\",\n      \"Created By\": \"created_by_name\",\n      \"Updated By\": \"approved_by_name\",\n      \"Updated At\": \"updated_at\",\n    };\n    return map[header] || header.toLowerCase().replace(\/\\s+\/g, \"_\");\n  }\n  \n  \/* \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac PAGINATION RENDER \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac *\/\n  function updatePagination(meta) {\n    const container = document.getElementById(\"pageNumbers\");\n    container.innerHTML = \"\";\n  \n    const total = Number(meta.total) || 0;\n    const perPage = Number(meta.perPage || meta.limit || meta.per_page) || 25;\n    const totalPages = Math.ceil(total \/ perPage) || 1;\n    const current = currentPage;\n  \n    const startEntry = total === 0 ? 0 : (current - 1) * perPage + 1;\n    const endEntry = Math.min(current * perPage, total);\n    document.getElementById(\"entryInfo\").textContent =\n      `Showing ${startEntry} to ${endEntry} of ${total} entries`;\n  \n    const maxVisible = 5;\n    let startPage = Math.max(1, current - Math.floor(maxVisible \/ 2));\n    let endPage = Math.min(totalPages, startPage + maxVisible - 1);\n  \n    if (endPage - startPage + 1 < maxVisible) {\n      startPage = Math.max(1, endPage - maxVisible + 1);\n    }\n  \n    \/\/ First page + ellipsis\n    if (startPage > 1) {\n      appendPageItem(container, 1, current);\n      if (startPage > 2) appendEllipsis(container);\n    }\n  \n    \/\/ Middle pages\n    for (let i = startPage; i <= endPage; i++) {\n      appendPageItem(container, i, current);\n    }\n  \n    \/\/ Ellipsis + last page\n    if (endPage < totalPages) {\n      if (endPage < totalPages - 1) appendEllipsis(container);\n      appendPageItem(container, totalPages, current);\n    }\n  \n    const prevBtn = document.getElementById(\"prevBtn\");\n    const nextBtn = document.getElementById(\"nextBtn\");\n  \n    prevBtn.className = `nav-link ${current === 1 ? \"disabled\" : \"\"}`;\n    nextBtn.className = `nav-link ${current === totalPages || totalPages === 0 ? \"disabled\" : \"\"}`;\n  \n    prevBtn.onclick = () => {\n      if (currentPage > 1) {\n        currentPage--;\n        triggerFetch();\n      }\n    };\n    nextBtn.onclick = () => {\n      if (currentPage < totalPages) {\n        currentPage++;\n        triggerFetch();\n      }\n    };\n  }\n  \n  function appendPageItem(container, pageNum, activePage) {\n    const p = document.createElement(\"div\");\n    p.className = `page-item ${pageNum === activePage ? \"active\" : \"\"}`;\n    p.textContent = pageNum;\n    p.onclick = () => {\n      currentPage = pageNum;\n      triggerFetch();\n    };\n    container.appendChild(p);\n  }\n  \n  function appendEllipsis(container) {\n    const el = document.createElement(\"div\");\n    el.className = \"page-item\";\n    el.textContent = \"...\";\n    el.style.cursor = \"default\";\n    container.appendChild(el);\n  }\n  \n  function triggerFetch() {\n    if (activeView === \"assigned\") fetchTableData(currentPage);\n    else fetchAdhocTableData(currentPage);\n  }\n  \n  function updatePaginationDisplay(meta, page) {\n    currentPage = page;\n    updatePagination(meta);\n  }\n  \n  async function fetchTableData(page = 1) {\n    if (activeView !== \"assigned\") return;\n    const url = buildUnsubmittedUrl(page);\n  \n    try {\n      const res = await fetch(url.toString(), { headers: getHeaders() });\n      if (handleAuthError(res)) return;\n      const json = await res.json();\n      const rows = Array.isArray(json?.data?.data) ? json.data.data : [];\n      lastFetchedRows = rows;\n  \n      if (rows.length === 0) {\n        document.getElementById(\"tblBody\").innerHTML =\n          '<tr><td colspan=\"14\" style=\"text-align:center;\">No data found<\/td><\/tr>';\n        updatePaginationDisplay({ total: 0, pages: 1, perPage: 25 }, 1);\n        return;\n      }\n  \n      document.getElementById(\"tblBody\").innerHTML = rows\n        .map(\n          (row) => `\n                  <tr>\n                      <td>${safeText(getOnlyDate(row.assigned_date))}<\/td>\n                      <td>${formatTableHours(row.hours)}<\/td>\n                      <td>${safeText(row.assigned_to_name)}<\/td>\n                      <td>${safeText(row.pesudo_name)}<\/td>\n                      <td>${safeText(row.file_name)}<\/td>\n                      <td>${safeText(getOnlyDate(row.received_on))}<\/td>\n                      <td>${safeText(row.insurance_name)}<\/td>\n                      <td>${safeText(row.account_name)}<\/td>\n                      <td>${safeText(row.project_name)}<\/td>\n                      <td>${safeText(row.entity_name)}<\/td>\n                      <td><span class=\"entity-badge\">${safeText(row.client_name)}<\/span><\/td>\n                      <td>${safeText(row.category_name)}<\/td>\n                      <td>${safeText(row.assigned_dos)}<\/td>\n                      <td>\n                          <div style=\"display: flex; gap: 8px;\">\n                              ${\n                                CAN_EDIT\n                                  ? `\n                              <button class=\"edit-icon-btn\" onclick=\"openEditModal('assigned', ${Number(row.id) || 0})\" title=\"Edit\">\n                                  ${editIconSVG}<span class=\"edit-label\">Edit<\/span>\n                              <\/button>`\n                                  : \"\"\n                              }\n                              ${\n                                !IS_ADMIN\n                                  ? `\n                              <button class=\"edit-icon-btn\" onclick=\"openSubmitModal(${Number(row.id) || 0})\" title=\"Submit\">\n                                  ${editIconSVG}<span class=\"edit-label\">Submit<\/span>\n                              <\/button>`\n                                  : \"\"\n                              }\n                              ${both(!CAN_EDIT, IS_ADMIN) ? `<span style=\"color: var(--text-muted); font-size: 12px;\">\u00e2\u20ac\u201d<\/span>` : \"\"}\n                          <\/div>\n                      <\/td>\n                  <\/tr>\n              `,\n        )\n        .join(\"\");\n  \n      const meta = {\n        total: json?.data?.total || json?.data?.pagination?.total || rows.length,\n        pages:\n          json?.data?.pages ||\n          json?.data?.pagination?.pages ||\n          json?.data?.last_page ||\n          1,\n        perPage:\n          json?.data?.perPage ||\n          json?.data?.pagination?.limit ||\n          json?.data?.per_page ||\n          25,\n      };\n      updatePaginationDisplay(meta, page);\n    } catch (error) {\n      console.error(\"Un-submitted fetch error\", error);\n      document.getElementById(\"tblBody\").innerHTML =\n        '<tr><td colspan=\"14\" style=\"text-align:center;\">Failed to load data<\/td><\/tr>';\n    }\n  }\n  \n  async function fetchAdhocTableData(page = 1) {\n    if (activeView !== \"adhoc\") return;\n    const url = buildAdhocUrl(page);\n  \n    try {\n      const res = await fetch(url.toString(), { headers: getHeaders() });\n      if (handleAuthError(res)) return;\n      const json = await res.json();\n      const rows = Array.isArray(json?.data?.rows) ? json.data.rows : [];\n      lastFetchedRows = rows;\n  \n      if (!rows.length) {\n        document.getElementById(\"tblBody\").innerHTML =\n          `<tr><td colspan=\"${getAdhocTableColspan()}\" style=\"text-align:center;\">No data found<\/td><\/tr>`;\n        updatePaginationDisplay({ total: 0, pages: 1, perPage: 25 }, 1);\n        return;\n      }\n  \n      document.getElementById(\"tblBody\").innerHTML = rows\n        .map((row) => {\n          \/\/ \u00e2\u201d\u20ac\u00e2\u201d\u20ac STATUS: derive the freshest possible label & class \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\n          \/\/ Backend may return: status_text ('Approved'\/'Pending'\/'Not Approved'),\n          \/\/ status (string), or is_approved (0\/1). Prefer the most specific.\n          const rawStatus = String(row.status_text || row.status || \"\")\n            .trim()\n            .toLowerCase();\n          const isApprovedRow =\n            rawStatus === \"approved\" ||\n            rawStatus === \"approve\" ||\n            Number(row.is_approved) === 1;\n          const isNotApprovedRow =\n            rawStatus === \"not approved\" ||\n            rawStatus === \"not approve\" ||\n            Number(row.is_approved) === 2;\n          const statusClass = isApprovedRow\n            ? \"approved\"\n            : isNotApprovedRow\n              ? \"not-approved\"\n              : \"pending\";\n          const statusLabel = isApprovedRow\n            ? \"Approved\"\n            : isNotApprovedRow\n              ? \"Not Approved\"\n              : row.status_text || row.status || \"Pending\";\n  \n          \/\/ \u00e2\u201d\u20ac\u00e2\u201d\u20ac UPDATED BY: prefer explicit updated_by fields; fall back to approver \u00e2\u201d\u20ac\n          const updatedBy =\n            row.updated_by_name ||\n            row.updated_by ||\n            row.modified_by_name ||\n            row.approved_by_name ||\n            \"\";\n  \n          return `\n                  <tr>\n                      <td>${safeText(row.date)}<\/td>\n                      <td>${safeText(row.client_name)}<\/td>\n                      <td>${safeText(row.project_name)}<\/td>\n                      <td style=\"white-space: normal; word-break: break-word; min-width: 150px;\">${safeText(row.ad_hoc_work_type)}<\/td>\n                      <td style=\"white-space: normal; word-break: break-word; min-width: 250px;\">${safeText(row.description)}<\/td>\n                      <td>${safeText(row.comments)}<\/td>\n                      <td>${safeText(formatAdhocDecimal(row.time_utilized_display || row.time_utilized_decimal))}<\/td>\n                      <td>${safeText(formatAdhocDecimal(row.time_approved_display || row.time_approved_decimal))}<\/td>\n                      <td>${safeText(row.created_by_name)}<\/td>\n                      <td>${safeText(updatedBy)}<\/td>\n                      <td>${safeText(getOnlyDate(row.updated_at || row.approved_at))}<\/td>\n                      <td>\n                          <div class=\"action-stack\">\n                              ${\n                                canEditAdhocRow(row)\n                                  ? `\n                              <button class=\"edit-icon-btn\" onclick=\"openEditModal('adhoc', ${Number(row.id) || 0})\" title=\"Edit\">\n                                  ${editIconSVG}<span class=\"edit-label\">Edit<\/span>\n                              <\/button>`\n                                  : ``\n                              }\n                              ${\n                                statusClass === \"pending\"\n                                  ? canApproveAdhocRow(row)\n                                    ? `<span class=\"status-pill pending\" style=\"cursor: pointer;\" onclick=\"openApprovalModal(${Number(row.id) || 0})\">${safeText(statusLabel)}<\/span>`\n                                    : `<span class=\"status-pill pending\">${safeText(statusLabel)}<\/span>`\n                                  : `<span class=\"status-pill ${statusClass}\">${safeText(statusLabel)}<\/span>`\n                              }\n                          <\/div>\n                      <\/td>\n                      ${\n                        CAN_BULK_ADHOC\n                          ? `\n                      <td class=\"adhoc-select-col\">\n                          <input type=\"checkbox\" class=\"adhoc-bulk-checkbox adhoc-id-checkbox\" name=\"adhoc_id[]\" value=\"${Number(row.id) || 0}\" onchange=\"syncAdhocSelectAll()\">\n                      <\/td>`\n                          : \"\"\n                      }\n                  <\/tr>\n              `;\n        })\n        .join(\"\");\n      syncAdhocSelectAll();\n  \n      const meta = {\n        total: json?.data?.total || json?.data?.pagination?.total || rows.length,\n        pages:\n          json?.data?.pages ||\n          json?.data?.pagination?.pages ||\n          json?.data?.last_page ||\n          1,\n        perPage:\n          json?.data?.perPage ||\n          json?.data?.pagination?.limit ||\n          json?.data?.per_page ||\n          25,\n      };\n      updatePaginationDisplay(meta, page);\n    } catch (error) {\n      console.error(\"Adhoc fetch error\", error);\n      document.getElementById(\"tblBody\").innerHTML =\n        `<tr><td colspan=\"${getAdhocTableColspan()}\" style=\"text-align:center;\">Failed to load data<\/td><\/tr>`;\n    }\n  }\n  \n  function toggleTab(view) {\n    activeView = view;\n    lastFetchedRows = [];\n    document\n      .getElementById(\"tab-assigned\")\n      .classList.toggle(\"active\", view === \"assigned\");\n    document\n      .getElementById(\"tab-adhoc\")\n      .classList.toggle(\"active\", view === \"adhoc\");\n    renderUI();\n    if (view === \"adhoc\") {\n      fetchAdhocTableData(1);\n    } else {\n      fetchTableData();\n    }\n  }\n  \n  \/\/ Currently editing record id (stored for update calls)\n  let _editingAssignedId = null;\n  let _editingAssignedRow = null;\n\nfunction parseFormInt(value) {\n  if (value === \"\" || value === null || value === undefined) return null;\n  const n = parseInt(String(value), 10);\n  return Number.isNaN(n) ? null : n;\n}\n\nfunction resolveEditFileId() {\n  const fromInput = document.getElementById(\"editFileId\")?.value;\n  if (fromInput !== \"\" && fromInput != null) {\n    const parsed = parseFormInt(fromInput);\n    if (parsed != null) return parsed;\n  }\n  const fromRow = _editingAssignedRow?.file_id ?? _editingAssignedRow?.file?.id;\n  if (fromRow !== \"\" && fromRow != null) {\n    const parsed = parseFormInt(fromRow);\n    if (parsed != null) return parsed;\n  }\n  return null;\n}\n  let _editingAdhocId = null;\n  let _editingAdhocRow = null;\n  let _currentEditBenchmark = 0;\n  let _currentSubmitBenchmark = 0;\n  let _currentSubmitAssignedDos = 0;\n  \n  function calculateHoursEdit() {\n    const assignedDos =\n      parseFloat(document.getElementById(\"editAssignedDos\").value) || 0;\n    const benchmark = _currentEditBenchmark || 0;\n  \n    if (both(benchmark, benchmark > 0)) {\n      const hours = assignedDos \/ benchmark;\n      document.getElementById(\"editHours\").value =\n        hours % 1 === 0 ? hours : hours.toFixed(2);\n    } else {\n      document.getElementById(\"editHours\").value = 0;\n    }\n  }\n  \n  async function fetchEditAccountBenchmark(accountId) {\n    if (!accountId) {\n      _currentEditBenchmark = 0;\n      calculateHoursEdit();\n      return;\n    }\n    try {\n      const res = await fetch(ENDPOINTS.ACCOUNT_DETAIL, {\n        method: \"POST\",\n        headers: getHeaders(),\n        body: JSON.stringify({ id: parseInt(accountId, 10) }),\n      });\n      if (handleAuthError(res, { logoutOnUnauthorized: false })) return;\n      const result = await res.json();\n      if (result.code === 200) {\n        _currentEditBenchmark = result.data.operational_benchmark || 0;\n        calculateHoursEdit();\n      }\n    } catch (err) {\n      console.error(\"Account Detail Error:\", err);\n      _currentEditBenchmark = 0;\n    }\n  }\n  \n  \/\/ \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac SUBMIT ASSIGNMENT: HOURS + PENDING (PHP munvalueSubmitted parity) \u00e2\u201d\u20ac\n  \/\/   pending = assigned_dos - dos_complete (min 0)\n  \/\/   hours   = dos_complete \/ operational_benchmark\n  function calculateHoursSubmit() {\n    const dosCompletedEl = document.getElementById(\"submitDosCompleted\");\n    const hoursEl = document.getElementById(\"submitHours\");\n    const pendingEl = document.getElementById(\"submitPendingDos\");\n    if (!dosCompletedEl || !hoursEl || !pendingEl) return;\n  \n    const raw = String(dosCompletedEl.value ?? \"\").trim();\n    if (!raw) {\n      hoursEl.value = \"\";\n      pendingEl.value = \"\";\n      return;\n    }\n  \n    const dosCompleted = parseFloat(raw) || 0;\n    const assignedDos = _currentSubmitAssignedDos || 0;\n    pendingEl.value = Math.max(0, assignedDos - dosCompleted);\n  \n    const benchmark = _currentSubmitBenchmark || 0;\n    if (benchmark > 0) {\n      const hours = dosCompleted \/ benchmark;\n      hoursEl.value = hours % 1 === 0 ? String(hours) : hours.toFixed(2);\n    } else {\n      hoursEl.value = \"\";\n    }\n  }\n  \n  function resolveSubmitHours() {\n    calculateHoursSubmit();\n    const raw = String(\n      document.getElementById(\"submitHours\")?.value ?? \"\",\n    ).trim();\n    if (both(raw !== \"\", !isNaN(parseFloat(raw)))) {\n      return parseFloat(raw);\n    }\n    const dosCompleted =\n      parseFloat(document.getElementById(\"submitDosCompleted\")?.value) || 0;\n    const benchmark = _currentSubmitBenchmark || 0;\n    if (both(benchmark > 0, dosCompleted > 0)) {\n      return parseFloat((dosCompleted \/ benchmark).toFixed(4));\n    }\n    return 0;\n  }\n  \n  async function fetchSubmitAccountBenchmark(accountId) {\n    if (!accountId) {\n      _currentSubmitBenchmark = 0;\n      calculateHoursSubmit();\n      return;\n    }\n    try {\n      const res = await fetch(ENDPOINTS.ACCOUNT_DETAIL, {\n        method: \"POST\",\n        headers: getHeaders(),\n        body: JSON.stringify({ id: parseInt(accountId, 10) }),\n      });\n      if (handleAuthError(res, { logoutOnUnauthorized: false })) return;\n      const result = await res.json();\n      if (result.code === 200) {\n        _currentSubmitBenchmark = result.data.operational_benchmark || 0;\n        calculateHoursSubmit();\n      }\n    } catch (err) {\n      console.error(\"Account Detail Error:\", err);\n      _currentSubmitBenchmark = 0;\n    }\n  }\n  \n  async function openEditModal(type, id) {\n    \/\/ Assigned edit is gated by the global edit capability.\n    \/\/ Ad hoc edit is gated per-row (PHP parity) once the record is loaded below,\n    \/\/ so a user can always edit their OWN pending ad hoc.\n    if (both(type === \"assigned\", !CAN_EDIT)) {\n      alert(\"Access denied: you do not have permission to edit assignments.\");\n      return;\n    }\n  \n    const buildOptions = (data, valueKey, labelKey, selectedValue) =>\n      buildSelectOptions(data, valueKey, labelKey, selectedValue);\n\n    if (type === \"assigned\") {\n      _editingAssignedId = id;\n  \n      \/\/ Try to fetch the record detail from the API\n      let row = null;\n      try {\n        const res = await fetchWorkAssignmentDetail(id);\n        if (res.status === 401) {\n          \/\/ Fall back to table row without logging out (list data already loaded).\n        } else if (handleAuthError(res)) {\n          return;\n        }\n        if (res.ok) {\n          const json = await res.json();\n          row = json?.data?.id ? json.data : json?.data?.data || json;\n        }\n      } catch (e) {\n        \/* ignore, try fallback *\/\n      }\n  \n      \/\/ Fallback: find in already-fetched table rows\n      if (!row || !row.id) {\n        row = lastFetchedRows.find((r) => String(r.id) === String(id)) || null;\n      }\n  \n      if (!row) {\n        alert(\"Could not load assignment data. Please try again.\");\n        return;\n      }\n\n      row = normalizeAssignmentRow(row);\n      _editingAssignedRow = row;\n  \n      document.getElementById(\"assignedModalFields\").innerHTML = `\n                <input type=\"hidden\" id=\"editFileId\" value=\"${row.file_id ?? \"\"}\">\n                  <input type=\"hidden\" id=\"editFileFieldEdit\" value=\"${row.file_id || \"\"}\">\n                  <div class=\"form-group\"><label class=\"required\">Assigned Date<\/label>\n                      <input type=\"date\" class=\"form-control\" id=\"editAssignedDate\" value=\"${formatDate(row.assigned_date)}\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Assigned To<\/label>\n                      <select class=\"form-control\" id=\"editAssignedTo\">\n                          <option value=\"\">Select User<\/option>\n                          ${buildGroupedUserSelectOptions(\n                            row.assigned_to,\n                            row.pesudo_name || row.assigned_to_name,\n                          )}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Received On<\/label>\n                      <input type=\"date\" class=\"form-control\" id=\"editReceivedOn\" value=\"${formatDate(row.received_on)}\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">File Name<\/label>\n                      <input type=\"text\" class=\"form-control\" id=\"editFileName\" value=\"${safeText(row.file_name || \"\")}\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Insurance<\/label>\n                      <select class=\"form-control\" id=\"editInsurance\">\n                          <option value=\"\">Select Insurance<\/option>\n                          ${buildOptions(dropDownData.insurances, \"id\", \"name\", row.insurance_id)}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Account<\/label>\n                      <select class=\"form-control\" id=\"editAccount\">\n                          <option value=\"\">Select Account<\/option>\n                          ${buildSelectOptions(\n                            dropDownData.accounts,\n                            \"id\",\n                            \"name\",\n                            row.account_id,\n                            row.account_name || row.account?.name,\n                          )}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Client<\/label>\n                      <select class=\"form-control\" id=\"editClient\">\n                          <option value=\"\">Select Client<\/option>\n                          ${buildOptions(dropDownData.clients, \"id\", \"name\", row.client_id)}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Category<\/label>\n                      <select class=\"form-control\" id=\"editCategory\">\n                          <option value=\"\">Select Category<\/option>\n                          ${buildOptions(dropDownData.categories, \"id\", \"category\", row.category_id)}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Project<\/label>\n                      <select class=\"form-control\" id=\"editProject\">\n                          <option value=\"\">Select Project<\/option>\n                          ${buildOptions(dropDownData.projects, \"id\", \"name\", row.project_id)}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Project Type<\/label>\n                      <select class=\"form-control\" id=\"editProjectType\">\n                          <option value=\"\">Select Project Type<\/option>\n                          ${buildOptions(dropDownData.projectTypes, \"id\", \"type\", row.project_type_id)}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Entity<\/label>\n                      <select class=\"form-control\" id=\"editEntity\">\n                          <option value=\"\">Select Entity<\/option>\n                          ${buildOptions(dropDownData.entities, \"id\", \"entity\", row.entity_id)}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Amount<\/label>\n                      <input type=\"number\" class=\"form-control\" id=\"editAmount\" value=\"${row.amount ?? 0}\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Pages<\/label>\n                      <input type=\"number\" class=\"form-control\" id=\"editPages\" value=\"${row.pages ?? 1}\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Dos Count<\/label>\n                      <input type=\"number\" class=\"form-control\" id=\"editDosCount\" value=\"${row.dos_count ?? 0}\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Assigned DOS<\/label>\n                      <input type=\"number\" class=\"form-control\" id=\"editAssignedDos\" value=\"${row.assigned_dos ?? 0}\" oninput=\"calculateHoursEdit()\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Hours<\/label>\n                      <input type=\"number\" step=\"0.01\" class=\"form-control\" id=\"editHours\" value=\"${row.hours ?? 0}\">\n                  <\/div>\n              `;\n      document.getElementById(\"modalAssigned\").style.display = \"flex\";\n  \n      \/\/ Initial benchmark fetch for the existing account\n      const initialAccountId =\n        row.account_id || document.getElementById(\"editAccount\").value;\n      if (initialAccountId) {\n        fetchEditAccountBenchmark(initialAccountId);\n      }\n  \n      \/\/ Add listener to account change in modal\n      document.getElementById(\"editAccount\").addEventListener(\"change\", (e) => {\n        fetchEditAccountBenchmark(e.target.value);\n      });\n    } else {\n      _editingAdhocId = id;\n  \n      \/\/ Try to fetch the ad hoc record detail from the API\n      let row = null;\n      try {\n        const res = await fetchAdHocDetail(id);\n        if (handleAuthError(res)) return;\n        if (res.ok) {\n          const json = await res.json();\n          row = json?.data?.id ? json.data : json?.data?.data || json;\n        }\n      } catch (e) {\n        \/* ignore, try fallback *\/\n      }\n  \n      \/\/ Fallback: find in already-fetched table rows\n      if (!row || !row.id) {\n        row = lastFetchedRows.find((r) => String(r.id) === String(id)) || null;\n      }\n  \n      if (!row) {\n        alert(\"Could not load ad hoc assignment data. Please try again.\");\n        return;\n      }\n  \n      \/\/ Per-row RBAC (PHP parity): own pending ad hoc is editable; otherwise admin only.\n      if (!canEditAdhocRow(row)) {\n        alert(\n          \"Access denied: you can only edit your own pending ad hoc assignment.\",\n        );\n        return;\n      }\n  \n      \/\/ Store row for use in updateAdHoc payload\n      _editingAdhocRow = row;\n  \n      \/\/ Parse time values: time_utilized \/ time_approved may be \"HH:MM\" or decimal hours\n      const parseHrsMins = (val) => {\n        if (both(!val, val !== 0)) return { hrs: 0, mins: 0 };\n        const str = String(val);\n        if (str.includes(\":\")) {\n          const [h, m] = str.split(\":\").map(Number);\n          return { hrs: isNaN(h) ? 0 : h, mins: isNaN(m) ? 0 : m };\n        }\n        const dec = parseFloat(str) || 0;\n        return { hrs: Math.floor(dec), mins: Math.round((dec % 1) * 60) };\n      };\n  \n      const utilized = parseHrsMins(\n        row.time_utilized ||\n          row.time_utilized_decimal ||\n          row.time_utilized_display,\n      );\n      const totalMins = utilized.hrs * 60 + utilized.mins;\n  \n      document.getElementById(\"adhocModalFields\").innerHTML = `\n                  <div class=\"form-group\"><label class=\"required\">Assigned date<\/label>\n                      <input type=\"date\" class=\"form-control\" id=\"editAdhocDate\" value=\"${formatDate(row.date)}\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Created By<\/label>\n                      <select class=\"form-control\" id=\"editAdhocCreatedBy\" disabled style=\"-webkit-appearance: none; -moz-appearance: none; appearance: none; background-color: #F1F3F4;\">\n                          <option value=\"${row.created_by || \"\"}\">${row.created_by_name || \"\"}<\/option>\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Client<\/label>\n                      <select class=\"form-control\" id=\"editAdhocClient\">\n                          <option value=\"\">Select Client<\/option>\n                          ${buildOptions(dropDownData.clients, \"id\", \"name\", row.client_id)}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Project<\/label>\n                      <select class=\"form-control\" id=\"editAdhocProject\">\n                          <option value=\"\">Select Project<\/option>\n                          ${buildOptions(dropDownData.projects, \"id\", \"name\", row.project_id)}\n                      <\/select>\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Hoc Work Type<\/label>\n                      <input type=\"text\" class=\"form-control\" id=\"editAdhocWorkType\" value=\"${row.ad_hoc_work_type || \"\"}\" placeholder=\"Hoc Work Type\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Description<\/label>\n                      <input type=\"text\" class=\"form-control\" id=\"editAdhocDescription\" value=\"${row.description || \"\"}\" placeholder=\"Enter Description\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Mins Utilized<\/label>\n                      <input type=\"number\" class=\"form-control\" id=\"editAdhocMinsUtilized\" value=\"${totalMins}\" placeholder=\"Enter Mins\" oninput=\"calcAdhocEditHrs()\">\n                  <\/div>\n                  <div class=\"form-group\"><label class=\"required\">Hrs Utilized<\/label>\n                      <input type=\"number\" class=\"form-control\" id=\"editAdhocHrsUtilized\" value=\"${utilized.hrs}\" placeholder=\"Enter Hrs\" disabled style=\"background-color: #F1F3F4;\">\n                  <\/div>\n                  <div class=\"form-group\"><label>Comment\/Remarks<\/label>\n                      <input type=\"text\" class=\"form-control\" id=\"editAdhocComments\" value=\"${row.comments || \"\"}\" placeholder=\"Write Something...\">\n                  <\/div>\n              `;\n      document.getElementById(\"modalAdhoc\").style.display = \"flex\";\n    }\n  }\n  \n  function closeModals() {\n    document.getElementById(\"modalAssigned\").style.display = \"none\";\n    document.getElementById(\"modalAdhoc\").style.display = \"none\";\n    document.getElementById(\"modalSubmit\").style.display = \"none\";\n    document.getElementById(\"modalAddAdHoc\").style.display = \"none\";\n    const approvalEl = document.getElementById(\"modalAdhocApproval\");\n    if (approvalEl) approvalEl.style.display = \"none\";\n  }\n  \n  async function updateAssignment() {\n    \/\/ Function-level RBAC guard \u00e2\u20ac\u201d backend must also enforce this on \/work_assignment\/update.\n    if (!CAN_EDIT) {\n      alert(\"Access denied: you do not have permission to edit assignments.\");\n      return;\n    }\n    if (!_editingAssignedId) {\n      alert(\"No assignment selected for update.\");\n      return;\n    }\n    const fileId = resolveEditFileId();\n    if (fileId == null) {\n      alert(\"File ID is missing for this assignment. Please reload the page and try again.\");\n      return;\n    }\n    const payload = {\n      work_assignment_id: _editingAssignedId,\n      file_id: fileId,\n      file_field_edit: String(\n        document.getElementById(\"editFileName\")?.value ||\n        document.getElementById(\"editFileFieldEdit\")?.value ||\n          document.getElementById(\"editFileId\")?.value ||\n          \"\",\n      ),\n      assigned_date: document.getElementById(\"editAssignedDate\")?.value || \"\",\n      assigned_to:\n        parseInt(document.getElementById(\"editAssignedTo\")?.value, 10) || null,\n      received_on: document.getElementById(\"editReceivedOn\")?.value || \"\",\n      file_name: document.getElementById(\"editFileName\")?.value || \"\",\n      insurance_id:\n        parseInt(document.getElementById(\"editInsurance\")?.value, 10) || null,\n      account_id:\n        parseInt(document.getElementById(\"editAccount\")?.value, 10) || null,\n      client_id:\n        parseInt(document.getElementById(\"editClient\")?.value, 10) || null,\n      category_id:\n        parseInt(document.getElementById(\"editCategory\")?.value, 10) || null,\n      project_id:\n        parseInt(document.getElementById(\"editProject\")?.value, 10) || null,\n      project_type_id:\n        parseInt(document.getElementById(\"editProjectType\")?.value, 10) || null,\n      entity_id:\n        parseInt(document.getElementById(\"editEntity\")?.value, 10) || null,\n      amount: parseFloat(document.getElementById(\"editAmount\")?.value) || 0,\n      pages: parseInt(document.getElementById(\"editPages\")?.value, 10) || 0,\n      dos_count:\n        parseInt(document.getElementById(\"editDosCount\")?.value, 10) || 0,\n      assigned_dos:\n        parseInt(document.getElementById(\"editAssignedDos\")?.value, 10) || 0,\n      hours: parseFloat(document.getElementById(\"editHours\")?.value) || 0,\n    };\n  \n    try {\n      const res = await fetch(ENDPOINTS.UPDATE_ASSIGNMENT, {\n        method: \"POST\",\n        headers: getHeaders(),\n        body: JSON.stringify(payload),\n      });\n      if (handleAuthError(res)) return;\n      let result;\n      try {\n        result = await res.json();\n      } catch (parseErr) {\n        alert(\"Update failed: invalid server response.\");\n        return;\n      }\n      if (res.status === 403) {\n        alert(\n          result.message ||\n            result.messages?.[0] ||\n            \"Access denied: you do not have permission to edit assignments.\",\n        );\n        return;\n      }\n      if (both(res.ok, result.code === 200 || result.status === \"success\")) {\n        alert(\"Assignment updated successfully.\");\n        closeModals();\n        fetchTableData(currentPage);\n      } else {\n        const errMsg = result.errors\n          ?.map((e) => e.msg || e.message)\n          .filter(Boolean)\n          .join(\"\\n\");\n        alert(\n          errMsg ||\n            result.message ||\n            result.messages?.[0] ||\n            \"Update failed. Please try again.\",\n        );\n      }\n    } catch (err) {\n      console.error(\"Update Assignment error:\", err);\n      alert(\"Network error. Please try again.\");\n    }\n  }\n  \n  async function updateAdHoc() {\n    \/\/ Per-row RBAC (PHP parity): own pending ad hoc is editable; otherwise admin only.\n    \/\/ Backend must also enforce this on \/ad_hoc_assignment\/update.\n    if (!_editingAdhocRow || !canEditAdhocRow(_editingAdhocRow)) {\n      alert(\n        \"Access denied: you can only edit your own pending ad hoc assignment.\",\n      );\n      return;\n    }\n    if (!_editingAdhocId) {\n      alert(\"No ad hoc assignment selected for update.\");\n      return;\n    }\n  \n    const date = document.getElementById(\"editAdhocDate\")?.value || \"\";\n    const clientId =\n      parseInt(document.getElementById(\"editAdhocClient\")?.value, 10) || null;\n    const projectId =\n      parseInt(document.getElementById(\"editAdhocProject\")?.value, 10) || null;\n    const workType = document.getElementById(\"editAdhocWorkType\")?.value || \"\";\n    const description =\n      document.getElementById(\"editAdhocDescription\")?.value || \"\";\n    const comments = document.getElementById(\"editAdhocComments\")?.value || \"\";\n  \n    const totalMins =\n      parseInt(document.getElementById(\"editAdhocMinsUtilized\")?.value, 10) || 0;\n    const hrsUtilized = Math.floor(totalMins \/ 60);\n    const minsUtilized = totalMins % 60;\n  \n    const payload = {\n      id: _editingAdhocId,\n      date: date,\n      client_id: clientId,\n      project_id: projectId,\n      ad_hoc_work_type: workType,\n      description: description,\n      minute_utilized: minsUtilized,\n      hour_utilized: hrsUtilized,\n      comments: comments,\n    };\n  \n    try {\n      const res = await fetch(ENDPOINTS.UPDATE_ADHOC, {\n        method: \"POST\",\n        headers: getHeaders(),\n        body: JSON.stringify(payload),\n      });\n      if (handleAuthError(res)) return;\n      const result = await res.json();\n      if (both(res.ok, result.code === 200 || result.status === \"success\")) {\n        alert(\"Ad Hoc assignment updated successfully.\");\n        closeModals();\n        fetchAdhocTableData(currentPage);\n      } else {\n        alert(\n          result.message ||\n            result.messages?.[0] ||\n            \"Update failed. Please try again.\",\n        );\n      }\n    } catch (err) {\n      console.error(\"Update AdHoc error:\", err);\n      alert(\"Network error. Please try again.\");\n    }\n  }\n  \n  let _editingAdhocApprovalId = null;\n  let _editingAdhocApprovalRow = null;\n  \n  async function openApprovalModal(id) {\n    \/\/ Function-level RBAC guard: Only Managers and Admins and Team Leads can approve\n    if (!CAN_APPROVE) {\n      alert(\n        \"Access denied: approving\/reverting ad hoc assignments requires a Manager or Team Lead role.\",\n      );\n      return;\n    }\n  \n    \/\/ Try to fetch the ad hoc record detail from the API\n    let row = null;\n    try {\n      const res = await fetchAdHocDetail(id);\n      if (handleAuthError(res)) return;\n      if (res.ok) {\n        const json = await res.json();\n        row = json?.data?.id ? json.data : json?.data?.data || json;\n      }\n    } catch (e) {\n      \/* ignore, try fallback *\/\n    }\n  \n    \/\/ Fallback: find in already-fetched table rows\n    if (!row || !row.id) {\n      row = lastFetchedRows.find((r) => String(r.id) === String(id)) || null;\n    }\n  \n    if (!row) {\n      alert(\"Could not load ad hoc assignment data. Please try again.\");\n      return;\n    }\n  \n    _editingAdhocApprovalId = id;\n    _editingAdhocApprovalRow = row;\n  \n    \/\/ Parse time values\n    const parseHrsMins = (val) => {\n      if (both(!val, val !== 0)) return { hrs: 0, mins: 0 };\n      const str = String(val);\n      if (str.includes(\":\")) {\n        const [h, m] = str.split(\":\").map(Number);\n        return { hrs: isNaN(h) ? 0 : h, mins: isNaN(m) ? 0 : m };\n      }\n      const dec = parseFloat(str) || 0;\n      return { hrs: Math.floor(dec), mins: Math.round((dec % 1) * 60) };\n    };\n  \n    const utilized = parseHrsMins(\n      row.time_utilized || row.time_utilized_decimal || row.time_utilized_display,\n    );\n    _approvalUtilized = { hrs: utilized.hrs, mins: utilized.mins };\n  \n    \/\/ Let's format the date to YYYY-MM-DD for the input fields\n    const today = new Date().toISOString().split(\"T\")[0];\n  \n    document.getElementById(\"adhocApprovalFields\").innerHTML = `\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Assigned date <span style=\"color: red;\">*<\/span><\/label>\n              <input type=\"date\" id=\"approveAssignedDate\" class=\"form-control\" value=\"${formatDate(row.date)}\" style=\"background-color: white; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #212529; outline: none;\">\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Client <span style=\"color: red;\">*<\/span><\/label>\n              <select class=\"form-control\" disabled style=\"background-color: #F1F3F4; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #555; -webkit-appearance: none;\">\n                  <option value=\"${row.client_id || \"\"}\">${row.client_name || \"\"}<\/option>\n              <\/select>\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Project <span style=\"color: red;\">*<\/span><\/label>\n              <select class=\"form-control\" disabled style=\"background-color: #F1F3F4; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #555; -webkit-appearance: none;\">\n                  <option value=\"${row.project_id || \"\"}\">${row.project_name || \"\"}<\/option>\n              <\/select>\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Hoc Work Type <span style=\"color: red;\">*<\/span><\/label>\n              <input type=\"text\" class=\"form-control\" value=\"${row.ad_hoc_work_type || \"\"}\" disabled style=\"background-color: #F1F3F4; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #555;\">\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Description <span style=\"color: red;\">*<\/span><\/label>\n              <input type=\"text\" class=\"form-control\" value=\"${row.description || \"\"}\" disabled style=\"background-color: #F1F3F4; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #555;\">\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Mins Utilized <span style=\"color: red;\">*<\/span><\/label>\n              <input type=\"number\" class=\"form-control\" value=\"${utilized.mins}\" disabled style=\"background-color: #F1F3F4; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #555;\">\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Hrs Utilized <span style=\"color: red;\">*<\/span><\/label>\n              <input type=\"number\" class=\"form-control\" value=\"${utilized.hrs}\" disabled style=\"background-color: #F1F3F4; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #555;\">\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Status <span style=\"color: red;\">*<\/span><\/label>\n              <select id=\"approveStatus\" class=\"form-control\" onchange=\"onApproveStatusChange()\" style=\"background-color: white; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #212529; outline: none;\">\n                  <option value=\"1\" selected>Approved<\/option>\n                  <option value=\"0\">Not Approved<\/option>\n              <\/select>\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Approved on <span style=\"color: red;\">*<\/span><\/label>\n              <input type=\"date\" id=\"approveDate\" class=\"form-control\" value=\"${today}\" style=\"background-color: white; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #212529; outline: none;\">\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Mins Approved <span style=\"color: red;\">*<\/span><\/label>\n              <input type=\"number\" id=\"approveMins\" class=\"form-control\" value=\"${utilized.mins}\" onblur=\"recalcApproveHrs()\" style=\"background-color: white; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #212529; outline: none;\">\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Hrs Approved <span style=\"color: red;\">*<\/span><\/label>\n              <input type=\"number\" id=\"approveHrs\" class=\"form-control\" value=\"${utilized.hrs}\" disabled style=\"background-color: #F1F3F4; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #555;\">\n          <\/div>\n          <div class=\"form-group\" style=\"display: flex; flex-direction: column; gap: 5px;\">\n              <label style=\"font-weight: 500; font-size: 13px; color: #212529;\">Comment<\/label>\n              <input type=\"text\" id=\"approveComment\" class=\"form-control\" value=\"${row.comments || \"Approved\"}\" style=\"background-color: white; border: 1px solid #D1D5DB; border-radius: 6px; padding: 8px 12px; font-size: 14px; color: #212529; outline: none;\">\n          <\/div>\n      `;\n  \n    document.getElementById(\"modalAdhocApproval\").style.display = \"flex\";\n  }\n  \n  async function submitAdhocApproval() {\n    if (!_editingAdhocApprovalId) {\n      alert(\"No ad hoc assignment selected for approval.\");\n      return;\n    }\n  \n    \/\/ PHP parity (AdHocAssignmentService::approve):\n    \/\/   $status      = request status  (1 = Approved, 0 = Not Approved)\n    \/\/   is_approved  = ($status == 1) ? 1 : 2\n    \/\/   status       = $status  (stored as numeric 1\/0)\n    const status = parseInt(document.getElementById(\"approveStatus\")?.value, 10);\n    const isApproved = status === 1 ? 1 : 2;\n    const approvedOn = document.getElementById(\"approveDate\")?.value || \"\";\n    const minsApproved =\n      parseInt(document.getElementById(\"approveMins\")?.value, 10) || 0;\n    const hrsApproved =\n      parseInt(document.getElementById(\"approveHrs\")?.value, 10) || 0;\n    const comments = document.getElementById(\"approveComment\")?.value || \"\";\n    const assignedDate =\n      document.getElementById(\"approveAssignedDate\")?.value || \"\";\n  \n    const payload = {\n      id: _editingAdhocApprovalId,\n      date: assignedDate,\n      client_id: _editingAdhocApprovalRow?.client_id || null,\n      project_id: _editingAdhocApprovalRow?.project_id || null,\n      ad_hoc_work_type: _editingAdhocApprovalRow?.ad_hoc_work_type || \"\",\n      description: _editingAdhocApprovalRow?.description || \"\",\n      minute_utilized:\n        _editingAdhocApprovalRow?.minute_utilized ||\n        _editingAdhocApprovalRow?.time_utilized_decimal * 60 ||\n        0,\n      hour_utilized:\n        _editingAdhocApprovalRow?.hour_utilized ||\n        _editingAdhocApprovalRow?.time_utilized_decimal ||\n        0,\n      is_approved: isApproved,\n      approved_by: CURRENT_USER_DATA.id || 1,\n      minute_approved: minsApproved,\n      hour_approved: hrsApproved,\n      comments: comments,\n      approved_at: approvedOn,\n      status: status,\n      updated_by: CURRENT_USER_DATA.id || 1,\n    };\n  \n    try {\n      const res = await fetch(ENDPOINTS.UPDATE_ADHOC, {\n        method: \"POST\",\n        headers: getHeaders(),\n        body: JSON.stringify(payload),\n      });\n      if (handleAuthError(res)) return;\n      const result = await res.json();\n      if (both(res.ok, result.code === 200 || result.status === \"success\")) {\n        alert(\"Ad Hoc assignment approved successfully.\");\n        closeModals();\n        fetchAdhocTableData(currentPage);\n      } else {\n        alert(\n          result.message ||\n            result.messages?.[0] ||\n            \"Approval submission failed. Please try again.\",\n        );\n      }\n    } catch (err) {\n      console.error(\"Submit AdHoc Approval error:\", err);\n      alert(\"Network error. Please try again.\");\n    }\n  }\n  \n  \/\/ \u00e2\u201d\u20ac\u00e2\u201d\u20ac CUSTOM DATE PICKER \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\n  \/\/ Two independent picker instances: 'assigned' and 'adhoc'\n  const dpState = {\n    assigned: {\n      viewYear: null,\n      viewMonth: null,\n      startDate: null,\n      endDate: null,\n      hoverDate: null,\n      activePreset: null,\n      selectedDate: null,\n    },\n    adhoc: {\n      viewYear: null,\n      viewMonth: null,\n      startDate: null,\n      endDate: null,\n      hoverDate: null,\n      activePreset: null,\n      selectedDate: null,\n    },\n  };\n  \n  const DP_IDS = {\n    assigned: {\n      wrapper: \"dpWrapperAssigned\",\n      display: \"filterDate\",\n      dropdown: \"dpDropdownAssigned\",\n      backdrop: \"dpBackdropAssigned\",\n      title: \"dpCalTitleAssigned\",\n      title2: \"dpCalTitleAssigned2\",\n      days: \"dpDaysAssigned\",\n      days2: \"dpDaysAssigned2\",\n    },\n    adhoc: {\n      wrapper: \"dpWrapperAdhoc\",\n      display: \"filterAdhocDate\",\n      dropdown: \"dpDropdownAdhoc\",\n      backdrop: \"dpBackdropAdhoc\",\n      title: \"dpCalTitleAdhoc\",\n      title2: \"dpCalTitleAdhoc2\",\n      days: \"dpDaysAdhoc\",\n      days2: \"dpDaysAdhoc2\",\n    },\n  };\n  const DP_MONTHS = [\n    \"January\",\n    \"February\",\n    \"March\",\n    \"April\",\n    \"May\",\n    \"June\",\n    \"July\",\n    \"August\",\n    \"September\",\n    \"October\",\n    \"November\",\n    \"December\",\n  ];\n  \n  function dpToday() {\n    const d = new Date();\n    d.setHours(0, 0, 0, 0);\n    return d;\n  }\n  \n  function dpFmt(d) {\n    if (!d) return \"\";\n    const dd = String(d.getDate()).padStart(2, \"0\");\n    const mm = String(d.getMonth() + 1).padStart(2, \"0\");\n    return `${dd}-${mm}-${d.getFullYear()}`;\n  }\n  \n  function dpFmtISO(d) {\n    if (!d) return \"\";\n    const dd = String(d.getDate()).padStart(2, \"0\");\n    const mm = String(d.getMonth() + 1).padStart(2, \"0\");\n    return `${d.getFullYear()}-${mm}-${dd}`;\n  }\n  \n  function dpSameDay(a, b) {\n    if (!a) return false;\n    if (!b) return false;\n    if (a.getFullYear() !== b.getFullYear()) return false;\n    if (a.getMonth() !== b.getMonth()) return false;\n    return a.getDate() === b.getDate();\n  }\n  \n  function dpRenderCalendar(inst) {\n    const s = dpState[inst];\n    const ids = DP_IDS[inst];\n  \n    const titleEl = document.getElementById(ids.title);\n    const title2El = document.getElementById(ids.title2);\n    const daysEl = document.getElementById(ids.days);\n    const days2El = document.getElementById(ids.days2);\n  \n    if (!titleEl || !title2El || !daysEl || !days2El) return;\n  \n    \/\/ Second month = first month + 1\n    let y2 = s.viewYear,\n      m2 = s.viewMonth + 1;\n    if (m2 > 11) {\n      m2 = 0;\n      y2++;\n    }\n  \n    titleEl.textContent = `${DP_MONTHS[s.viewMonth]} ${s.viewYear}`;\n    title2El.textContent = `${DP_MONTHS[m2]} ${y2}`;\n  \n    daysEl.innerHTML = dpBuildDays(s.viewYear, s.viewMonth, s, inst);\n    days2El.innerHTML = dpBuildDays(y2, m2, s, inst);\n  }\n  \n  function dpBuildDays(year, month, s, inst) {\n    const today = dpToday();\n    const startDay = new Date(year, month, 1).getDay();\n    const daysInMonth = new Date(year, month + 1, 0).getDate();\n    let html = \"\";\n    for (let i = 0; i < startDay; i++)\n      html += `<div class=\"dp-day other-month\"><\/div>`;\n    for (let d = 1; d <= daysInMonth; d++) {\n      const cur = new Date(year, month, d);\n      let cls = \"dp-day\";\n      if (dpSameDay(cur, today)) cls += \" today\";\n      const dayOfWeek = cur.getDay();\n      if (s.startDate) {\n        if (s.endDate) {\n          if (dpSameDay(cur, s.startDate)) {\n            cls += \" selected selected-start\";\n          } else if (dpSameDay(cur, s.endDate)) {\n            cls += \" selected selected-end\";\n          } else if (cur > s.startDate) {\n            if (cur < s.endDate) {\n              cls += \" in-range\";\n              if (dayOfWeek === 0) cls += \" row-start\";\n              if (dayOfWeek === 6) cls += \" row-end\";\n            }\n          }\n        } else if (dpSameDay(cur, s.startDate)) {\n          cls += \" selected selected-start selected-end\";\n        } else if (s.hoverDate) {\n          let rS = s.startDate,\n            rE = s.hoverDate;\n          if (rE < rS) {\n            const t = rS;\n            rS = rE;\n            rE = t;\n          }\n          if (dpSameDay(cur, s.hoverDate)) {\n            cls +=\n              s.hoverDate < s.startDate\n                ? \" hover-start hover-range\"\n                : \" hover-end hover-range\";\n          } else if (cur > rS) {\n            if (cur < rE) {\n              cls += \" hover-range\";\n              if (dayOfWeek === 0) cls += \" row-start\";\n              if (dayOfWeek === 6) cls += \" row-end\";\n            }\n          }\n        }\n      }\n      html += `<div class=\"${cls}\" onclick=\"dpPickDay(event,${year},${month},${d},'${inst}')\" onmouseover=\"dpHoverDay('${inst}',${year},${month},${d})\">${d}<\/div>`;\n    }\n    return html;\n  }\n  \n  function dpPickDay(e, y, m, d, inst) {\n    e.stopPropagation();\n    const s = dpState[inst];\n    const chosen = new Date(y, m, d);\n  \n    if (!s.startDate) {\n      s.startDate = chosen;\n      s.endDate = null;\n    } else if (s.endDate) {\n      s.startDate = chosen;\n      s.endDate = null;\n    } else {\n      if (chosen < s.startDate) {\n        s.endDate = s.startDate;\n        s.startDate = chosen;\n      } else {\n        s.endDate = chosen;\n      }\n    }\n  \n    s.hoverDate = null;\n    s.activePreset = null;\n    const dropId = inst === \"assigned\" ? \"dpDropdownAssigned\" : \"dpDropdownAdhoc\";\n    document\n      .querySelectorAll(`#${dropId} .dp-preset-item`)\n      .forEach((el) => el.classList.remove(\"active\"));\n    dpRenderCalendar(inst);\n    dpUpdateFooterRange(inst);\n  }\n  \n  function dpHoverDay(inst, y, m, d) {\n    const s = dpState[inst];\n    if (s.startDate) {\n      if (!s.endDate) {\n        const h = new Date(y, m, d);\n        if (!dpSameDay(h, s.hoverDate)) {\n          s.hoverDate = h;\n          dpRenderCalendar(inst);\n        }\n      }\n    }\n  }\n  \n  function dpUpdateFooterRange(inst) {\n    const s = dpState[inst];\n    const el = document.getElementById(\n      inst === \"assigned\" ? \"dpRangeDisplayAssigned\" : \"dpRangeDisplayAdhoc\",\n    );\n    if (!el) return;\n    if (s.startDate) {\n      if (s.endDate) {\n        el.textContent = `${dpFmtISO(s.startDate)} to ${dpFmtISO(s.endDate)}`;\n      } else {\n        el.textContent = `${dpFmtISO(s.startDate)} to Select end date`;\n      }\n    } else {\n      el.textContent = \"Select Date Range\";\n    }\n  }\n  \n  function dpChangeMonth(e, dir, inst) {\n    e.stopPropagation();\n    const s = dpState[inst];\n    s.viewMonth += dir;\n    if (s.viewMonth > 11) {\n      s.viewMonth = 0;\n      s.viewYear++;\n    }\n    if (s.viewMonth < 0) {\n      s.viewMonth = 11;\n      s.viewYear--;\n    }\n    dpRenderCalendar(inst);\n  }\n  \n  function selectPreset(e, preset, inst) {\n    e.stopPropagation();\n    const s = dpState[inst];\n    const today = dpToday();\n    s.activePreset = preset;\n    const dropId = DP_IDS[inst].dropdown;\n    document\n      .querySelectorAll(`#${dropId} .dp-preset-item`)\n      .forEach((el) =>\n        el.classList.toggle(\"active\", el.dataset.preset === preset),\n      );\n  \n    switch (preset) {\n      case \"today\":\n        s.startDate = new Date(today);\n        s.endDate = new Date(today);\n        break;\n      case \"yesterday\": {\n        const y = new Date(today);\n        y.setDate(y.getDate() - 1);\n        s.startDate = y;\n        s.endDate = y;\n        break;\n      }\n      case \"last7\": {\n        const y = new Date(today);\n        y.setDate(y.getDate() - 6);\n        s.startDate = y;\n        s.endDate = new Date(today);\n        break;\n      }\n      case \"last30\": {\n        const y = new Date(today);\n        y.setDate(y.getDate() - 29);\n        s.startDate = y;\n        s.endDate = new Date(today);\n        break;\n      }\n      case \"thisMonth\":\n        s.startDate = new Date(today.getFullYear(), today.getMonth(), 1);\n        s.endDate = new Date(today);\n        break;\n      case \"lastMonth\":\n        s.startDate = new Date(today.getFullYear(), today.getMonth() - 1, 1);\n        s.endDate = new Date(today.getFullYear(), today.getMonth(), 0);\n        break;\n    }\n    s.selectedDate = s.startDate;\n    s.viewYear = s.startDate.getFullYear();\n    s.viewMonth = s.startDate.getMonth();\n    dpRenderCalendar(inst);\n    dpUpdateFooterRange(inst);\n    \/\/ Auto-apply preset\n    dpApply(e, inst);\n  }\n  \n  function dpApply(e, inst) {\n    if (e) e.stopPropagation();\n    const s = dpState[inst];\n    const display = document.getElementById(DP_IDS[inst].display);\n    if (s.startDate) {\n      if (s.endDate) {\n        if (dpSameDay(s.startDate, s.endDate)) {\n          display.value = dpFmtISO(s.startDate);\n        } else {\n          display.value = `${dpFmtISO(s.startDate)} to ${dpFmtISO(s.endDate)}`;\n        }\n      } else {\n        display.value = dpFmtISO(s.startDate);\n      }\n    } else {\n      display.value = \"\";\n    }\n    closeDatePicker(inst);\n    \/\/ Auto-filter\n    handleActionClick(\"Filter\");\n  }\n  \n  function dpClear(e, inst) {\n    e.stopPropagation();\n    const s = dpState[inst];\n    s.startDate = null;\n    s.endDate = null;\n    s.hoverDate = null;\n    s.selectedDate = null;\n    s.activePreset = null;\n    document.getElementById(DP_IDS[inst].display).value = \"\";\n    const dropId = DP_IDS[inst].dropdown;\n    document\n      .querySelectorAll(`#${dropId} .dp-preset-item`)\n      .forEach((el) => el.classList.remove(\"active\"));\n    dpRenderCalendar(inst);\n    dpUpdateFooterRange(inst);\n    closeDatePicker(inst);\n  }\n  \n  function toggleDatePicker(e, inst) {\n    e.stopPropagation();\n    const ids = DP_IDS[inst];\n    const dd = document.getElementById(ids.dropdown);\n    if (dd.classList.contains(\"open\")) {\n      closeDatePicker(inst);\n    } else {\n      const s = dpState[inst];\n      const ref = s.selectedDate || dpToday();\n      s.viewYear = ref.getFullYear();\n      s.viewMonth = ref.getMonth();\n      if (!s.selectedDate) {\n        s.activePreset = \"today\";\n        document\n          .querySelectorAll(`#${ids.dropdown} .dp-preset-item`)\n          .forEach((el) =>\n            el.classList.toggle(\"active\", el.dataset.preset === \"today\"),\n          );\n      }\n      dpRenderCalendar(inst);\n      dpUpdateFooterRange(inst);\n      dd.classList.add(\"open\");\n      document.getElementById(ids.backdrop).classList.add(\"show\");\n      \/\/ Align to the right edge of the input (opening to the left)\n      \/\/ to ensure it stays on screen and matches \"not on right side\" requirement.\n      dd.classList.add(\"align-right\");\n    }\n  }\n  \n  function closeDatePicker(inst) {\n    const ids = DP_IDS[inst];\n    document.getElementById(ids.dropdown).classList.remove(\"open\");\n    document.getElementById(ids.backdrop).classList.remove(\"show\");\n  }\n  \n  \/\/ Close pickers when clicking outside\n  document.addEventListener(\"click\", function (e) {\n    [\"assigned\", \"adhoc\"].forEach((inst) => {\n      const wrapId = inst === \"assigned\" ? \"dpWrapperAssigned\" : \"dpWrapperAdhoc\";\n      const wrapEl = document.getElementById(wrapId);\n      if (both(wrapEl, !wrapEl.contains(e.target))) {\n        closeDatePicker(inst);\n      }\n    });\n  });\n  \n  let _submittingAssignedId = null;\n  \n  async function openSubmitModal(id) {\n    _submittingAssignedId = id;\n  \n    const buildOptions = (data, valueKey, labelKey, selectedValue) =>\n      data\n        .map(\n          (item) =>\n            `<option value=\"${item[valueKey] ?? \"\"}\" ${String(item[valueKey]) === String(selectedValue) ? \"selected\" : \"\"}>${item[labelKey] ?? \"\"}<\/option>`,\n        )\n        .join(\"\");\n  \n    let row = null;\n    try {\n      const res = await fetchWorkAssignmentDetail(id);\n      if (handleAuthError(res)) return;\n      if (res.ok) {\n        const json = await res.json();\n        row = json?.data?.id ? json.data : json?.data?.data || json;\n      }\n    } catch (e) {\n      console.warn(\"POST detail failed, trying fallback\");\n    }\n  \n    if (!row || !row.id) {\n      row = lastFetchedRows.find((r) => String(r.id) === String(id)) || null;\n    }\n  \n    if (!row) {\n      alert(\"Could not load assignment data. Please try again.\");\n      return;\n    }\n  \n    document.getElementById(\"submitModalFields\").innerHTML = `\n          <div class=\"form-group\"><label class=\"required\">Assigned date<\/label>\n              <input type=\"text\" class=\"form-control\" value=\"${getOnlyDate(row.assigned_date)}\" disabled>\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Assigned to<\/label>\n              <select class=\"form-control\" disabled>\n                  <option value=\"\">Select User<\/option>\n                  ${buildGroupedUserSelectOptions(\n                    row.assigned_to || row.assigned_to_id,\n                    row.pesudo_name || row.assigned_to_name,\n                  )}\n              <\/select>\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Received on<\/label>\n              <input type=\"text\" class=\"form-control\" value=\"${getOnlyDate(row.received_on)}\" disabled>\n          <\/div>\n      \n          <div class=\"form-group\"><label class=\"required\">File Name<\/label>\n              <input type=\"text\" class=\"form-control\" value=\"${row.file_name || \"\"}\" disabled>\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Insurance<\/label>\n              <select class=\"form-control\" disabled>\n                  <option value=\"\">Select Insurance<\/option>\n                  ${buildOptions(dropDownData.insurances, \"id\", \"name\", row.insurance_id)}\n              <\/select>\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Pages<\/label>\n              <input type=\"number\" class=\"form-control\" value=\"${row.pages ?? 0}\" disabled>\n          <\/div>\n      \n          <div class=\"form-group\"><label class=\"required\">Project<\/label>\n              <select class=\"form-control\" disabled>\n                  <option value=\"\">Select Project<\/option>\n                  ${buildOptions(dropDownData.projects, \"id\", \"name\", row.project_id)}\n              <\/select>\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Project Type<\/label>\n              <select class=\"form-control\" disabled>\n                  <option value=\"\">Select Project Type<\/option>\n                  ${buildOptions(dropDownData.projectTypes, \"id\", \"type\", row.project_type_id)}\n              <\/select>\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Entity<\/label>\n              <select class=\"form-control\" disabled>\n                  <option value=\"\">Select Entity<\/option>\n                  ${buildOptions(dropDownData.entities, \"id\", \"entity\", row.entity_id)}\n              <\/select>\n          <\/div>\n      \n          <div class=\"form-group\"><label class=\"required\">Dos Count<\/label>\n              <input type=\"number\" class=\"form-control\" value=\"${row.dos_count ?? 0}\" disabled>\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Amount<\/label>\n              <input type=\"number\" class=\"form-control\" value=\"${row.amount ?? 0}\" disabled>\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Assigned DOS<\/label>\n              <input type=\"number\" class=\"form-control\" id=\"submitAssignedDos\" value=\"${row.assigned_dos ?? 0}\" disabled>\n          <\/div>\n  \n          <div class=\"form-group\"><label class=\"required\">DOS Completed<\/label>\n              <input type=\"number\" class=\"form-control\" id=\"submitDosCompleted\" placeholder=\"Enter DOS Completed\" min=\"0\" value=\"\" oninput=\"calculateHoursSubmit()\">\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Pending DOS<\/label>\n              <input type=\"text\" class=\"form-control\" id=\"submitPendingDos\" placeholder=\"Auto calculated\" value=\"\" readonly style=\"pointer-events:none;background:#f9f9f9;\">\n          <\/div>\n          <div class=\"form-group\"><label class=\"required\">Hours<\/label>\n              <input type=\"text\" class=\"form-control\" id=\"submitHours\" placeholder=\"Auto calculated\" value=\"\" readonly style=\"pointer-events:none;background:#f9f9f9;\">\n          <\/div>\n      \n          <div class=\"form-group\"><label>Remarks<\/label>\n              <input type=\"text\" class=\"form-control\" id=\"submitRemarks\" placeholder=\"Enter Remarks\" value=\"${row.remarks ?? \"\"}\">\n          <\/div>\n      `;\n  \n    document.getElementById(\"modalSubmit\").style.display = \"flex\";\n  \n    \/\/ PHP parity: benchmark + assigned DOS drive auto hours\/pending on dos_complete input.\n    _currentSubmitBenchmark = 0;\n    _currentSubmitAssignedDos = parseFloat(row.assigned_dos) || 0;\n    fetchSubmitAccountBenchmark(row.account_id);\n  }\n  \n  async function submitAssignmentLog() {\n    if (!_submittingAssignedId) return;\n  \n    const payload = {\n      work_assignment_id: _submittingAssignedId,\n      dos_complete: document.getElementById(\"submitDosCompleted\")?.value || 0,\n      pending_dos: document.getElementById(\"submitPendingDos\")?.value || 0,\n      hours: resolveSubmitHours(),\n      remarks: document.getElementById(\"submitRemarks\")?.value || \"\",\n    };\n  \n    try {\n      const res = await fetch(ENDPOINTS.SUBMIT_LOG, {\n        method: \"POST\",\n        headers: getHeaders(),\n        body: JSON.stringify(payload),\n      });\n      if (handleAuthError(res)) return;\n      const result = await res.json();\n  \n      if (\n        both(\n          res.ok,\n          result.code === 200 || result.status === \"success\" || result.message,\n        )\n      ) {\n        lastFetchedRows = lastFetchedRows.filter(\n          (r) => String(r.id) !== String(_submittingAssignedId),\n        );\n        _submittingAssignedId = null;\n        closeModals();\n        fetchTableData(currentPage);\n      } else {\n        alert(\n          result.message ||\n            result.messages?.[0] ||\n            \"Submit failed. Please try again.\",\n        );\n      }\n    } catch (err) {\n      console.error(\"Submit Log Error:\", err);\n      alert(\"Network error. Please try again.\");\n    }\n  }\n  \n  \/\/ \u00e2\u201d\u20ac\u00e2\u201d\u20ac ADD AD HOC ASSIGNMENT \u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\u00e2\u201d\u20ac\n  function openAddAdHocModal() {\n    \/\/ Set today's date as default\n    const today = new Date();\n    const yyyy = today.getFullYear();\n    const mm = String(today.getMonth() + 1).padStart(2, \"0\");\n    const dd = String(today.getDate()).padStart(2, \"0\");\n    document.getElementById(\"addAdHocDate\").value = `${yyyy}-${mm}-${dd}`;\n  \n    \/\/ Populate Client dropdown\n    const clientSel = document.getElementById(\"addAdHocClient\");\n    clientSel.innerHTML =\n      '<option value=\"\">Select Client<\/option>' +\n      dropDownData.clients\n        .map((c) => `<option value=\"${c.id}\">${c.name || \"\"}<\/option>`)\n        .join(\"\");\n  \n    \/\/ Populate Project dropdown\n    const projSel = document.getElementById(\"addAdHocProject\");\n    projSel.innerHTML =\n      '<option value=\"\">Select Project<\/option>' +\n      dropDownData.projects\n        .map((p) => `<option value=\"${p.id}\">${p.name || \"\"}<\/option>`)\n        .join(\"\");\n  \n    \/\/ Reset fields\n    document.getElementById(\"addAdHocWorkType\").value = \"\";\n    document.getElementById(\"addAdHocDescription\").value = \"\";\n    document.getElementById(\"addAdHocMinsUtilized\").value = \"\";\n    document.getElementById(\"addAdHocHrsUtilized\").value = \"\";\n  \n    document.getElementById(\"modalAddAdHoc\").style.display = \"flex\";\n  }\n  \n  function calcAdHocHrs() {\n    const mins =\n      parseInt(document.getElementById(\"addAdHocMinsUtilized\").value, 10) || 0;\n    document.getElementById(\"addAdHocHrsUtilized\").value = (mins \/ 60).toFixed(2);\n  }\n  \n  async function submitAdHocAssignment() {\n    const date = document.getElementById(\"addAdHocDate\").value;\n    const clientId = document.getElementById(\"addAdHocClient\").value;\n    const projectId = document.getElementById(\"addAdHocProject\").value;\n    const workType = document.getElementById(\"addAdHocWorkType\").value.trim();\n    const description = document\n      .getElementById(\"addAdHocDescription\")\n      .value.trim();\n    const minsUtilized = document.getElementById(\"addAdHocMinsUtilized\").value;\n  \n    if (\n      !date ||\n      !clientId ||\n      !projectId ||\n      !workType ||\n      !description ||\n      !minsUtilized\n    ) {\n      alert(\"Please fill in all required fields.\");\n      return;\n    }\n  \n    const totalMins = parseInt(minsUtilized, 10) || 0;\n    const hrs = Math.floor(totalMins \/ 60);\n    const mins = totalMins % 60;\n  \n    const payload = {\n      date: date,\n      client_id: parseInt(clientId, 10),\n      project_id: parseInt(projectId, 10),\n      ad_hoc_work_type: workType,\n      description: description,\n      minute_utilized: mins,\n      hour_utilized: hrs,\n    };\n  \n    try {\n      const res = await fetch(ENDPOINTS.ADHOC_ADD, {\n        method: \"POST\",\n        headers: getHeaders(),\n        body: JSON.stringify(payload),\n      });\n      if (handleAuthError(res)) return;\n  \n      if (!res.ok) {\n        const text = await res.text();\n        let message = \"Failed to add. Server error.\";\n        try {\n          const errorJson = JSON.parse(text);\n          message = errorJson.message || errorJson.messages?.[0] || message;\n        } catch (e) {\n          console.error(\"Non-JSON error:\", text);\n        }\n        alert(message);\n        return;\n      }\n  \n      const result = await res.json();\n      if (result.code === 200 || result.status === \"success\" || result.message) {\n        alert(\"Ad Hoc Assignment added successfully.\");\n        closeModals();\n        if (activeView === \"adhoc\") {\n          fetchAdhocTableData(currentPage);\n        }\n      } else {\n        alert(\n          result.message ||\n            result.messages?.[0] ||\n            \"Failed to add. Please try again.\",\n        );\n      }\n    } catch (err) {\n      console.error(\"Add Ad Hoc error:\", err);\n      alert(\"Network error. Please try again.\");\n    }\n  }\n  \n  async function approveAllAdhoc() {\n    if (!CAN_BULK_ADHOC) {\n      alert(\n        \"Access denied: you do not have permission to bulk approve ad hoc assignments.\",\n      );\n      return;\n    }\n    const ids = getSelectedAdhocIds();\n    if (ids.length === 0) {\n      alert(\"Please select at least one ad hoc assignment to approve.\");\n      return;\n    }\n    if (!confirm(\"Are you sure you want to approve selected item\")) {\n      return;\n    }\n    try {\n      const res = await fetch(ENDPOINTS.ADHOC_APPROVE_BULK, {\n        method: \"POST\",\n        headers: getHeaders(),\n        body: JSON.stringify({ adhoc_id: ids }),\n      });\n      if (handleAuthError(res)) return;\n      const result = await res.json();\n      if (\n        both(\n          res.ok,\n          result.code === 200 || result.status === \"success\" || result.message,\n        )\n      ) {\n        alert(result.messages?.[0] || \"Ad Hoc Assignments Approved.\");\n        fetchAdhocTableData(currentPage);\n      } else {\n        alert(\n          result.message ||\n            result.messages?.[0] ||\n            \"Approve failed. Please try again.\",\n        );\n      }\n    } catch (err) {\n      console.error(\"Approve All error:\", err);\n      alert(\"Network error. Please try again.\");\n    }\n  }\n  \n  async function resetAllAdhoc() {\n    if (!CAN_BULK_ADHOC) {\n      alert(\n        \"Access denied: you do not have permission to bulk reset ad hoc assignments.\",\n      );\n      return;\n    }\n    const ids = getSelectedAdhocIds();\n    if (ids.length === 0) {\n      alert(\"Please select at least one ad hoc assignment to reset.\");\n      return;\n    }\n    if (!confirm(\"Are you sure you want to reset selected item\")) {\n      return;\n    }\n    try {\n      const res = await fetch(ENDPOINTS.ADHOC_RESET_BULK, {\n        method: \"POST\",\n        headers: getHeaders(),\n        body: JSON.stringify({ adhoc_id: ids }),\n      });\n      if (handleAuthError(res)) return;\n      const result = await res.json();\n      if (\n        both(\n          res.ok,\n          result.code === 200 || result.status === \"success\" || result.message,\n        )\n      ) {\n        alert(result.messages?.[0] || \"Ad Hoc Assignments Reset.\");\n        fetchAdhocTableData(currentPage);\n      } else {\n        alert(\n          result.message ||\n            result.messages?.[0] ||\n            \"Reset failed. Please try again.\",\n        );\n      }\n    } catch (err) {\n      console.error(\"Reset All error:\", err);\n      alert(\"Network error. Please try again.\");\n    }\n  }\n  \n  window.onload = init;\n<\/script>\n\n\n    \n    <div class=\"ph-title\" id=\"pageHeading\">Assigned Assignment<\/div> <br>\n    \n    <div class=\"filter-grid\" id=\"filterForm\"><\/div>\n    \n    <div class=\"action-row\" id=\"btnGroup\"><\/div>\n    \n    <!-- Hidden CSV Import Input -->\n    <input type=\"file\" id=\"csvImportInput\" accept=\".csv\" onchange=\"handleCSVImport(event)\">\n    \n    <div class=\"tabs-nav\">\n        <div class=\"tab-link active\" id=\"tab-assigned\" onclick=\"toggleTab('assigned')\">Assigned Assignment<\/div>\n        <div class=\"tab-link\" id=\"tab-adhoc\" onclick=\"toggleTab('adhoc')\">Ad Hoc Assignment<\/div>\n    <\/div>\n    \n    <div class=\"table-container\">\n        <table>\n            <thead id=\"tblHead\"><\/thead>\n            <tbody id=\"tblBody\"><\/tbody>\n        <\/table>\n    <\/div>\n    \n    <!-- Pagination Footer -->\n    <div class=\"pagination-container\">\n        <div class=\"pagination-controls\">\n            <span class=\"nav-link\" id=\"prevBtn\">&laquo; Previous<\/span>\n            <div id=\"pageNumbers\" style=\"display:flex; gap: 4px; flex-wrap: wrap; justify-content: center;\"><\/div>\n            <span class=\"nav-link\" id=\"nextBtn\">Next &raquo;<\/span>\n        <\/div>\n        <div id=\"entryInfo\" style=\"font-size: 12px; color: var(--text-muted);\">\n            Showing 0 to 0 of 0 entries\n        <\/div>\n    <\/div>\n    \n    \n    <div id=\"modalSubmit\" class=\"modal-overlay\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">Submit Assignment<\/div>\n            <div class=\"modal-grid\" id=\"submitModalFields\" style=\"grid-template-columns: repeat(3, 1fr);\"><\/div>\n            <div class=\"modal-footer\">\n                <button class=\"btn btn-clear\" onclick=\"closeModals()\">Close<\/button>\n                <button class=\"btn btn-blue\" style=\"width: 150px;\" onclick=\"submitAssignmentLog()\">Submit<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n    \n    <div id=\"modalAssigned\" class=\"modal-overlay\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">Edit Assigned Assignments<\/div>\n            <div class=\"modal-grid\" id=\"assignedModalFields\"><\/div>\n            <div class=\"modal-footer\">\n                <button class=\"btn btn-clear\" onclick=\"closeModals()\">Close<\/button>\n                <button class=\"btn btn-blue\" style=\"width: 200px;\" onclick=\"updateAssignment()\">Edit Assignment<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n    \n    <div id=\"modalAdhoc\" class=\"modal-overlay\">\n        <div class=\"modal-content\">\n            <div class=\"modal-header\">Edit Ad Hoc Assignment<\/div>\n            <div class=\"modal-grid\" id=\"adhocModalFields\" style=\"grid-template-columns: repeat(3, 1fr);\"><\/div>\n            <div class=\"modal-footer\">\n                <button class=\"btn btn-clear\" onclick=\"closeModals()\">Close<\/button>\n                <button class=\"btn btn-blue\" style=\"width: 150px;\" onclick=\"updateAdHoc()\">Submit<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n    \n    <div id=\"modalAdhocApproval\" class=\"modal-overlay\">\n        <div class=\"modal-content\" style=\"max-width: 800px; width: 90%; padding: 24px;\">\n            <div class=\"modal-header\" style=\"font-size: 20px; font-weight: 600; margin-bottom: 20px; border-bottom: 1px solid #EFEFEF; padding-bottom: 10px;\">Approve Ad Hoc Assignment<\/div>\n            <div class=\"modal-grid\" id=\"adhocApprovalFields\" style=\"display: grid; grid-template-columns: repeat(3, 1fr); gap: 15px; margin-bottom: 20px;\"><\/div>\n            <div class=\"modal-footer\" style=\"display: flex; justify-content: flex-end; gap: 15px; border-top: 1px solid #EFEFEF; padding-top: 15px;\">\n                <button class=\"btn btn-clear\" onclick=\"closeModals()\">Close<\/button>\n                <button class=\"btn btn-blue\" style=\"width: 150px;\" onclick=\"submitAdhocApproval()\">Submit<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n    \n    <!-- Add Ad Hoc Assignment Modal -->\n\n    \n    <div id=\"modalAddAdHoc\" class=\"modal-overlay\">\n        <div class=\"adhoc-modal-content\">\n            <div class=\"adhoc-modal-title\">Add Ad Hoc Assignment<\/div>\n            <div class=\"adhoc-form-group\">\n                <label>Date <span class=\"req\">*<\/span><\/label>\n                <input type=\"date\" class=\"adhoc-form-control\" id=\"addAdHocDate\">\n            <\/div>\n            <div class=\"adhoc-form-group\">\n                <label>Client <span class=\"req\">*<\/span><\/label>\n                <select class=\"adhoc-form-control select-control\" id=\"addAdHocClient\">\n                    <option value=\"\">Select Client<\/option>\n                <\/select>\n            <\/div>\n            <div class=\"adhoc-form-group\">\n                <label>Project <span class=\"req\">*<\/span><\/label>\n                <select class=\"adhoc-form-control select-control\" id=\"addAdHocProject\">\n                    <option value=\"\">Select Project<\/option>\n                <\/select>\n            <\/div>\n            <div class=\"adhoc-form-group\">\n                <label>Hoc Work Type <span class=\"req\">*<\/span><\/label>\n                <input type=\"text\" class=\"adhoc-form-control\" id=\"addAdHocWorkType\" placeholder=\"Hoc Work Type\">\n            <\/div>\n            <div class=\"adhoc-form-group\">\n                <label>Description <span class=\"req\">*<\/span><\/label>\n                <input type=\"text\" class=\"adhoc-form-control\" id=\"addAdHocDescription\" placeholder=\"Enter Description\">\n            <\/div>\n            <div class=\"adhoc-form-group\">\n                <label>Mins Utilized <span class=\"req\">*<\/span><\/label>\n                <input type=\"number\" class=\"adhoc-form-control\" id=\"addAdHocMinsUtilized\" placeholder=\"Enter Mins\" oninput=\"calcAdHocHrs()\">\n            <\/div>\n            <div class=\"adhoc-form-group\">\n                <label>Hrs Utilized <span class=\"req\">*<\/span><\/label>\n                <input type=\"number\" class=\"adhoc-form-control\" id=\"addAdHocHrsUtilized\" placeholder=\"Enter Hrs\" disabled=\"\">\n            <\/div>\n            <div class=\"adhoc-modal-footer\">\n                <button class=\"adhoc-btn-close\" onclick=\"closeModals()\">Close<\/button>\n                <button class=\"adhoc-btn-submit\" onclick=\"submitAdHocAssignment()\">Submit<\/button>\n            <\/div>\n        <\/div>\n    <\/div>\n    \n\n<\/div><\/div>\n\n<\/div><\/div><\/div><\/div>\n","protected":false},"excerpt":{"rendered":"<p>Assigned Assignment Assigned Assignment Ad Hoc Assignment &laquo; Previous Next &raquo; Showing 0 to 0 of 0 entries Submit Assignment Close Submit Edit Assigned Assignments Close Edit Assignment Edit Ad Hoc Assignment Close Submit Approve Ad Hoc Assignment Close Submit Add Ad Hoc Assignment Date * Client * Select Client Project * Select Project Hoc&#8230;<\/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-202","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages\/202","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=202"}],"version-history":[{"count":141,"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages\/202\/revisions"}],"predecessor-version":[{"id":1213,"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages\/202\/revisions\/1213"}],"wp:attachment":[{"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/media?parent=202"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}