|
301 | 301 | let wlFilter='all',wlSearch='',selectedP360=null,selectedCohort=null,lastTab='overview'; |
302 | 302 |
|
303 | 303 | async function sql(q){const r=await fetch(`${AIDBOX_URL}/$sql`,{method:'POST',headers:{'Authorization':AUTH,'Content-Type':'application/json'},body:JSON.stringify([q])});if(!r.ok)throw new Error(`SQL ${r.status}`);const t=await r.text();return t.trim()?JSON.parse(t):[]} |
304 | | -function buildSQL(id,s,e,p){let q=MEASURES[id].sql;q=q.replace(/\{PERIOD_START\}/g,s).replace(/\{PERIOD_END\}/g,e);if(p)q=q.replace('ORDER BY ap.patient_id;',`WHERE ap.patient_id='${p}'\nORDER BY ap.patient_id;`);return q} |
| 304 | +function buildSQL(id,s,e,p){let q=p&&MEASURES[id].sql_subject?MEASURES[id].sql_subject:MEASURES[id].sql;q=q.replace(/\{PERIOD_START\}/g,s).replace(/\{PERIOD_END\}/g,e);if(p)q=MEASURES[id].sql_subject?q.replace(/\{PATIENT_ID\}/g,p):q.replace('ORDER BY ap.patient_id;',`WHERE ap.patient_id='${p}'\nORDER BY ap.patient_id;`);return q} |
305 | 305 | function gapStatus(r){const ip=+r.ip,exc=+r.exc,num=+r.num;if(ip===0)return{label:'Not in IP',cls:'gap-not-in-ip',key:'noip'};if(exc===1)return{label:'Excluded',cls:'gap-excluded',key:'excl'};if(num===1)return{label:'Closed',cls:'gap-closed',key:'closed'};return{label:'Open',cls:'gap-open',key:'open'}} |
306 | 306 | function calcStats(rows){let ip=0,den=0,exc=0,num=0,open=0,closed=0,excluded=0,noip=0;for(const r of rows){const rip=+r.ip,rden=+r.den,rexc=+r.exc,rnum=+r.num;ip+=rip;den+=rden;exc+=rexc;num+=rnum;if(rip===0)noip++;else if(rnum===1)closed++;else if(rexc===1)excluded++;else open++}return{total:rows.length,ip,den,exc,num,open,closed,excluded,noip,score:den>0?(num/Math.max(den-exc,1)*100):null}} |
307 | 307 | function getPeriod(){return{start:document.getElementById('period-start').value,end:document.getElementById('period-end').value}} |
|
478 | 478 | async function loadEvidence(mid,pid,targetId){ |
479 | 479 | const m=MEASURES[mid];const el=document.getElementById(targetId);if(!m.diagnostic_sql){el.innerHTML='<div class="evidence-panel open"><span class="ev-none">No diagnostic SQL</span></div>';return} |
480 | 480 | el.innerHTML='<div class="evidence-panel open"><span class="ev-none">Loading...</span></div>';const{start,end}=getPeriod(); |
481 | | - try{let diag=m.diagnostic_sql.replace(/\{PERIOD_START\}/g,start).replace(/\{PERIOD_END\}/g,end).replace(/\{PATIENT_ID\}/g,pid);const d=(await sql(diag))[0]||{};let evRows=[];if(m.evidence_sql){try{const all=await sql(m.evidence_sql.replace(/\{PERIOD_START\}/g,start).replace(/\{PERIOD_END\}/g,end));evRows=all.filter(r=>r.patient_id===pid)}catch(e){}} |
| 481 | + try{let diag=m.diagnostic_sql.replace(/\{PERIOD_START\}/g,start).replace(/\{PERIOD_END\}/g,end).replace(/\{PATIENT_ID\}/g,pid);const d=(await sql(diag))[0]||{};let evRows=[];if(m.evidence_sql_subject){try{const evQuery=m.evidence_sql_subject.replace(/\{PERIOD_START\}/g,start).replace(/\{PERIOD_END\}/g,end).replace(/\{PATIENT_ID\}/g,pid);evRows=await sql(evQuery)}catch(e){}}else if(m.evidence_sql){try{const all=await sql(m.evidence_sql.replace(/\{PERIOD_START\}/g,start).replace(/\{PERIOD_END\}/g,end));evRows=all.filter(r=>r.patient_id===pid)}catch(e){}} |
482 | 482 | let html='<div class="evidence-panel open"><table class="decision-table"><thead><tr><th>Step</th><th>CTE</th><th>Result</th></tr></thead><tbody>'; |
483 | 483 | for(const step of m.steps){const val=d[step.cte],isYes=val==='YES';const isSummary=['denominator_exclusion','numerator','initial_population'].includes(step.cte);html+=`<tr${isSummary?' class="step-summary"':''}><td>${isSummary?'<strong>'+step.label+'</strong>':step.label}</td><td><code>${step.cte}</code></td><td class="${isYes?'yes':'no'}">${isSummary?'<strong>'+(isYes?'YES':'no')+'</strong>':(val||'—')}</td></tr>`}html+='</tbody></table>'; |
484 | 484 | const ipItems=evRows.filter(r=>r.ip_code_display);const numItems=evRows.filter(r=>r.code_display||r.exclusion_pathway); |
|
0 commit comments