mirror of
https://github.com/gauvainboiche/ketapk.git
synced 2026-09-02 11:13:11 +02:00
166 lines
5.8 KiB
JavaScript
166 lines
5.8 KiB
JavaScript
import { MODES, PK_MODELS, CLINICAL_THRESHOLDS, generateSimulationData } from '../../pkCore.js';
|
|
import { generatePDFReport } from './pdfExport.js';
|
|
|
|
let currentMode = MODES.ESKETAMINE;
|
|
let pkChart = null;
|
|
|
|
// Initialisation de la Grille Saisie (61 intervalles de 5 min)
|
|
const timelineInputs = Array.from({ length: 61 }, (_, i) => ({
|
|
time: i * 5,
|
|
bolusMg: 0,
|
|
perfRateMgKgH: 0
|
|
}));
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
initChart();
|
|
renderTimelineGrid();
|
|
setupEventListeners();
|
|
updateSimulation();
|
|
});
|
|
|
|
function initChart() {
|
|
const ctx = document.getElementById('pkChart').getContext('2d');
|
|
|
|
pkChart = new Chart(ctx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: timelineInputs.map(d => `${d.time}'`),
|
|
datasets: []
|
|
},
|
|
options: {
|
|
responsive: true,
|
|
maintainAspectRatio: false,
|
|
scales: {
|
|
y: {
|
|
beginAtZero: true,
|
|
max: CLINICAL_THRESHOLDS[currentMode].maxScale,
|
|
title: { display: true, text: 'Cp (ng/mL)', color: '#94a3b8' },
|
|
grid: { color: 'rgba(51, 65, 85, 0.3)' }
|
|
},
|
|
x: {
|
|
title: { display: true, text: 'Temps (minutes)', color: '#94a3b8' },
|
|
grid: { color: 'rgba(51, 65, 85, 0.3)' }
|
|
}
|
|
},
|
|
plugins: {
|
|
legend: { labels: { color: '#f8fafc' } }
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function updateSimulation() {
|
|
const weight = parseFloat(document.getElementById('inputWeight').value) || 70;
|
|
|
|
const datasets = [];
|
|
|
|
if (document.getElementById('chkDomino').checked) {
|
|
datasets.push({
|
|
label: PK_MODELS.DOMINO.name,
|
|
data: generateSimulationData({ model: PK_MODELS.DOMINO, weightKg: weight, timelineInputs }),
|
|
borderColor: PK_MODELS.DOMINO.color,
|
|
borderWidth: 3,
|
|
tension: 0.2
|
|
});
|
|
}
|
|
|
|
if (document.getElementById('chkClements').checked) {
|
|
datasets.push({
|
|
label: PK_MODELS.CLEMENTS.name,
|
|
data: generateSimulationData({ model: PK_MODELS.CLEMENTS, weightKg: weight, timelineInputs }),
|
|
borderColor: PK_MODELS.CLEMENTS.color,
|
|
borderWidth: 3,
|
|
tension: 0.2
|
|
});
|
|
}
|
|
|
|
if (document.getElementById('chkKamp').checked) {
|
|
datasets.push({
|
|
label: PK_MODELS.KAMP.name,
|
|
data: generateSimulationData({ model: PK_MODELS.KAMP, weightKg: weight, timelineInputs }),
|
|
borderColor: PK_MODELS.KAMP.color,
|
|
borderWidth: 3,
|
|
tension: 0.2
|
|
});
|
|
}
|
|
|
|
pkChart.data.datasets = datasets;
|
|
pkChart.options.scales.y.max = CLINICAL_THRESHOLDS[currentMode].maxScale;
|
|
pkChart.update();
|
|
}
|
|
|
|
function renderTimelineGrid() {
|
|
const container = document.getElementById('timelineGrid');
|
|
container.innerHTML = '';
|
|
|
|
timelineInputs.forEach((item, idx) => {
|
|
const col = document.createElement('div');
|
|
col.className = 'flex-1 bg-slate-900 border border-slate-700/60 rounded-xl p-2 text-center text-xs flex flex-col gap-1.5';
|
|
col.innerHTML = `
|
|
<div class="font-bold text-amber-400 border-b border-slate-800 pb-1">${item.time} min</div>
|
|
<div>
|
|
<span class="text-[10px] text-slate-500 block">Bolus (mg)</span>
|
|
<input type="number" data-idx="${idx}" data-field="bolusMg" value="${item.bolusMg || ''}" placeholder="0" class="w-full bg-slate-800 border border-slate-700 text-center rounded text-white py-1 outline-none">
|
|
</div>
|
|
<div>
|
|
<span class="text-[10px] text-slate-500 block">Perf (mg/kg/h)</span>
|
|
<input type="number" data-idx="${idx}" data-field="perfRateMgKgH" value="${item.perfRateMgKgH || ''}" placeholder="0" class="w-full bg-slate-800 border border-slate-700 text-center rounded text-white py-1 outline-none">
|
|
</div>
|
|
`;
|
|
container.appendChild(col);
|
|
});
|
|
}
|
|
|
|
function setupEventListeners() {
|
|
document.getElementById('timelineGrid').addEventListener('input', (e) => {
|
|
const idx = e.target.dataset.idx;
|
|
const field = e.target.dataset.field;
|
|
if (idx !== undefined && field) {
|
|
timelineInputs[idx][field] = parseFloat(e.target.value) || 0;
|
|
updateSimulation();
|
|
}
|
|
});
|
|
|
|
document.getElementById('btnEsk').addEventListener('click', () => setMode(MODES.ESKETAMINE));
|
|
document.getElementById('btnRac').addEventListener('click', () => setMode(MODES.RACEMIQUE));
|
|
|
|
['inputWeight', 'chkDomino', 'chkClements', 'chkKamp'].forEach(id => {
|
|
document.getElementById(id).addEventListener('change', updateSimulation);
|
|
});
|
|
|
|
document.getElementById('btnRaz').addEventListener('click', () => {
|
|
timelineInputs.forEach(item => { item.bolusMg = 0; item.perfRateMgKgH = 0; });
|
|
renderTimelineGrid();
|
|
updateSimulation();
|
|
});
|
|
|
|
document.getElementById('btnExportPdf').addEventListener('click', () => {
|
|
// On rassemble les données actuelles du formulaire
|
|
const patientData = {
|
|
weight: document.getElementById('inputWeight').value || 70,
|
|
age: document.getElementById('inputAge').value || 50,
|
|
height: document.getElementById('inputHeight').value || 170
|
|
};
|
|
|
|
// On lance l'exportation (pkChart et currentMode sont des variables globales de app.js)
|
|
generatePDFReport(pkChart, patientData, currentMode);
|
|
});
|
|
}
|
|
|
|
function setMode(mode) {
|
|
currentMode = mode;
|
|
const btnEsk = document.getElementById('btnEsk');
|
|
const btnRac = document.getElementById('btnRac');
|
|
const concInput = document.getElementById('inputConc');
|
|
|
|
if (mode === MODES.ESKETAMINE) {
|
|
btnEsk.className = 'px-4 py-1.5 rounded-lg text-sm font-semibold bg-amber-500 text-slate-950 shadow';
|
|
btnRac.className = 'px-4 py-1.5 rounded-lg text-sm font-semibold text-slate-300 hover:text-white';
|
|
concInput.value = CLINICAL_THRESHOLDS[MODES.ESKETAMINE].defaultConcentration;
|
|
} else {
|
|
btnRac.className = 'px-4 py-1.5 rounded-lg text-sm font-semibold bg-fuchsia-500 text-slate-950 shadow';
|
|
btnEsk.className = 'px-4 py-1.5 rounded-lg text-sm font-semibold text-slate-300 hover:text-white';
|
|
concInput.value = CLINICAL_THRESHOLDS[MODES.RACEMIQUE].defaultConcentration;
|
|
}
|
|
updateSimulation();
|
|
} |