Initial import: eCW Charge Validation bot and results Portal

Snapshot of the working project as of 2026-10-23 (local 2d4d4fc), one
commit with no earlier history: the tracked files were de-identified
first (synthetic claim ids and patient data only; see Context.md
section 7). Credentials, run logs, screenshots, claim reports and client
workbooks are gitignored and not included.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ManikandanandClaude Opus 5.5 committed 2026-10-23 18:38:17 +05:30
commit ba15a574ab
205 files changed
+56772

No files matched your search

+83
View File
@@ -0,0 +1,83 @@
{# One claim's side panel — for the day page and a claim's history. A row
carries its data in data-fields (tojson: escaped for the attribute) and
data-details; the panel writes them with textContent only. #}
<aside class="drawer" id="claim-panel" hidden>
<div class="top"><h2 id="cp-title"></h2>
<button type="button" class="close">Close</button></div>
<div class="body">
<p><span id="cp-cat"></span> <span class="note" id="cp-when"></span></p>
<dl id="cp-fields"></dl>
<div id="cp-details-box" hidden><h3>Conditions and changes</h3>
<pre id="cp-details"></pre></div>
</div>
</aside>
<script>
function showClaim(tr) {
document.querySelectorAll('tr.sel').forEach(t => t.classList.remove('sel'));
tr.classList.add('sel');
$('cp-title').textContent = 'Claim ' + tr.dataset.claim;
const cat = tr.dataset.category || '';
$('cp-cat').className = CATEGORIES.includes(cat) ? 'cat ' + cat : '';
$('cp-cat').textContent = cat;
$('cp-when').textContent = tr.dataset.when || '';
const dl = $('cp-fields');
dl.replaceChildren();
// Only the fields that hold something: an empty field says nothing.
for (const [header, value] of JSON.parse(tr.dataset.fields || '[]')) {
if (!value) continue;
const dt = document.createElement('dt');
dt.textContent = header;
const dd = document.createElement('dd');
dd.textContent = value;
dl.append(dt, dd);
}
const det = tr.dataset.details || '';
$('cp-details').textContent = det;
$('cp-details-box').hidden = !det;
openPanel('claim-panel');
}
// 10 claims a page (operator, 2026-10-15), pagers above and below.
const PAGE_SIZE = 10;
const allRows = [...document.querySelectorAll('tbody tr[data-claim]')];
allRows.forEach(tr => tr.addEventListener('click', () => showClaim(tr)));
let page = 0;
const pageCount = () => Math.max(1, Math.ceil(allRows.length / PAGE_SIZE));
function goToPage(n) {
page = Math.min(Math.max(n, 0), pageCount() - 1);
allRows.forEach((tr, i) =>
tr.hidden = Math.floor(i / PAGE_SIZE) !== page);
drawPagers();
}
function drawPagers() {
const total = allRows.length;
for (const id of ['pager-top', 'pager-bottom']) {
const box = $(id);
if (!box) continue;
box.replaceChildren();
if (pageCount() < 2) continue;
const btn = (text, to, cur) => {
const b = document.createElement('button');
b.type = 'button'; b.textContent = text;
if (cur) b.className = 'cur';
b.disabled = cur || to < 0 || to >= pageCount();
b.onclick = () => {
goToPage(to);
// From the bottom pager the new page starts above the window.
if (id === 'pager-bottom')
$('pager-top').scrollIntoView({block: 'nearest'});
};
box.append(b);
};
btn('◀ Prev', page - 1, false);
for (let i = 0; i < pageCount(); i++) btn(String(i + 1), i, i === page);
btn('Next ▶', page + 1, false);
const info = document.createElement('span');
info.className = 'info';
info.textContent = `Showing ${page * PAGE_SIZE + 1}–` +
`${Math.min((page + 1) * PAGE_SIZE, total)} of ${total}`;
box.append(info);
}
}
goToPage(0);
</script>