From 290724c88397c286f7eb47eb75f1978ec42b0f3a Mon Sep 17 00:00:00 2001 From: Daniel Date: Tue, 14 Apr 2026 12:27:14 +0200 Subject: [PATCH] Revert "Bilirubin chart: BiliTool/PediTools-style visual polish (no data changes)" This reverts commit e6d90f4ba686d73aaf3958e68b08bb2d1c4026de. --- public/js/calculators.js | 128 ++++----------------------------------- 1 file changed, 11 insertions(+), 117 deletions(-) diff --git a/public/js/calculators.js b/public/js/calculators.js index 7eb69de..71601fa 100644 --- a/public/js/calculators.js +++ b/public/js/calculators.js @@ -1404,64 +1404,6 @@ return keys.map(function(h) { return { x: h, y: table[h] }; }); } - // Chart.js plugin — labels threshold lines at their right end (like - // BiliTool/PediTools do on their plots) and re-paints the patient dot - // on top so labels never cover it. - var biliLabelPlugin = { - id: 'biliThresholdLabels', - afterDatasetsDraw: function(chart) { - var ctx = chart.ctx; - var font = '700 11px -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif'; - chart.data.datasets.forEach(function(ds, i) { - if (!ds.label || ds.label === 'Patient') return; - var meta = chart.getDatasetMeta(i); - if (!meta || meta.hidden || !meta.data || !meta.data.length) return; - var last = meta.data[meta.data.length - 1]; - if (!last) return; - var color = typeof ds.borderColor === 'string' ? ds.borderColor : '#555'; - var m = color.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/); - if (m) color = 'rgb(' + m[1] + ',' + m[2] + ',' + m[3] + ')'; - ctx.save(); - ctx.font = font; - ctx.textAlign = 'left'; - ctx.textBaseline = 'middle'; - ctx.lineWidth = 3; - ctx.strokeStyle = 'rgba(255,255,255,0.92)'; - ctx.strokeText(ds.label, last.x + 5, last.y); - ctx.fillStyle = color; - ctx.fillText(ds.label, last.x + 5, last.y); - ctx.restore(); - }); - // Patient dot on top - chart.data.datasets.forEach(function(ds, i) { - if (ds.label !== 'Patient') return; - var meta = chart.getDatasetMeta(i); - if (!meta || !meta.data || !meta.data.length) return; - var pt = meta.data[0]; - if (!pt) return; - ctx.save(); - ctx.beginPath(); - ctx.arc(pt.x, pt.y, 5, 0, Math.PI * 2); - ctx.fillStyle = '#2563eb'; - ctx.fill(); - ctx.lineWidth = 1.8; - ctx.strokeStyle = '#ffffff'; - ctx.stroke(); - // Value label next to the dot - ctx.font = '700 12px -apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif'; - ctx.textAlign = 'left'; - ctx.textBaseline = 'middle'; - ctx.lineWidth = 3; - ctx.strokeStyle = 'rgba(255,255,255,0.95)'; - var lbl = ds.data[0].y.toFixed(1); - ctx.strokeText(lbl, pt.x + 9, pt.y); - ctx.fillStyle = '#1e40af'; - ctx.fillText(lbl, pt.x + 9, pt.y); - ctx.restore(); - }); - } - }; - function renderBiliChart(patientHours, patientTSB, curveDatasets) { if (typeof Chart === 'undefined') return; var container = document.getElementById('bili-chart-container'); @@ -1474,61 +1416,33 @@ return Object.assign({ pointRadius: 0, pointHoverRadius: 0, tension: 0.3, order: 10 }, ds); }); - // Patient point (native dataset — used for tooltip + legend. The plugin - // re-paints it on top at the end so threshold labels never cover it.) + // Patient point datasets.push({ label: 'Patient', data: [{ x: patientHours, y: patientTSB }], backgroundColor: '#2563eb', - borderColor: '#ffffff', - borderWidth: 1.8, - pointRadius: 5, - pointHoverRadius: 7, + borderColor: '#1d4ed8', + pointRadius: 8, + pointHoverRadius: 10, showLine: false, type: 'scatter', - order: -1 + order: 0 }); - // Derive nice x-axis range from actual data (clamped to a minimum - // visible window so single-point patients still show in context). - var xMax = patientHours + 6; - var xMin = 12; - curveDatasets.forEach(function(ds) { - (ds.data || []).forEach(function(p) { - if (typeof p.x === 'number') xMax = Math.max(xMax, p.x); - }); - }); - xMax = Math.min(Math.max(xMax, 72), 180); - _chartInstances['bili-chart-canvas'] = new Chart(document.getElementById('bili-chart-canvas'), { type: 'line', data: { datasets: datasets }, - plugins: [biliLabelPlugin], options: { responsive: true, maintainAspectRatio: true, aspectRatio: 1.6, animation: { duration: 300 }, - // Extra right padding so the threshold labels drawn past the - // last data point stay inside the canvas. - layout: { padding: { right: 40 } }, scales: { - x: { - type: 'linear', - title: { display: true, text: 'Age (hours)', font: { size: 12, weight: 'bold' } }, - min: xMin, max: xMax, - ticks: { stepSize: 12, font: { size: 11 } }, - grid: { color: 'rgba(0,0,0,0.08)' } - }, - y: { - title: { display: true, text: 'TSB (mg/dL)', font: { size: 12, weight: 'bold' } }, - min: 0, - ticks: { stepSize: 5, font: { size: 11 } }, - grid: { color: 'rgba(0,0,0,0.08)' } - } + x: { type: 'linear', title: { display: true, text: 'Age (hours)', font: { size: 12, weight: 'bold' } }, min: 12, max: 150, grid: { color: 'rgba(0,0,0,0.05)' } }, + y: { title: { display: true, text: 'TSB (mg/dL)', font: { size: 12, weight: 'bold' } }, min: 0, grid: { color: 'rgba(0,0,0,0.05)' } } }, plugins: { - legend: { display: false }, + legend: { display: true, position: 'bottom', labels: { font: { size: 11 }, usePointStyle: true, pointStyle: 'line' } }, tooltip: { callbacks: { label: function(ctx) { @@ -1639,32 +1553,12 @@ '' + '

GA ' + ga + ' weeks, ' + (risk === 'medium' ? 'with' : 'without') + ' neurotoxicity risk factors. AAP 2022 CPG (exact values from published nomograms). Always use clinical judgment.

'; - // Chart: clinical BiliTool/PediTools-style layout - // - Green tint below the phototherapy line (safe zone) - // - Amber tint between phototherapy and exchange (treatment zone) - // - Dashed crimson exchange line above (danger threshold) + // Chart: phototherapy + exchange threshold lines vs patient var chartDatasets = [ - { - label: 'Phototherapy', - data: generateThresholdCurve(table), - borderColor: '#f97316', // orange line - borderWidth: 2.4, - borderDash: [], - fill: 'origin', - backgroundColor: 'rgba(22,163,74,0.07)' // faint green below = "safe" - } + { label: 'Phototherapy Threshold', data: generateThresholdCurve(table), borderColor: '#ef4444', borderWidth: 2, borderDash: [], fill: { target: 'origin', above: 'rgba(239,68,68,0.08)' } } ]; if (exchangeTable) { - chartDatasets.push({ - label: 'Exchange', - data: generateThresholdCurve(exchangeTable), - borderColor: '#b91c1c', // crimson line - borderWidth: 2.4, - borderDash: [6, 3], - // Fill between this line and the phototherapy line (dataset 0) - fill: { target: 0 }, - backgroundColor: 'rgba(252,211,77,0.22)' // amber band = "treat" - }); + chartDatasets.push({ label: 'Exchange Transfusion', data: generateThresholdCurve(exchangeTable), borderColor: '#7f1d1d', borderWidth: 2, borderDash: [6,3], fill: false }); } renderBiliChart(hours, tsb, chartDatasets); });