function generateFilterChips(applied={}){ let html=''; Object.keys(applied).forEach(key=>{ const value=applied[key]; if(!value||(Array.isArray(value)&&!value.length))return; html+=` ${key}: ${Array.isArray(value)?value.join(', '):value} `; }); return html; } /* COMPONENT */ const triggerComp=ap.$('0a337864-15fd-4e94-8da1-59b7c89a0b17'); /* FILTER CONFIG */ const filtersConfig=[ {label:'Case ID',key:'cid',type:'range'}, {label:'eSub ID',filter:'eSubNum',type:'search'}, {label:'Submission Date',key:'submissionDate',type:'date-range'}, {label:'Policy Number',filter:'policyNumber',type:'search'}, {label:'Insured Name',filter:'insuredName',type:'search'}, {label:'Priority',filter:'priority',type:'multi-select',options:['High','Medium','Low']}, {label:'Agent Name',filter:'agentName',type:'search'}, {label:'Claim Number',filter:'claimNumber',type:'search'}, {label:'Hospital Name',filter:'hospitalName',type:'search'}, {label:'Status',filter:'status',type:'multi-select',options:['Pending','Approved','Rejected']} ]; /* INIT */ function waitForTrigger(){ const root=triggerComp.shadowRoot||triggerComp; if(!root)return setTimeout(waitForTrigger,300); const btn=root.querySelector('button')||root.querySelector('.p-button')||root.firstElementChild; if(!btn)return setTimeout(waitForTrigger,300); if(btn.dataset.filterAttached==='true')return; btn.dataset.filterAttached='true'; btn.addEventListener('click',e=>{ e.preventDefault(); e.stopPropagation(); openCustomFilterDialog(btn); }); } /* POPUP */ function openCustomFilterDialog(buttonEl){ const existing=document.querySelector('#custom-filter-popup'); if(existing){existing.remove();return;} const applied=alpha.local.get().appliedFilters||{}; const popup=document.createElement('div'); popup.id='custom-filter-popup'; popup.style.position='fixed'; popup.style.zIndex='999999'; popup.innerHTML=` `; document.body.appendChild(popup); function updatePopupPosition(){ const rect=buttonEl.getBoundingClientRect(); const popupWidth=280; const popupHeight=340; let top=rect.bottom+6; let left=rect.right-popupWidth; const viewportWidth=window.innerWidth; const viewportHeight=window.innerHeight; if(left+popupWidth>viewportWidth-8){ left=viewportWidth-popupWidth-8; } if(left<8)left=8; if(top+popupHeight>viewportHeight-8){ top=rect.top-popupHeight-6; } const isOutsideViewport= rect.bottom<0|| rect.top>viewportHeight|| rect.right<0|| rect.left>viewportWidth; if(isOutsideViewport){ closePopup(); return; } popup.style.top=`${top}px`; popup.style.left=`${left}px`; } updatePopupPosition(); function closePopup(){ popup.remove(); document.removeEventListener('click',outsideClickHandler); window.removeEventListener('scroll',updatePopupPosition,true); window.removeEventListener('resize',updatePopupPosition); } window.addEventListener('scroll',updatePopupPosition,true); window.addEventListener('resize',updatePopupPosition); setTimeout(()=>{ document.addEventListener('click',outsideClickHandler); },0); function outsideClickHandler(e){ if(!popup.contains(e.target)&&!buttonEl.contains(e.target)){ closePopup(); } } popup.querySelector('.popup-close').addEventListener('click',closePopup); popup.addEventListener('click',e=>{ const header=e.target.closest('.panel-header'); if(!header)return; const panel=header.closest('.filter-panel'); panel.classList.toggle('collapsed'); }); popup.addEventListener('input',()=>{ validateFilters(popup); toggleApplyButton(popup); }); popup.querySelector('.btn-clear').addEventListener('click',()=>{ popup.querySelectorAll('input').forEach(input=>{ if(input.type==='checkbox'){ input.checked=false; }else{ input.value=''; } }); alpha.local.update('appliedFilters',{}); alpha.local.update('filterChips',''); validateFilters(popup); toggleApplyButton(popup); fetchCompletedCases({}); }); popup.querySelector('.btn-apply').addEventListener('click',()=>{ validateFilters(popup); if(hasValidationErrors(popup))return; const values=getFilterValues(popup); alpha.local.update('appliedFilters',values); alpha.local.update('filterChips',generateFilterChips(values)); fetchCompletedCases(values); closePopup(); }); validateFilters(popup); toggleApplyButton(popup); } /* HTML */ function generateFilterHTML(config,applied){ let html=''; config.forEach(filter=>{ const key=filter.key||filter.filter; html+=`
${filter.label}
`; if(filter.type==='range'){ html+=`
`; } if(filter.type==='search'){ html+=`
`; } if(filter.type==='date-range'){ html+=`
`; } if(filter.type==='multi-select'){ const selected=(applied[filter.filter]||[]).map(v=>v.toLowerCase()); filter.options.forEach(opt=>{ const checked=selected.includes(opt.toLowerCase())?'checked':''; html+=`
${opt}
`; }); } html+=`
`; }); return html; } /* VALIDATION */ function validateFilters(root){ const minInput=root.querySelector('[data-filter="cid"][data-type="min"]'); const maxInput=root.querySelector('[data-filter="cid"][data-type="max"]'); const min=Number(minInput?.value); const max=Number(maxInput?.value); const cidError=root.querySelector('[data-error="cid"]'); if(minInput?.value&&min<0){ cidError.innerText='Min value cannot be less than 0'; cidError.style.display='block'; }else if(maxInput?.value&&max<0){ cidError.innerText='Max value cannot be less than 0'; cidError.style.display='block'; }else if(minInput?.value&&maxInput?.value&&min>max){ cidError.innerText='Min cannot exceed Max'; cidError.style.display='block'; }else{ cidError.innerText=''; cidError.style.display='none'; } const fromDateInput=root.querySelector('[data-filter="submissionDate"][data-type="from"]'); const toDateInput=root.querySelector('[data-filter="submissionDate"][data-type="to"]'); const fromDate=fromDateInput?.value; const toDate=toDateInput?.value; const dateError=root.querySelector('[data-error="submissionDate"]'); if(fromDate&&toDate&&new Date(toDate)el.style.display==='block'); } function hasAnyFilterValue(root){ const inputs=root.querySelectorAll('input[data-filter]'); for(let input of inputs){ if(input.type==='checkbox'&&input.checked)return true; if(input.type!=='checkbox'&&input.value)return true; } return false; } function toggleApplyButton(root){ const btn=root.querySelector('.btn-apply'); if(!btn)return; const hasErrors=hasValidationErrors(root); const hasValues=hasAnyFilterValue(root); if(hasErrors||!hasValues){ btn.disabled=true; btn.classList.add('disabled'); }else{ btn.disabled=false; btn.classList.remove('disabled'); } } function getFilterValues(root){ const result={}; root.querySelectorAll('input[data-filter]').forEach(input=>{ const filter=input.dataset.filter; const type=input.dataset.type; if(input.type==='checkbox'){ if(input.checked){ if(!result[filter]){ result[filter]=[]; } result[filter].push(input.value); } return; } if(!input.value)return; if(filter==='cid'){ if(type==='min'){ result.fromCid=Number(input.value); } if(type==='max'){ result.toCid=Number(input.value); } return; } if(filter==='submissionDate'){ if(type==='from'){ result.fromSubmissionDate=input.value; } if(type==='to'){ result.toSubmissionDate=input.value; } return; } result[filter]=input.value; }); return result; } function generateFilterChips(applied){ let html=''; Object.keys(applied||{}).forEach(key=>{ const value=applied[key]; if(!value)return; html+=` ${key}:${Array.isArray(value)?value.join(', '):value} `; }); return html; } waitForTrigger(); async function fetchCompletedCases(filterBody){ try{ const options={ url:{ type:'environment', value:{ __alpha_env__:'PHI_BACKEND_BASE_URL' } }, path:'/cases/completed/fetch', method:'POST', headers:{ 'Content-Type':'application/json', auth_token:{ type:'environment', value:{ __alpha_env__:'PHI_AUTH_TOKEN' } } }, body:{ filterBody }, parseResponseBody:true }; const httpRes=await ap.http( options.url, { method:options.method, headers:options.headers, path:options.path, body:JSON.stringify(options.body) } ); const res=await httpRes.json(); console.log('API RESPONSE =>',res); alpha.local.update( 'closed_cases', res?.casesDetails || [] ); alpha.local.update( 'totalCount', Number( res?.totalCount?.[0]?.total_count ) || 0 ); const table=ap.$( '2077cc64-eded-48da-bb87-27360331d005' ); table.pageNumber=1; table.rows=5; window.dispatchEvent( new CustomEvent( 'alpha_element:connected_callback', { detail:{ element:table } } ) ); }catch(err){ ap.toast.showToast({ status:'error', title:'Filter Failed', message: 'Failed to fetch filtered records' }); console.error( 'FILTER API ERROR =>', err ); } }