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=`
${generateFilterHTML(filtersConfig,applied)}
`;
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+=`
`;
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
);
}
}