{"id":181,"date":"2026-03-31T09:56:40","date_gmt":"2026-03-31T09:56:40","guid":{"rendered":"https:\/\/ph-taskportal.zyneventures.com\/?page_id=181"},"modified":"2026-07-23T17:04:40","modified_gmt":"2026-07-23T17:04:40","slug":"submitted-work-assignment","status":"publish","type":"page","link":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/submitted-work-assignment\/","title":{"rendered":"Submitted Work Assignment"},"content":{"rendered":"<style>.kadence-column181_27d997-62 > .kt-inside-inner-col,.kadence-column181_27d997-62 > .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-column181_27d997-62 > .kt-inside-inner-col{column-gap:var(--global-kb-gap-sm, 1rem);}.kadence-column181_27d997-62 > .kt-inside-inner-col{flex-direction:column;}.kadence-column181_27d997-62 > .kt-inside-inner-col > .aligncenter{width:100%;}.kadence-column181_27d997-62 > .kt-inside-inner-col:before{opacity:0.3;}.kadence-column181_27d997-62{position:relative;}@media all and (max-width: 1024px){.kadence-column181_27d997-62 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}@media all and (max-width: 767px){.kadence-column181_27d997-62 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}<\/style>\n<div class=\"wp-block-kadence-column kadence-column181_27d997-62\"><div class=\"kt-inside-inner-col\"><style>.kb-row-layout-id181_f89b15-31 > .kt-row-column-wrap{align-content:start;}:where(.kb-row-layout-id181_f89b15-31 > .kt-row-column-wrap) > .wp-block-kadence-column{justify-content:start;}.kb-row-layout-id181_f89b15-31 > .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-id181_f89b15-31 > .kt-row-layout-overlay{opacity:0.30;}@media all and (max-width: 1024px){.kb-row-layout-id181_f89b15-31 > .kt-row-column-wrap{grid-template-columns:minmax(0, 1fr);}}@media all and (max-width: 767px){.kb-row-layout-id181_f89b15-31 > .kt-row-column-wrap{grid-template-columns:minmax(0, 1fr);}}<\/style><div class=\"kb-row-layout-wrap kb-row-layout-id181_f89b15-31 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-column181_0dd5aa-d9 > .kt-inside-inner-col,.kadence-column181_0dd5aa-d9 > .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-column181_0dd5aa-d9 > .kt-inside-inner-col{column-gap:var(--global-kb-gap-sm, 1rem);}.kadence-column181_0dd5aa-d9 > .kt-inside-inner-col{flex-direction:column;}.kadence-column181_0dd5aa-d9 > .kt-inside-inner-col > .aligncenter{width:100%;}.kadence-column181_0dd5aa-d9 > .kt-inside-inner-col:before{opacity:0.3;}.kadence-column181_0dd5aa-d9{position:relative;}@media all and (max-width: 1024px){.kadence-column181_0dd5aa-d9 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}@media all and (max-width: 767px){.kadence-column181_0dd5aa-d9 > .kt-inside-inner-col{flex-direction:column;justify-content:center;}}<\/style>\n<div class=\"wp-block-kadence-column kadence-column181_0dd5aa-d9\"><div class=\"kt-inside-inner-col\">\n<style>\n    :root {\n        --primary-blue: #0180FF;\n        --hover-blue: #3499FF;\n        --text-dark: #212529;\n        --text-muted: #8D8C9C;\n        --border-color: #EFEFEF;\n        --bg-light: #F7F8FA;\n        --success-green: #1E8E3E;\n        --white: #ffffff;\n    }\n\n    *, *::before, *::after {\n        box-sizing: border-box;\n    }\n\n    html, body {\n        overflow-x: hidden;\n        max-width: 100%;\n    }\n\n    body {\n        font-family: 'Sora', sans-serif;\n        background-color: var(--white);\n        color: var(--text-dark);\n    }\n\n    .dashboard-title,\n    .filter-grid,\n    .action-row,\n    .tab-header,\n    .table-container,\n    .pagination-container {\n        max-width: 100%;\n    }\n\n    \/* Page Header *\/\n    .dashboard-title {\n        font-size: 21px;\n        font-weight: 500;\n        text-transform: uppercase;\n        margin-bottom: 25px;\n        letter-spacing: 0.5px;\n    }\n\n    \/* Filter 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', sans-serif;\n        font-size: 12px;\n        outline: none;\n        box-sizing: border-box;\n        width: 100%;\n    }\n\n    .form-control:focus {\n        border-color: var(--primary-blue);\n    }\n\n    \/* Action Row \u2014 left-aligned, natural button widths *\/\n    .action-row {\n        display: flex;\n        flex-wrap: wrap;\n        gap: 10px;\n        margin-bottom: 25px;\n    }\n\n    .action-row .btn {\n        flex: 0 0 auto;\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-primary {\n        background: var(--primary-blue);\n        color: white;\n    }\n\n    .btn:hover {\n        opacity: 0.88;\n    }\n\n    \/* Tab Header *\/\n    .tab-header {\n        border-bottom: 2px solid var(--primary-blue);\n        display: inline-block;\n        padding-bottom: 5px;\n        margin-bottom: 20px;\n        font-size: 16px;\n        font-weight: 500;\n        color: var(--text-dark);\n    }\n\n    \/* Table *\/\n    .table-container {\n        width: 100%;\n        max-width: 100%;\n        overflow-x: hidden;\n        border: 1px solid var(--border-color);\n        border-radius: 6px;\n    }\n\n    .data-table {\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\n    .data-table th {\n        background: var(--bg-light);\n        text-align: left;\n        padding: 8px 6px;\n        color: var(--text-dark);\n        font-weight: 500;\n        border-bottom: 1px solid var(--border-color);\n        white-space: normal;\n        word-break: break-word;\n        line-height: 1.3;\n        font-size: 10px;\n    }\n\n    .data-table td {\n        padding: 8px 6px;\n        border-bottom: 1px solid #f2f2f2;\n        color: #8D8C9C;\n        font-size: 10px;\n        font-weight: 400;\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    \/* Keep date + status values single-line on laptop *\/\n    .data-table td:nth-child(1),\n    .data-table td:nth-child(15),\n    .data-table td:nth-child(17) {\n        white-space: nowrap;\n        word-break: normal;\n        overflow-wrap: normal;\n    }\n\n    \/* Status Badge *\/\n    .status-badge {\n        background-color: #D3EFE8;\n        color: #268A76;\n        padding: 4px 10px;\n        border-radius: 999px;\n        font-size: 11px;\n        font-weight: 500;\n        display: inline-block;\n        white-space: nowrap;\n        word-break: normal;\n        line-height: 1.3;\n    }\n\n    \/* Pagination Footer \u2014 synced with Assigned_Assignment.html *\/\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        width: 32px;\n        height: 32px;\n        display: flex;\n        align-items: center;\n        justify-content: center;\n        cursor: pointer;\n        border-radius: 50%;\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    \/* Hidden CSV file input *\/\n    #csvImportInput {\n        display: none;\n    }\n\n    \/* Custom Select Dropdown *\/\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        height: 38px;\n        padding: 0 36px 0 12px;\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    \/* 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-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        display: none;\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    \/* 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 #ced4da;\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: #70757a;\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    \/* Custom Date Picker Dropdown *\/\n    .dp-dropdown {\n        display: none;\n        position: absolute;\n        top: calc(100% + 6px);\n        left: 0;\n        z-index: 2000;\n        background: #fff;\n        border: 1px solid #E0E0E0;\n        border-radius: 10px;\n        box-shadow: 0 8px 28px rgba(0, 0, 0, 0.13);\n        flex-direction: row;\n        width: 680px;\n        max-width: calc(100vw - 24px);\n        overflow: hidden;\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-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    \/* Responsive *\/\n    @media (max-width: 1200px) {\n        .filter-grid {\n            grid-template-columns: repeat(3, minmax(0, 1fr));\n        }\n    }\n\n    @media (max-width: 1100px) {\n        .filter-grid {\n            grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));\n        }\n    }\n\n    @media (max-width: 768px) {\n        body {\n            padding: 12px;\n        }\n\n        .filter-grid {\n            grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));\n        }\n\n        .action-row {\n            gap: 8px;\n        }\n\n        .btn {\n            font-size: 11px;\n        }\n    }\n\n    @media (max-width: 480px) {\n        .filter-grid {\n            grid-template-columns: 1fr;\n        }\n\n        .action-row .btn {\n            flex: 1 1 calc(50% - 5px);\n        }\n\n        .pagination-controls {\n            flex-direction: column;\n            gap: 10px;\n            width: 100%;\n        }\n\n        .nav-link {\n            width: 100%;\n            text-align: center;\n            border: 1px solid var(--border-color);\n            border-radius: 4px;\n            padding: 8px;\n            box-sizing: border-box;\n        }\n\n        #pageNumbers {\n            justify-content: center;\n            width: 100%;\n        }\n    }\n\n    \/* Browser download status toast *\/\n    .csv-download-toast {\n        position: fixed;\n        right: 20px;\n        bottom: 20px;\n        z-index: 9999;\n        display: none;\n        align-items: center;\n        gap: 10px;\n        min-width: 260px;\n        max-width: 360px;\n        padding: 12px 16px;\n        border-radius: 8px;\n        background: #0f172a;\n        color: #fff;\n        font-family: 'Sora', sans-serif;\n        font-size: 12px;\n        box-shadow: 0 8px 24px rgba(0, 0, 0, 0.25);\n    }\n    .csv-download-toast.show { display: flex; }\n    .csv-download-toast .spin {\n        width: 14px;\n        height: 14px;\n        border: 2px solid rgba(255,255,255,0.25);\n        border-top-color: #60a5fa;\n        border-radius: 50%;\n        animation: csvSpin 0.8s linear infinite;\n        flex-shrink: 0;\n    }\n    @keyframes csvSpin { to { transform: rotate(360deg); } }\n<\/style>\n\n<div class=\"main-content\">\n    <h2 class=\"dashboard-title\">Submitted Work Assignments &#8211; Data Team<\/h2> <br>\n\n    <div class=\"filter-grid\" id=\"filterForm\"><\/div>\n\n    <div class=\"action-row\">\n        <button class=\"btn btn-clear\" onclick=\"clearFilters()\">Clear<\/button>\n        <button class=\"btn btn-primary\" onclick=\"handleFilter()\">Filter<\/button>\n        <a id=\"btnCSVImport\" class=\"btn btn-primary\" href=\"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/import-assignment\/\" style=\"display:none; text-decoration:none;\">+ CSV Import<\/a>\n        <button id=\"btnDownloadCSV\" class=\"btn btn-primary\" onclick=\"handleDownloadCSV()\">+ Download CSV<\/button>\n    <\/div> <br>\n\n    <div id=\"csvDownloadToast\" class=\"csv-download-toast\" aria-live=\"polite\">\n        <div class=\"spin\"><\/div>\n        <div>\n            <div style=\"font-weight:600; margin-bottom:2px;\">Downloading CSV\u2026<\/div>\n            <div style=\"opacity:0.85;\">Check your browser downloads bar for progress.<\/div>\n        <\/div>\n    <\/div>\n\n    <div class=\"tab-header\">Submitted Assignment<\/div>\n\n    <div class=\"table-container\">\n        <table class=\"data-table\">\n            <thead>\n                <tr>\n                    <th>Assigned Date<\/th>\n                    <th>Assigned To<\/th>\n                    <th>Client<\/th>\n                    <th>Project<\/th>\n                    <th>Entity<\/th>\n                    <th>Account<\/th>\n                    <th>Category<\/th>\n                    <th>DOS Count<\/th>\n                    <th>Amount<\/th>\n                    <th>Assigned DOS<\/th>\n                    <th>Completed DOS<\/th>\n                    <th>Pending DOS<\/th>\n                    <th>Hours<\/th>\n                    <th>Created By<\/th>\n                    <th>Approved On<\/th>\n                    <th>Remarks<\/th>\n                    <th>Status<\/th>\n                    <th id=\"thEdit\">Edit<\/th>\n                <\/tr>\n            <\/thead>\n            <tbody id=\"assignmentData\">\n                <tr>\n                    <td colspan=\"18\" style=\"text-align:center; color: var(--text-muted);\">Loading&#8230;<\/td>\n                <\/tr>\n            <\/tbody>\n        <\/table>\n    <\/div>\n\n    <div class=\"pagination-container\">\n        <div class=\"pagination-controls\">\n            <span class=\"nav-link\" id=\"prevBtn\">\u00ab Previous<\/span>\n            <div id=\"pageNumbers\" style=\"display:flex; gap: 4px;\"><\/div>\n            <span class=\"nav-link\" id=\"nextBtn\">Next \u00bb<\/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<\/div>\n\n<script>\n    \/** \u2500\u2500 ENDPOINTS \u2500\u2500 **\/\n    const BASE_URL = 'https:\/\/api-ph-portal.zyneventures.com\/api\/v1';\n    const ENDPOINTS = {\n        SUBMITTED: `${BASE_URL}\/work_assignment\/submitted`,\n        SUBMIT_EXPORT: `${BASE_URL}\/work_assignment\/submit-export`,\n        SUBMIT_IMPORT: `${BASE_URL}\/work_assignment\/import`,\n        USERS: `${BASE_URL}\/user\/table\/list`,\n        TEAM_MEMBERS: `${BASE_URL}\/user\/team-members`,\n        UNSUBMIT: `${BASE_URL}\/work_assignment\/unsubmit`,\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    };\n\n    \/** \u2500\u2500 STATE \u2500\u2500 **\/\n    let currentPage = 1;\n    let totalPages = 1;\n    let currentPerPage = 25;\n    let currentTotal = 0;\n    let lastFetchedRows = [];\n\n    const PERMISSION_TIER = (localStorage.getItem(\"PERMISSION_TIER\") || \"none\").toLowerCase();\n\n    \/** PHP userRole() + submitted_list.blade.php visibility rules *\/\n    function getUserRole() {\n        let user = {};\n        try {\n            const raw = localStorage.getItem('USER_DATA') ||\n                        localStorage.getItem('USER') ||\n                        localStorage.getItem('user_data');\n            if (raw) user = JSON.parse(raw);\n        } catch (_) {}\n        const roleRaw = user.role || localStorage.getItem('USER_ROLE') || user.user_role || '';\n        return (typeof roleRaw === 'object'\n            ? (roleRaw.name || roleRaw.role || '')\n            : roleRaw).toString().toLowerCase().trim();\n    }\n\n    \/** PHP: userRole() == 'administrator' *\/\n    function isAdministratorUser() {\n        if (PERMISSION_TIER === 'admin') return true;\n        return getUserRole() === 'administrator';\n    }\n\n    \/** PHP: checKMangersAndAbove() \u2014 role contains manage or director *\/\n    function isManagersAndAboveUser() {\n        if (isAdministratorUser()) return true;\n        if (PERMISSION_TIER === 'manager') return true;\n        const role = getUserRole();\n        return role.includes('manage') || role.includes('director');\n    }\n\n    \/** PHP submitted_list Edit column: strpos(userRole(), 'manage') !== false *\/\n    function canShowEditColumn() {\n        if (PERMISSION_TIER === 'manager') return true;\n        return getUserRole().includes('manage');\n    }\n\n    const IS_ADMIN = isAdministratorUser();\n    const CAN_DOWNLOAD_CSV = isManagersAndAboveUser();\n    const CAN_EDIT = canShowEditColumn();\n\n    const dropDownData = {\n        users: [],\n        entities: [],\n        clients: [],\n        accounts: [],\n        categories: [],\n        projects: []\n    };\n\n\n\n    \/** \u2500\u2500 AUTH HEADER (matches login_form.html \u2014 token stored as \"TOKEN\") \u2500\u2500 **\/\n    const getHeaders = () => ({\n        'Content-Type': 'application\/json',\n        'Authorization': `Bearer ${localStorage.getItem('TOKEN')}`\n    });\n\n    \/** \u2500\u2500 HELPERS \u2500\u2500 **\/\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    \/**\n     * formatDateOnly \u2014 extracts only the date portion from a date\/datetime string.\n     * Handles formats like \"2025-01-15 10:30:00\", \"2025-01-15T10:30:00Z\", or \"2025-01-15\".\n     * Returns '-' for null\/undefined\/empty values.\n     *\/\n    function formatDateOnly(value) {\n        if (value === null || value === undefined || value === '') return '-';\n        const str = String(value).trim();\n        \/\/ Try splitting by 'T' (ISO) or space (datetime) to get just the date part\n        const datePart = str.split('T')[0].split(' ')[0];\n        return safeText(datePart);\n    }\n\n    \/**\n     * formatHours \u2014 limits the displayed value to a maximum of 2 decimal places.\n     * - If the value is not a valid number, falls back to '-'.\n     * - Trailing zeros after the decimal are removed (e.g. 1.50 \u2192 \"1.5\", 2.00 \u2192 \"2\").\n     *\/\n    function formatHours(value) {\n        if (value === null || value === undefined || value === '') return '-';\n        const num = parseFloat(value);\n        if (isNaN(num)) return safeText(value);\n        \/\/ toFixed(2) caps at exactly 2 decimal places\n        return num.toFixed(2);\n    }\n    function fmtHours2(value) {\n        if (value === null || value === undefined || value === '') return '0.00';\n        const n = parseFloat(value);\n        return Number.isFinite(n) ? n.toFixed(2) : safeText(value);\n    }\n    function getFilterValue(id) {\n        const el = document.getElementById(id);\n        return el ? el.value : '';\n    }\n\n    \/** \u2500\u2500 LOOKUP PESUDO_NAME FROM TEAM-MEMBERS API DATA \u2500\u2500 **\/\n    function getPesudoNameById(assignedToId) {\n        if (assignedToId === null || assignedToId === undefined || assignedToId === '') return '-';\n        const user = (dropDownData.users || []).find(u => String(u.id) === String(assignedToId));\n        if (user && user.pesudo_name) return user.pesudo_name;\n        return '-';\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 || 0\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        if (Number.isFinite(directPages) && directPages > 0) {\n            return { pages: directPages, limit: Number.isFinite(limit) && limit > 0 ? limit : fallbackLimit };\n        }\n        const total = Number(\n            payload?.pagination?.total ||\n            payload?.data?.pagination?.total ||\n            payload?.total ||\n            payload?.data?.total || 0\n        );\n        const safeLimit = Number.isFinite(limit) && limit > 0 ? limit : fallbackLimit;\n        const derivedPages = total > 0 ? Math.ceil(total \/ safeLimit) : 1;\n        return { pages: Math.max(1, derivedPages), limit: safeLimit };\n    };\n\n    \/** \u2500\u2500 FETCH ALL PAGES FOR DROPDOWNS \u2500\u2500 **\/\n    async function fetchAllPages(endpoint) {\n        const defaultLimit = 500;\n        const buildUrl = (page, limit = defaultLimit) => {\n            const url = new URL(endpoint);\n            url.searchParams.set('page', String(page));\n            url.searchParams.set('limit', String(limit));\n            return url.toString();\n        };\n        const firstRes = await fetch(buildUrl(1, defaultLimit), { headers: getHeaders() });\n        const firstJson = await firstRes.json();\n        let allItems = extractListData(firstJson);\n        const { pages, limit } = extractPaginationInfo(firstJson, defaultLimit);\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            const otherPages = await Promise.all(pageRequests);\n            otherPages.forEach(pageData => {\n                if (pageData) allItems = allItems.concat(extractListData(pageData));\n            });\n        }\n        return allItems;\n    }\n\n    \/** \u2500\u2500 FETCH DROPDOWN DATA \u2500\u2500 **\/\n    async function fetchDropdownData() {\n        try {\n            const [u, e, c, a, cat, p] = await Promise.all([\n                fetchAllPages(ENDPOINTS.TEAM_MEMBERS),\n                fetchAllPages(ENDPOINTS.ENTITIES),\n                fetchAllPages(ENDPOINTS.CLIENTS),\n                fetch(ENDPOINTS.ACCOUNTS, { headers: getHeaders() }).then(r => r.json()),\n                fetchAllPages(ENDPOINTS.CATEGORIES),\n                fetchAllPages(ENDPOINTS.PROJECTS)\n            ]);\n            dropDownData.users = Array.isArray(u) ? u : [];\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        } catch (err) {\n            console.error('Dropdown fetch error', err);\n        }\n    }\n\n    \/** \u2500\u2500 RENDER SEARCHABLE SELECT \u2500\u2500 **\/\n    function renderSelect(label, selectId, data, labelKey, valueKey = 'id', multi = false) {\n        const optionsData = [{ _val: '', _label: `Select ${label}`, _placeholder: true }]\n            .concat((data || []).map(item => ({ _val: item[valueKey] ?? '', _label: item[labelKey] ?? '' })));\n        const optionsHtml = optionsData.map((o, i) =>\n            `<div class=\"custom-select-option${o._placeholder ? ' placeholder-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        ).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            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        const wrapper = document.getElementById('csWrapper_' + selectId);\n        if (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.querySelectorAll('.custom-select-option').forEach(o => o.classList.remove('highlighted'));\n        const visible = Array.from(drop.querySelectorAll('.custom-select-option'))\n            .filter(o => o.style.display !== 'none' && !o.classList.contains('placeholder-option'));\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('.custom-select-option.highlighted');\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(drop.querySelectorAll('.custom-select-option'))\n                .filter(o => o.style.display !== 'none' && !o.classList.contains('placeholder-option'));\n            if (visibleOptions.length === 0) return;\n            let currentIdx = visibleOptions.findIndex(o => o.classList.contains('highlighted'));\n            visibleOptions.forEach(o => o.classList.remove('highlighted'));\n            currentIdx = (currentIdx + 1) % visibleOptions.length;\n            visibleOptions[currentIdx].classList.add('highlighted');\n            visibleOptions[currentIdx].scrollIntoView({ block: 'nearest' });\n            return;\n        }\n\n        if (e.key === 'ArrowUp') {\n            e.preventDefault();\n            if (!isOpen) {\n                csToggle(selectId, e);\n                return;\n            }\n            const visibleOptions = Array.from(drop.querySelectorAll('.custom-select-option'))\n                .filter(o => o.style.display !== 'none' && !o.classList.contains('placeholder-option'));\n            if (visibleOptions.length === 0) return;\n            let currentIdx = visibleOptions.findIndex(o => o.classList.contains('highlighted'));\n            visibleOptions.forEach(o => o.classList.remove('highlighted'));\n            if (currentIdx <= 0) currentIdx = visibleOptions.length - 1;\n            else currentIdx -= 1;\n            visibleOptions[currentIdx].classList.add('highlighted');\n            visibleOptions[currentIdx].scrollIntoView({ block: 'nearest' });\n            return;\n        }\n\n        if (e.key === 'Escape') {\n            wrapper.classList.remove('open');\n            return;\n        }\n    }\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            const placeholderLabel = wrapper.querySelector('.placeholder-option .opt-label');\n            const hadIntegratedInput = !!document.getElementById('csInput_' + selectId);\n            if (hadIntegratedInput) {\n                const phText = placeholderLabel ? placeholderLabel.textContent.trim() : '';\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.querySelector('.opt-label').textContent.trim();\n            }\n            trigger.classList.add('placeholder-shown');\n            wrapper.querySelectorAll('.custom-select-option').forEach(o => o.classList.remove('selected'));\n            optionEl.classList.add('selected');\n            if (!multi) wrapper.classList.remove('open');\n            fetchTableData(1);\n            return;\n        }\n\n        if (!multi) {\n            input.value = value;\n            const selectedText = optionEl.querySelector('.opt-label').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.querySelectorAll('.custom-select-option').forEach(o => o.classList.remove('selected'));\n            optionEl.classList.add('selected');\n            wrapper.classList.remove('open');\n        } else {\n            let values = input.value ? input.value.split(',') : [];\n            const idx = values.indexOf(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('.placeholder-option .opt-label');\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(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.map(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                `).join('');\n\n                labelEl.innerHTML = chipsHtml + `<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            if (wrapper.classList.contains('open')) {\n                const newInput = document.getElementById('csInput_' + selectId);\n                if (newInput) setTimeout(() => newInput.focus(), 0);\n            }\n        }\n        fetchTableData(1);\n    }\n\n    function csRemoveChip(e, selectId, value) {\n        e.stopPropagation();\n        const wrapper = document.getElementById('csWrapper_' + selectId);\n        const optionEl = wrapper.querySelector(`.custom-select-option[data-value=\"${value}\"]`);\n        if (optionEl) {\n            csSelect(selectId, value, optionEl, true);\n        }\n    }\n\n    document.addEventListener('click', function (e) {\n        if (!e.target.closest('.custom-select-wrapper')) {\n            document.querySelectorAll('.custom-select-wrapper.open').forEach(w => w.classList.remove('open'));\n        }\n        if (!e.target.closest('.date-wrapper')) {\n            closeDatePicker('date');\n        }\n    });\n\n    function renderFilters() {\n        document.getElementById('filterForm').innerHTML = `\n            ${renderSelect('Assigned to', 'filterAssignedTo', dropDownData.users, '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('Project', 'filterProject', dropDownData.projects, 'name', 'id', true)}\n            ${renderSelect('Category', 'filterCategory', dropDownData.categories, 'category', 'id', true)}\n            <div class=\"form-group\"><label>Select Date<\/label>\n                <div class=\"date-wrapper\" id=\"dpWrapperDate\">\n                    <input type=\"text\" id=\"filterDate\" placeholder=\"Select Date Range\" readonly onclick=\"toggleDatePicker(event,'date')\">\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=\"dpBackdropDate\" onclick=\"closeDatePicker('date')\"><\/div>\n                    <div class=\"dp-dropdown\" id=\"dpDropdownDate\">\n                        <div class=\"dp-presets\">\n                            <div class=\"dp-preset-item active\" data-preset=\"today\"     onclick=\"selectPreset(event,'today','date')\">Today<\/div>\n                            <div class=\"dp-preset-item\"       data-preset=\"yesterday\"  onclick=\"selectPreset(event,'yesterday','date')\">Yesterday<\/div>\n                            <div class=\"dp-preset-item\"       data-preset=\"last7\"      onclick=\"selectPreset(event,'last7','date')\">Last 7 Days<\/div>\n                            <div class=\"dp-preset-item\"       data-preset=\"last30\"     onclick=\"selectPreset(event,'last30','date')\">Last 30 Days<\/div>\n                            <div class=\"dp-preset-item\"       data-preset=\"thisMonth\"  onclick=\"selectPreset(event,'thisMonth','date')\">This Month<\/div>\n                            <div class=\"dp-preset-item\"       data-preset=\"lastMonth\"  onclick=\"selectPreset(event,'lastMonth','date')\">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,'date')\">&#8249;<\/button>\n                                        <span class=\"dp-cal-title\" id=\"dpCalTitleDate\"><\/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=\"dpDaysDate\"><\/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=\"dpCalTitleDate2\"><\/span>\n                                        <button class=\"dp-nav-btn\" onclick=\"dpChangeMonth(event,1,'date')\">&#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=\"dpDaysDate2\"><\/div>\n                                <\/div>\n                            <\/div>\n                            <div class=\"dp-footer\">\n                                <div class=\"dp-range-display\" id=\"dpRangeDisplayDate\">Select Date Range<\/div>\n                                <div class=\"dp-footer-btns\">\n                                    <button class=\"dp-btn-clear\" onclick=\"dpClear(event,'date')\">Cancel<\/button>\n                                    <button class=\"dp-btn-apply\" onclick=\"dpApply(event,'date')\">Apply<\/button>\n                                <\/div>\n                            <\/div>\n                        <\/div>\n                    <\/div>\n                <\/div>\n            <\/div>\n            <div class=\"form-group\">\n                <label>Per Page<\/label>\n                <select id=\"filterPerPage\" class=\"form-control\" onchange=\"fetchTableData(1)\">\n                    <option value=\"\" disabled selected>Per Page<\/option>\n                    <option value=\"10\">10<\/option>\n                    <option value=\"15\">15<\/option>\n                    <option value=\"25\">25<\/option>\n                    <option value=\"50\">50<\/option>\n                    <option value=\"100\">100<\/option>\n                <\/select>\n            <\/div>\n        `;\n    }\n\n    \/** \u2500\u2500 BUILD URL \u2500\u2500 **\/\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    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 (parts.length === 2 && isValidISODate(parts[0]) && isValidISODate(parts[1])) {\n                return `${parts[0].trim()} - ${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 (parts.length === 2 && isValidISODate(parts[0]) && isValidISODate(parts[1])) {\n                return `${parts[0].trim()} - ${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 appendSubmittedFilters(url) {\n        const filters = {\n            assigned_to: getFilterValue('filterAssignedTo'),\n            entity_id: getFilterValue('filterEntity'),\n            client_id: getFilterValue('filterClient'),\n            account_id: getFilterValue('filterAccount'),\n            project_id: getFilterValue('filterProject'),\n            category_id: getFilterValue('filterCategory')\n        };\n        Object.entries(filters).forEach(([key, value]) => {\n            if (value !== '') url.searchParams.set(key, value);\n        });\n\n        const dateVal = getFilterValue('filterDate');\n        if (dateVal) {\n            const datesParam = formatDatesParam(dateVal);\n            if (datesParam) url.searchParams.set('dates', datesParam);\n        }\n    }\n\n    function buildSubmittedUrl(page = 1) {\n        const url = new URL(ENDPOINTS.SUBMITTED);\n        const perPage = getFilterValue('filterPerPage') || '25';\n        url.searchParams.set('page', String(page));\n        url.searchParams.set('perPage', String(perPage));\n        appendSubmittedFilters(url);\n        return url;\n    }\n\n    function buildSubmitExportUrl() {\n        const url = new URL(ENDPOINTS.SUBMIT_EXPORT);\n        appendSubmittedFilters(url);\n        return url;\n    }\n\n    \/** \u2500\u2500 FETCH TABLE DATA \u2500\u2500 **\/\n    async function fetchTableData(page = 1) {\n        const url = buildSubmittedUrl(page);\n        const tbody = document.getElementById('assignmentData');\n        tbody.innerHTML = '<tr><td colspan=\"18\" style=\"text-align:center; color: var(--text-muted);\">Loading...<\/td><\/tr>';\n\n        try {\n            const res = await fetch(url.toString(), { headers: getHeaders() });\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) {\n                tbody.innerHTML = '<tr><td colspan=\"18\" style=\"text-align:center; color: var(--text-muted);\">No data found<\/td><\/tr>';\n                renderPagination({ total: 0, pages: 1, perPage: 25 }, 1);\n                return;\n            }\n\n            tbody.innerHTML = rows.map(row => `\n                <tr>\n                    <td>${safeText(row.assigned_date)}<\/td>\n                    <td>${safeText(row.pesudo_name || row.assigned_to_name || getPesudoNameById(row.assigned_to))}<\/td>\n                    <td>${safeText(row.client_name)}<\/td>\n                    <td>${safeText(row.project_name)}<\/td>\n                    <td>${safeText(row.entity_name)}<\/td>\n                    <td>${safeText(row.account_name)}<\/td>\n                    <td>${safeText(row.category_name)}<\/td>\n                    <td>${safeText(row.dos_count)}<\/td>\n                    <td>${safeText(row.amount)}<\/td>\n                    <td>${safeText(row.assigned_dos)}<\/td>\n                    <td>${safeText(row.dos_completed)}<\/td>\n                    <td>${safeText(row.pending_dos)}<\/td>\n                    <td>${fmtHours2(row.completed_hours ?? row.hours)}<\/td>\n                    <td>${safeText(row.created_by_name || row.created_by)}<\/td>\n                    <td>${formatDateOnly(row.approved_on || row.approved_at)}<\/td>\n                    <td>${safeText(row.remarks)}<\/td>\n                    <td><span class=\"status-badge\">${safeText(row.status || 'Submitted')}<\/span><\/td>\n                    ${CAN_EDIT ? `<td style=\"text-align: center;\">\n                        ${!IS_ADMIN ? `<button onclick=\"unsubmitAssignment(${row.id}, this)\" style=\"color: #0180FF; background: none; border: none; text-decoration: underline; font-size: 11px; cursor: pointer; font-family: 'Sora', sans-serif; padding: 0;\">Un-Submit<\/button>` : ''}\n                    <\/td>` : ''}\n                <\/tr>\n            `).join('');\n\n            const meta = {\n                total: json?.data?.total || json?.data?.pagination?.total || rows.length,\n                pages: json?.data?.pages || json?.data?.pagination?.pages || json?.data?.last_page || 1,\n                perPage: json?.data?.perPage || json?.data?.pagination?.limit || json?.data?.per_page || 25\n            };\n            renderPagination(meta, page);\n\n        } catch (error) {\n            console.error('Submitted fetch error', error);\n            tbody.innerHTML = '<tr><td colspan=\"18\" style=\"text-align:center; color: var(--text-muted);\">Failed to load data<\/td><\/tr>';\n        }\n    }\n\n    \/** \u2500\u2500 UNSUBMIT ASSIGNMENT \u2500\u2500 **\/\n    async function unsubmitAssignment(id, btnEl) {\n        if (!confirm('Are you sure you want to un-submit this assignment?')) return;\n        btnEl.disabled = true;\n        btnEl.textContent = 'Processing...';\n        try {\n            const res = await fetch(ENDPOINTS.UNSUBMIT, {\n                method: 'POST',\n                headers: getHeaders(),\n                body: JSON.stringify({ id })\n            });\n            const json = await res.json();\n            if (res.ok) {\n                alert(json?.message || 'Assignment un-submitted successfully.');\n                fetchTableData(currentPage);\n            } else {\n                alert(json?.message || 'Failed to un-submit assignment.');\n                btnEl.disabled = false;\n                btnEl.textContent = 'Un-Submit';\n            }\n        } catch (err) {\n            console.error('Unsubmit error', err);\n            alert('An error occurred while un-submitting the assignment.');\n            btnEl.disabled = false;\n            btnEl.textContent = 'Un-Submit';\n        }\n    }\n\n    \/** \u2500\u2500 PAGINATION RENDER (synced with Assigned_Assignment.html) \u2500\u2500 **\/\n    function renderPagination(meta, page) {\n        currentPage = page;\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 = `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 = () => { if (currentPage > 1) { fetchTableData(currentPage - 1); } };\n        nextBtn.onclick = () => { if (currentPage < totalPages) { fetchTableData(currentPage + 1); } };\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 = () => { fetchTableData(pageNum); };\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    \/** \u2500\u2500 FILTER \/ CLEAR \u2500\u2500 **\/\n    function handleFilter() {\n        fetchTableData(1);\n    }\n\n    \/** \u2500\u2500 CSV DOWNLOAD: native browser download (shows in browser download bar) \u2500\u2500 **\/\n    function showCsvDownloadToast(show) {\n        const el = document.getElementById('csvDownloadToast');\n        if (!el) return;\n        el.classList.toggle('show', !!show);\n    }\n\n    async function handleDownloadCSV() {\n        if (!CAN_DOWNLOAD_CSV) return;\n        const btn = document.getElementById('btnDownloadCSV');\n        const originalText = btn ? btn.textContent : '+ Download CSV';\n        if (btn) {\n            btn.disabled = true;\n            btn.textContent = 'Downloading...';\n        }\n        showCsvDownloadToast(true);\n\n        try {\n            const token = localStorage.getItem('TOKEN');\n            if (!token) {\n                alert('You are not logged in. Please login again.');\n                return;\n            }\n\n            \/\/ Native navigation download so Chrome\/Edge download bar shows progress.\n            \/\/ Token goes in query because <a> navigation cannot send Authorization header.\n            const url = buildSubmitExportUrl();\n            url.searchParams.set('token', token);\n\n            const link = document.createElement('a');\n            link.href = url.toString();\n            link.rel = 'noopener';\n            document.body.appendChild(link);\n            link.click();\n            document.body.removeChild(link);\n        } catch (error) {\n            console.error('Submit export download error', error);\n            alert('Failed to download CSV. Please try again.');\n        } finally {\n            \/\/ Keep toast briefly so user notices browser download UI\n            setTimeout(() => {\n                showCsvDownloadToast(false);\n                if (btn) {\n                    btn.disabled = false;\n                    btn.textContent = originalText;\n                }\n            }, 2500);\n        }\n    }\n\n    \/** \u2500\u2500 UPGRADED RANGE DATE PICKER \u2500\u2500 **\/\n    const dpState = {\n        date: { viewYear: null, viewMonth: null, startDate: null, endDate: null, hoverDate: null, selectedDate: null, activePreset: null }\n    };\n    const DP_IDS = {\n        date: { dropdown: 'dpDropdownDate', backdrop: 'dpBackdropDate', title: 'dpCalTitleDate', days: 'dpDaysDate', title2: 'dpCalTitleDate2', days2: 'dpDaysDate2', display: 'filterDate' }\n    };\n    const DP_MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];\n    function dpToday() { const d = new Date(); d.setHours(0, 0, 0, 0); return d; }\n    function dpSameDay(a, b) {\n        if (!a) return false;\n        if (!b) return false;\n        return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();\n    }\n    function dpFmtISO(d) {\n        if (!d) return '';\n        return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;\n    }\n\n    function dpRenderCalendar(inst) {\n        const s = dpState[inst];\n        const ids = DP_IDS[inst];\n        let y2 = s.viewYear, m2 = s.viewMonth + 1;\n        if (m2 > 11) { m2 = 0; y2++; }\n        document.getElementById(ids.title).textContent = `${DP_MONTHS[s.viewMonth]} ${s.viewYear}`;\n        document.getElementById(ids.title2).textContent = `${DP_MONTHS[m2]} ${y2}`;\n        document.getElementById(ids.days).innerHTML = dpBuildDays(s.viewYear, s.viewMonth, s, inst);\n        document.getElementById(ids.days2).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++) 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, rE = s.hoverDate;\n                    if (rE < rS) { const t = rS; rS = rE; rE = t; }\n                    if (dpSameDay(cur, s.hoverDate)) {\n                        cls += (s.hoverDate < s.startDate) ? ' hover-start hover-range' : ' 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        if (!s.startDate) {\n            s.startDate = chosen;\n            s.endDate = null;\n        } else if (s.startDate && !s.endDate) {\n            if (chosen < s.startDate) {\n                s.endDate = s.startDate;\n                s.startDate = chosen;\n            } else {\n                s.endDate = chosen;\n            }\n        } else {\n            \/\/ Both are set, start new selection\n            s.startDate = chosen;\n            s.endDate = null;\n        }\n\n        s.hoverDate = null;\n        s.activePreset = null;\n        const dropId = DP_IDS[inst].dropdown;\n        document.querySelectorAll(`#${dropId} .dp-preset-item`).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('dpRangeDisplayDate');\n        if (!el) return;\n        if (s.startDate) {\n            if (s.endDate) {\n                el.textContent = `${dpFmtISO(s.startDate)} - ${dpFmtISO(s.endDate)}`;\n            } else {\n                el.textContent = `${dpFmtISO(s.startDate)} - 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) { s.viewMonth = 0; s.viewYear++; }\n        if (s.viewMonth < 0) { s.viewMonth = 11; s.viewYear--; }\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.querySelectorAll(`#${dropId} .dp-preset-item`).forEach(el =>\n            el.classList.toggle('active', el.dataset.preset === preset));\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); y.setDate(y.getDate() - 1); s.startDate = y; s.endDate = y; break; }\n            case 'last7':\n                { const y = new Date(today); y.setDate(y.getDate() - 6); s.startDate = y; s.endDate = new Date(today); break; }\n            case 'last30':\n                { const y = new Date(today); y.setDate(y.getDate() - 29); s.startDate = y; s.endDate = new Date(today); break; }\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)} - ${dpFmtISO(s.endDate)}`;\n                }\n            } else {\n                display.value = dpFmtISO(s.startDate);\n            }\n        } else {\n            display.value = '';\n        }\n        closeDatePicker(inst);\n        fetchTableData(1);\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.querySelectorAll(`#${dropId} .dp-preset-item`).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.querySelectorAll(`#${ids.dropdown} .dp-preset-item`).forEach(el =>\n                    el.classList.toggle('active', el.dataset.preset === 'today'));\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        const dd = document.getElementById(ids.dropdown);\n        const bd = document.getElementById(ids.backdrop);\n        if (dd) dd.classList.remove('open');\n        if (bd) bd.classList.remove('show');\n    }\n\n    \/** \u2500\u2500 CLEAR FILTERS \u2500\u2500 **\/\n    function clearFilters() {\n        ['filterAssignedTo', 'filterEntity', 'filterClient', 'filterAccount', 'filterProject', 'filterCategory'].forEach(id => {\n            const input = document.getElementById(id);\n            if (input) {\n                input.value = '';\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 firstOption = wrapper.querySelector('.custom-select-option.placeholder-option');\n                    labelEl.textContent = firstOption ? firstOption.textContent : 'Select';\n                    trigger.classList.add('placeholder-shown');\n                    wrapper.querySelectorAll('.custom-select-option').forEach(o => o.classList.remove('selected'));\n                }\n            }\n        });\n        document.getElementById('filterDate').value = '';\n        if (dpState.date) {\n            dpState.date.startDate = null;\n            dpState.date.endDate = null;\n            dpState.date.hoverDate = null;\n            dpState.date.selectedDate = null;\n            dpState.date.activePreset = null;\n            dpUpdateFooterRange('date');\n            dpRenderCalendar('date');\n        }\n        const pp = document.getElementById('filterPerPage');\n        if (pp) pp.value = '';\n        fetchTableData(1);\n    }\n\n    \/** PHP flash success after import redirect *\/\n    function showImportSuccessFlash() {\n        const params = new URLSearchParams(window.location.search);\n        const success = params.get('success');\n        if (!success) return;\n        alert(decodeURIComponent(success));\n        params.delete('success');\n        const qs = params.toString();\n        const cleanUrl = window.location.pathname + (qs ? `?${qs}` : '');\n        window.history.replaceState({}, '', cleanUrl);\n    }\n\n    \/** \u2500\u2500 INIT \u2500\u2500 **\/\n    async function init() {\n        if (IS_ADMIN) {\n            const btnImport = document.getElementById('btnCSVImport');\n            if (btnImport) btnImport.style.display = 'inline-flex';\n        }\n        if (!CAN_DOWNLOAD_CSV) {\n            const btnDownload = document.getElementById('btnDownloadCSV');\n            if (btnDownload) btnDownload.style.display = 'none';\n        }\n        if (!CAN_EDIT) {\n            const thEdit = document.getElementById('thEdit');\n            if (thEdit) thEdit.style.display = 'none';\n        }\n        showImportSuccessFlash();\n        await fetchDropdownData();\n        renderFilters();\n        fetchTableData(1);\n    }\n\n    window.onload = init;\n<\/script>\n<\/div><\/div>\n\n<\/div><\/div><\/div><\/div>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Submitted Work Assignments &#8211; Data Team Clear Filter + CSV Import + Download CSV Downloading CSV\u2026 Check your browser downloads bar for progress. Submitted Assignment Assigned Date Assigned To Client Project Entity Account Category DOS Count Amount Assigned DOS Completed DOS Pending DOS Hours Created By Approved On Remarks Status Edit Loading&#8230; \u00ab Previous Next&#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-181","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages\/181","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=181"}],"version-history":[{"count":49,"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages\/181\/revisions"}],"predecessor-version":[{"id":1263,"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/pages\/181\/revisions\/1263"}],"wp:attachment":[{"href":"https:\/\/ph-portal-v2.zyneventures.com\/index.php\/wp-json\/wp\/v2\/media?parent=181"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}