Update web/index.html
Browse files- web/index.html +30 -23
web/index.html
CHANGED
|
@@ -710,11 +710,23 @@
|
|
| 710 |
const response = await api.getDashboardStats().catch(() => null);
|
| 711 |
if (response && response.success) {
|
| 712 |
const stats = response.stats;
|
| 713 |
-
|
| 714 |
-
|
| 715 |
-
|
| 716 |
-
|
| 717 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 718 |
} else {
|
| 719 |
showErrorMessage('Error cargando estadísticas del dashboard');
|
| 720 |
}
|
|
@@ -723,30 +735,25 @@
|
|
| 723 |
function updateStatCard(selector, value) {
|
| 724 |
const card = $(selector);
|
| 725 |
const valueElement = card.find('span.h3');
|
| 726 |
-
const currentValue = parseInt(valueElement.text()) || 0;
|
| 727 |
|
| 728 |
-
if (typeof value === '
|
| 729 |
-
const targetValue = parseInt(value) || 0;
|
| 730 |
-
animateValue(valueElement[0], currentValue, targetValue, 1000);
|
| 731 |
-
} else {
|
| 732 |
valueElement.text(value);
|
|
|
|
|
|
|
|
|
|
| 733 |
}
|
| 734 |
}
|
| 735 |
|
| 736 |
-
// Función para animar valores numéricos
|
| 737 |
function animateValue(element, start, end, duration) {
|
| 738 |
if (!element) return;
|
| 739 |
-
|
| 740 |
-
const
|
| 741 |
-
const
|
| 742 |
-
|
|
|
|
| 743 |
const progress = Math.min(elapsed / duration, 1);
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
| 747 |
-
if (progress < 1) {
|
| 748 |
-
window.requestAnimationFrame(step);
|
| 749 |
-
}
|
| 750 |
};
|
| 751 |
window.requestAnimationFrame(step);
|
| 752 |
}
|
|
@@ -912,7 +919,7 @@
|
|
| 912 |
tbody.append(`
|
| 913 |
<tr>
|
| 914 |
<td>${date}</td>
|
| 915 |
-
<td>${consultation.patient_name || 'Desconocido'}</td>
|
| 916 |
<td><span class="badge ${resultClass}">${resultText}</span></td>
|
| 917 |
<td>${confidence}</td>
|
| 918 |
</tr>
|
|
@@ -939,7 +946,7 @@
|
|
| 939 |
<div class="row mb-3">
|
| 940 |
<div class="col-md-6">
|
| 941 |
<h6>Información Básica</h6>
|
| 942 |
-
<p><strong>Paciente:</strong> ${consultation.patient_name || 'Desconocido'}</p>
|
| 943 |
<p><strong>Fecha:</strong> ${consultation.consultationDate || 'N/A'}</p>
|
| 944 |
</div>
|
| 945 |
<div class="col-md-6">
|
|
|
|
| 710 |
const response = await api.getDashboardStats().catch(() => null);
|
| 711 |
if (response && response.success) {
|
| 712 |
const stats = response.stats;
|
| 713 |
+
// Usar || 0 para evitar undefined/null que causan contadores negativos
|
| 714 |
+
const totalPatients = parseInt(stats.total_patients || stats.total_unique_patients || 0);
|
| 715 |
+
const positiveCases = parseInt(stats.positive_cases || stats.patients_with_rd || 0);
|
| 716 |
+
const negativeCases = parseInt(stats.negative_cases || stats.patients_without_rd || 0);
|
| 717 |
+
const positivityRate = parseFloat(stats.positivity_rate || 0).toFixed(1);
|
| 718 |
+
|
| 719 |
+
updateStatCard('#totalPatientsCard', totalPatients);
|
| 720 |
+
updateStatCard('#positiveCasesCard', positiveCases);
|
| 721 |
+
updateStatCard('#negativeCasesCard', negativeCases);
|
| 722 |
+
updateStatCard('#positivityRateCard', positivityRate + '%');
|
| 723 |
+
|
| 724 |
+
// Pasar stats normalizados al donut
|
| 725 |
+
updateDonutChart({
|
| 726 |
+
total_unique_patients: totalPatients,
|
| 727 |
+
patients_with_rd: positiveCases,
|
| 728 |
+
patients_without_rd: negativeCases
|
| 729 |
+
});
|
| 730 |
} else {
|
| 731 |
showErrorMessage('Error cargando estadísticas del dashboard');
|
| 732 |
}
|
|
|
|
| 735 |
function updateStatCard(selector, value) {
|
| 736 |
const card = $(selector);
|
| 737 |
const valueElement = card.find('span.h3');
|
|
|
|
| 738 |
|
| 739 |
+
if (typeof value === 'string' && value.includes('%')) {
|
|
|
|
|
|
|
|
|
|
| 740 |
valueElement.text(value);
|
| 741 |
+
} else {
|
| 742 |
+
const targetValue = parseInt(value) || 0;
|
| 743 |
+
animateValue(valueElement[0], 0, targetValue, 800);
|
| 744 |
}
|
| 745 |
}
|
| 746 |
|
|
|
|
| 747 |
function animateValue(element, start, end, duration) {
|
| 748 |
if (!element) return;
|
| 749 |
+
const safeEnd = Math.max(0, parseInt(end) || 0);
|
| 750 |
+
const safeStart = Math.max(0, parseInt(start) || 0);
|
| 751 |
+
const startTime = performance.now();
|
| 752 |
+
const step = (currentTime) => {
|
| 753 |
+
const elapsed = currentTime - startTime;
|
| 754 |
const progress = Math.min(elapsed / duration, 1);
|
| 755 |
+
element.textContent = Math.floor(progress * (safeEnd - safeStart) + safeStart);
|
| 756 |
+
if (progress < 1) window.requestAnimationFrame(step);
|
|
|
|
|
|
|
|
|
|
|
|
|
| 757 |
};
|
| 758 |
window.requestAnimationFrame(step);
|
| 759 |
}
|
|
|
|
| 919 |
tbody.append(`
|
| 920 |
<tr>
|
| 921 |
<td>${date}</td>
|
| 922 |
+
<td>${consultation.patientName || consultation.patient_name || 'Desconocido'}</td>
|
| 923 |
<td><span class="badge ${resultClass}">${resultText}</span></td>
|
| 924 |
<td>${confidence}</td>
|
| 925 |
</tr>
|
|
|
|
| 946 |
<div class="row mb-3">
|
| 947 |
<div class="col-md-6">
|
| 948 |
<h6>Información Básica</h6>
|
| 949 |
+
<p><strong>Paciente:</strong> ${consultation.patientName || consultation.patient_name || 'Desconocido'}</p>
|
| 950 |
<p><strong>Fecha:</strong> ${consultation.consultationDate || 'N/A'}</p>
|
| 951 |
</div>
|
| 952 |
<div class="col-md-6">
|