bilirubin-calculator/src/bilirubin_app.js

163 lines
4.4 KiB
JavaScript

/*
Neonatal jaundice treatment threshold calculator
Copyright (C) 2024-2025 Lee Yingtong Li
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
// --------------
// Graph plotting
function plotGraphData() {
let gestation = document.getElementById('gestation').valueAsNumber;
if (isNaN(gestation) || gestation < 23) {
chart.data.datasets[0].data = [];
chart.data.datasets[1].data = [];
} else {
chart.data.datasets[0].data = [...Array(14*24).keys()].map((i) => i / 24).map((d) => ({x: d, y: nice_phototherapy_thresh(d, gestation)}));
chart.data.datasets[1].data = [...Array(14*24).keys()].map((i) => i / 24).map((d) => ({x: d, y: nice_exchange_thresh(d, gestation)}));
}
chart.update();
}
Chart.defaults.color = '#111827'; // gray-900
Chart.defaults.font.family = 'Manrope, Helvetica, Arial, sans-serif';
const chart = new Chart(document.getElementById('bilirubinChart'), {
type: 'scatter',
data: {
datasets: [
{
label: 'Phototherapy',
data: [],
showLine: true,
pointStyle: false
},
{
label: 'Exchange transfusion',
data: [],
showLine: true,
pointStyle: false
},
{
label: 'Measurement',
data: []
}
]
},
options: {
scales: {
x: {
title: {
display: true,
text: 'Chronological age (days)'
},
min: 0,
max: 14,
ticks: {
stepSize: 0.25,
callback: (value) => value % 1 == 0 ? value : '',
autoSkip: false,
maxRotation: 0
},
grid: {
color: (context) => context.tick.value % 1 == 0 ? '#9ca3af' : '#e5e7eb' // gray-400 / gray-200
}
},
y: {
title: {
display: true,
text: 'Total bilirubin (μmol/L)'
},
min: 0,
max: 550,
ticks: {
stepSize: 10,
callback: (value) => value % 50 == 0 ? value : '',
autoSkip: false
},
grid: {
color: (context) => context.tick.value % 50 == 0 ? '#9ca3af' : '#e5e7eb' // gray-400 / gray-200
}
}
},
interaction: {
mode: 'x',
intersect: false
},
plugins: {
tooltip: {
callbacks: {
title: (context) => prettyPrintDays(context[0].parsed.x),
label: (context) => context.dataset.label + ': ' + Math.round(context.parsed.y)
},
filter: (context, idx, items) => Math.abs(context.parsed.x - items[0].parsed.x) < 0.5/24
}
},
maintainAspectRatio: false
}
});
plotGraphData();
// ------------
// Prefill form
let dateNow = dateToISOStringLocal(new Date());
if (document.getElementById('time_birth').value === '') {
document.getElementById('time_birth').value = dateNow;
}
if (document.getElementById('time_measurement').value === '') {
document.getElementById('time_measurement').value = dateNow;
}
// --------------------------
// Plot bilirubin measurement
function updateBilirubin() {
let resultDiv = document.getElementById('result');
let resultP = resultDiv.querySelector('p');
let bilirubin = document.getElementById('bilirubin').valueAsNumber;
let gestation = document.getElementById('gestation').valueAsNumber;
if (document.getElementById('time_birth').value === '') {
resultDiv.className = 'hidden';
return;
}
if (document.getElementById('time_measurement').value === '') {
resultDiv.className = 'hidden';
return;
}
if (isNaN(bilirubin)) {
resultDiv.className = 'hidden';
return;
}
if (isNaN(gestation) || gestation < 23) {
resultDiv.className = 'hidden';
return;
}
let [d, result_text, text_colour, background_colour, accent_colour] = describeBilirubin(gestation, new Date(document.getElementById('time_birth').value), new Date(document.getElementById('time_measurement').value), bilirubin);
chart.data.datasets[2].data = [{x: d, y: bilirubin}];
chart.update();
resultDiv.className = 'border-l-4 ' + accent_colour + ' ' + background_colour + ' py-2 px-4 mt-4';
resultP.className = 'text-sm ' + text_colour;
resultP.innerHTML = result_text;
}
updateBilirubin();