Recepción: el contador de exámenes no se actualizaba en las cargas silenciosas

La insignia con la cantidad de exámenes solo se refrescaba desde los callbacks
onItemAdd/onItemRemove de TomSelect, y hay cuatro rutas que manipulan la
selección por código sin dispararlos:

- Importar desde RIPS usa addItem(id, true) —silencioso a propósito, para no
  recalcular precios en cada examen—, así que la insignia quedaba en cero
  aunque se hubieran cargado varios.
- El botón "Limpiar selección", toggleSoloMuestras y resetCheckboxes usan
  clear(), que internamente quita los ítems en modo silencioso: la insignia
  conservaba el número anterior.

Al revisarlo apareció un segundo efecto en toggleSoloMuestras: limpiaba los
exámenes sin recalcular, dejando el panel de precios mostrando exámenes que
ya no estaban seleccionados.

Se agrega limpiarExamenes(), que limpia y sincroniza contador y precios, y se
usa en las tres rutas de limpieza; la carga desde RIPS actualiza el contador
una vez al terminar, conservando el modo silencioso por examen.

Validado con node sobre un doble de TomSelect que replica el comportamiento
silencioso: los cuatro escenarios pasan.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-11 07:59:31 -05:00
co-authored by Claude Opus 5
parent 9b5e144386
commit 5d4315fae7
+19 -3
View File
@@ -736,7 +736,7 @@ document.addEventListener('DOMContentLoaded', function() {
</select>
</div>
<div class="mt-2">
<button class="btn btn-outline-secondary btn-sm" onclick="examTS && examTS.clear()">
<button class="btn btn-outline-secondary btn-sm" onclick="limpiarExamenes()">
<i class="fas fa-times me-1"></i>Limpiar selección
</button>
</div>
@@ -1168,6 +1168,19 @@ function _actualizarContadorExamenes() {
badge.classList.toggle('d-none', n === 0);
}
/**
* Limpia la selección de exámenes dejando contador y precios en sincronía.
* examTS.clear() quita los ítems en modo silencioso, así que no dispara
* onItemRemove: sin esto la insignia conserva el número anterior y el panel
* de precios sigue mostrando exámenes que ya no están seleccionados.
*/
function limpiarExamenes() {
if (!examTS) return;
examTS.clear();
_actualizarContadorExamenes();
recalcularPrecios();
}
document.addEventListener('DOMContentLoaded', () => {
examTS = new TomSelect('#sel-examenes', {
plugins: ['remove_button'],
@@ -1711,7 +1724,10 @@ async function consultarExamenesRips(cedula) {
async function cargarExamenesRips() {
if (!_ripsData?.encontrados?.length || !examTS) return;
// Se agregan en modo silencioso para no recalcular precios en cada examen;
// el recálculo y el contador se hacen una sola vez al terminar.
_ripsData.encontrados.forEach(e => examTS.addItem(String(e.exam_tipo_id), true));
_actualizarContadorExamenes();
if (_ripsData.diagnostico_cod) {
document.getElementById('inp-diag').value = _ripsData.diagnostico_cod;
}
@@ -2382,7 +2398,7 @@ function escJs(s) { return String(s||'').replace(/\\/g,'\\\\').replace(/'/g,"\\'
function toggleSoloMuestras() {
const solo = document.getElementById('chk-solo-muestras').checked;
const wrap = document.getElementById('wrap-examenes');
if (examTS) { examTS.clear(); solo ? examTS.disable() : examTS.enable(); }
if (examTS) { limpiarExamenes(); solo ? examTS.disable() : examTS.enable(); }
wrap.classList.toggle('disabled', solo);
document.getElementById('bloque-medico').style.display = solo ? 'none' : '';
if (solo) quitarMedico();
@@ -2390,7 +2406,7 @@ function toggleSoloMuestras() {
function resetCheckboxes() {
document.getElementById('chk-solo-muestras').checked = false;
if (examTS) { examTS.clear(); examTS.enable(); }
if (examTS) { limpiarExamenes(); examTS.enable(); }
document.getElementById('wrap-examenes').classList.remove('disabled');
document.getElementById('bloque-medico').style.display = '';
descartarRips();