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>
84 lines
3.2 KiB
HTML
84 lines
3.2 KiB
HTML
{# 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>
|