Files
Lizandro GuarnizoandClaude Sonnet 4.6 cf8d011f09 feat(lab_examenes): múltiples consentimientos por examen
Mismo patrón que turnero/configuracion: form_ids[] en lugar de
formulario_id único, checkboxes en la vista, INSERT múltiple en save.php

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-08 08:19:06 -05:00

508 lines
26 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require_once APP_ROOT . '/config/config.php';
if (!isUserLoggedIn()) { header('Location: ' . BASE_URL . 'login.php'); exit; }
$id = (int)($_GET['id'] ?? 0);
$pdo = Database::getInstance()->getConnection();
$exam = null;
$items = [];
if ($id) {
$s = $pdo->prepare('SELECT * FROM exam_tipos WHERE id=?');
$s->execute([$id]);
$exam = $s->fetch(PDO::FETCH_ASSOC);
if (!$exam) { header('Location: ' . BASE_URL . 'erp.php?m=lab_examenes&v=index'); exit; }
$s = $pdo->prepare('SELECT * FROM lab_items_resultado WHERE cod_protocolo=? ORDER BY orden,id');
$s->execute([$exam['cod_protocolo'] ?? $exam['codigo']]);
$items = $s->fetchAll(PDO::FETCH_ASSOC);
}
$protocolos = $pdo->query('SELECT codigo, nombre FROM lab_protocolos ORDER BY nombre')->fetchAll(PDO::FETCH_ASSOC);
$muestras = $pdo->query('SELECT codigo, nombre FROM lab_tipos_muestra ORDER BY nombre')->fetchAll(PDO::FETCH_ASSOC);
$formularios = $pdo->query('SELECT id, nombre FROM lab_formularios ORDER BY nombre')->fetchAll(PDO::FETCH_ASSOC);
$formsActuales = [];
if ($id) {
$s = $pdo->prepare('SELECT formulario_id FROM exam_tipo_consentimientos WHERE exam_tipo_id=?');
$s->execute([$id]);
$formsActuales = $s->fetchAll(PDO::FETCH_COLUMN);
}
$titulo = $exam ? 'Editar: ' . htmlspecialchars($exam['nombre']) : 'Nuevo Examen';
Layout::open($titulo, 'fas fa-flask');
$API = BASE_URL . 'modules/lab_examenes/api/';
?>
<style>
body { background:#f1f5f9 }
.page-header { background:#fff; border-bottom:1px solid #e2e8f0; padding:12px 24px;
display:flex; align-items:center; gap:10px; flex-wrap:wrap }
.breadcrumb-lab { font-size:.82rem; color:#64748b }
.breadcrumb-lab a { color:#2563eb; text-decoration:none }
.content-wrap { max-width:1100px; margin:20px auto; padding:0 16px 60px }
.panel { background:#fff; border:1px solid #e2e8f0; border-radius:12px; margin-bottom:20px }
.panel-hdr { padding:14px 20px; border-bottom:1px solid #e2e8f0; display:flex; align-items:center; gap:8px }
.panel-hdr h2 { font-size:1rem; font-weight:700; color:#1e293b; margin:0; flex:1 }
.panel-body { padding:20px }
.form-label { font-size:.8rem; font-weight:600; color:#374151 }
/* items table */
.items-table { width:100%; border-collapse:collapse; font-size:.83rem }
.items-table th { background:#f8fafc; padding:7px 10px; font-size:.7rem; text-transform:uppercase;
letter-spacing:.06em; color:#64748b; border-bottom:1px solid #e2e8f0; white-space:nowrap }
.items-table td { padding:6px 8px; border-bottom:1px solid #f1f5f9; vertical-align:middle }
.items-table tr:last-child td { border-bottom:none }
.items-table input, .items-table select { font-size:.8rem; padding:3px 6px; border:1px solid #d1d5db;
border-radius:5px; width:100% }
.items-table input:focus, .items-table select:focus { outline:none; border-color:#6366f1 }
/* tarifas table */
.tar-table { width:100%; border-collapse:collapse; font-size:.83rem }
.tar-table th { background:#f8fafc; padding:7px 14px; font-size:.7rem; text-transform:uppercase;
letter-spacing:.06em; color:#64748b; border-bottom:1px solid #e2e8f0 }
.tar-table td { padding:7px 14px; border-bottom:1px solid #f1f5f9; vertical-align:middle }
.tar-table tr:last-child td { border-bottom:none }
.tar-table tr:hover td { background:#f8fafc }
.tar-val { font-family:monospace; font-size:.88rem }
.edit-inline { display:none; gap:4px; align-items:center }
.tr-editing .edit-inline { display:flex }
.tr-editing .val-display { display:none }
.inp-val { width:90px; padding:3px 6px; font-size:.83rem; border:1px solid #d1d5db; border-radius:5px }
.inp-val:focus { border-color:#6366f1; outline:none }
</style>
<div class="page-header">
<div class="breadcrumb-lab">
<a href="<?= BASE_URL ?>erp.php?m=lab_examenes&v=index"><i class="fas fa-flask me-1"></i>Exámenes</a>
<i class="fas fa-chevron-right mx-1" style="font-size:.7rem"></i>
<?= $exam ? htmlspecialchars($exam['nombre']) : 'Nuevo examen' ?>
</div>
<?php if ($exam): ?>
<button class="btn btn-outline-danger btn-sm ms-auto" onclick="eliminar(<?=$exam['id']?>, '<?= addslashes(htmlspecialchars($exam['nombre'])) ?>')">
<i class="fas fa-trash me-1"></i>Eliminar
</button>
<?php endif; ?>
</div>
<div class="content-wrap">
<div id="alerta-global" class="alert d-none mb-3 py-2"></div>
<!-- ── Datos generales ── -->
<div class="panel">
<div class="panel-hdr">
<i class="fas fa-info-circle text-primary"></i>
<h2>Datos generales</h2>
<button class="btn btn-primary btn-sm" onclick="guardarExamen()">
<i class="fas fa-save me-1"></i>Guardar
</button>
</div>
<div class="panel-body">
<input type="hidden" id="exam-id" value="<?= $exam['id'] ?? '' ?>">
<div class="row g-3">
<div class="col-sm-3">
<label class="form-label">Código <span class="text-danger">*</span></label>
<input type="text" id="f-codigo" class="form-control form-control-sm"
value="<?= htmlspecialchars($exam['codigo'] ?? '') ?>" maxlength="20" style="text-transform:uppercase">
</div>
<div class="col-sm-3">
<label class="form-label">Código CUPS</label>
<input type="text" id="f-cups" class="form-control form-control-sm"
value="<?= htmlspecialchars($exam['cups'] ?? '') ?>" maxlength="20">
</div>
<div class="col-sm-3">
<label class="form-label">Abreviatura</label>
<input type="text" id="f-abreviatura" class="form-control form-control-sm"
value="<?= htmlspecialchars($exam['abreviatura'] ?? '') ?>" maxlength="30">
</div>
<div class="col-sm-3">
<label class="form-label">Nivel</label>
<input type="number" id="f-nivel" class="form-control form-control-sm"
value="<?= $exam['nivel'] ?? '' ?>" min="0" max="9">
</div>
<div class="col-12">
<label class="form-label">Nombre <span class="text-danger">*</span></label>
<input type="text" id="f-nombre" class="form-control form-control-sm"
value="<?= htmlspecialchars($exam['nombre'] ?? '') ?>" maxlength="150">
</div>
<div class="col-sm-4">
<label class="form-label">Protocolo</label>
<select id="f-protocolo" class="form-select form-select-sm">
<option value="">— ninguno —</option>
<?php foreach ($protocolos as $p): ?>
<option value="<?= htmlspecialchars($p['codigo']) ?>"
<?= ($exam['cod_protocolo'] ?? '') === $p['codigo'] ? 'selected' : '' ?>>
<?= htmlspecialchars($p['codigo'] . ' ' . $p['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-sm-4">
<label class="form-label">Tipo de muestra</label>
<select id="f-muestra" class="form-select form-select-sm">
<option value="">— ninguna —</option>
<?php foreach ($muestras as $m): ?>
<option value="<?= htmlspecialchars($m['codigo']) ?>"
<?= ($exam['tipo_muestra'] ?? '') === $m['codigo'] ? 'selected' : '' ?>>
<?= htmlspecialchars($m['nombre']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-sm-4">
<label class="form-label">Formularios consentimiento</label>
<div id="f-formularios-wrap" class="border rounded p-2" style="max-height:120px;overflow-y:auto;background:#fffbeb">
<?php foreach ($formularios as $f): ?>
<div class="form-check mb-1">
<input class="form-check-input f-formulario-chk" type="checkbox"
value="<?= $f['id'] ?>" id="f-fc-<?= $f['id'] ?>"
<?= in_array((int)$f['id'], array_map('intval', $formsActuales)) ? 'checked' : '' ?>>
<label class="form-check-label small" for="f-fc-<?= $f['id'] ?>">
<?= htmlspecialchars($f['nombre']) ?>
</label>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="col-sm-6">
<label class="form-label">Se recibe de (lab externo)</label>
<input type="text" id="f-serecibe" class="form-control form-control-sm"
value="<?= htmlspecialchars($exam['serecibe'] ?? '') ?>" maxlength="50">
</div>
<div class="col-sm-6">
<label class="form-label">Instrucciones para el paciente</label>
<input type="text" id="f-instrucciones" class="form-control form-control-sm"
value="<?= htmlspecialchars($exam['instrucciones'] ?? '') ?>">
</div>
<div class="col-12">
<div class="d-flex gap-4 flex-wrap">
<div class="form-check">
<input class="form-check-input" type="checkbox" id="f-seremite"
<?= ($exam['seremite'] ?? 0) ? 'checked' : '' ?>>
<label class="form-check-label small" for="f-seremite">Se remite a laboratorio externo</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="f-ayuno"
<?= ($exam['requiere_ayuno'] ?? 0) ? 'checked' : '' ?>>
<label class="form-check-label small" for="f-ayuno">Requiere ayuno</label>
</div>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="f-activo"
<?= ($exam['activo'] ?? 1) ? 'checked' : '' ?>>
<label class="form-check-label small" for="f-activo">Activo</label>
</div>
</div>
</div>
<div class="col-sm-3" id="blq-ayuno" style="display:<?= ($exam['requiere_ayuno'] ?? 0) ? 'block' : 'none' ?>">
<label class="form-label">Horas de ayuno</label>
<input type="number" id="f-horas-ayuno" class="form-control form-control-sm"
value="<?= $exam['horas_ayuno'] ?? '' ?>" min="1" max="72">
</div>
</div>
</div>
</div>
<?php if ($exam): ?>
<!-- ── Items de resultado ── -->
<div class="panel">
<div class="panel-hdr">
<i class="fas fa-list text-success"></i>
<h2>Items / Valores de referencia</h2>
<button class="btn btn-outline-success btn-sm" onclick="addItem()">
<i class="fas fa-plus me-1"></i>Agregar item
</button>
</div>
<div style="overflow-x:auto">
<table class="items-table">
<thead>
<tr>
<th style="width:30px">#</th>
<th>Nombre item</th>
<th style="width:70px">Sexo</th>
<th style="width:70px">Tipo</th>
<th style="width:90px">Medida</th>
<th style="width:80px">V.Min</th>
<th style="width:80px">V.Max</th>
<th style="width:50px">Ord.</th>
<th>Fórmula</th>
<th style="width:60px"></th>
</tr>
</thead>
<tbody id="items-body">
<?php foreach ($items as $it): ?>
<tr data-id="<?=$it['id']?>" data-cod="<?=htmlspecialchars($exam['cod_protocolo']??$exam['codigo'])?>">
<?= _itemRow($it) ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- ── Tarifas ── -->
<div class="panel">
<div class="panel-hdr">
<i class="fas fa-tags text-warning"></i>
<h2>Precios por tarifa</h2>
<small class="text-muted">Clic en el valor para editar</small>
</div>
<div style="overflow-x:auto">
<table class="tar-table" id="tar-table">
<thead>
<tr>
<th style="width:30px">#</th>
<th>Tarifa</th>
<th style="width:120px">Valor</th>
<th style="width:100px">R. Urgencia</th>
<th style="width:100px">R. Festivo</th>
<th style="width:100px">R. Especial</th>
<th style="width:80px"></th>
</tr>
</thead>
<tbody id="tar-body">
<tr><td colspan="7" class="text-center text-muted py-3">Cargando tarifas…</td></tr>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
</div>
<?php
function _itemRow(array $it): string {
$sexos = [''=>'Ambos','M'=>'M','F'=>'F'];
$tipos = ['T'=>'Texto','N'=>'Numérico'];
$sOpts = ''; foreach($sexos as $v=>$l) $sOpts .= "<option value='$v'".($it['tipo_sexo']===$v?' selected':'').">$l</option>";
$tOpts = ''; foreach($tipos as $v=>$l) $tOpts .= "<option value='$v'".($it['tipo']===$v?' selected':'').">$l</option>";
return "
<td><input type='number' name='orden' value='{$it['orden']}' style='width:45px'></td>
<td><input type='text' name='nombre' value='".htmlspecialchars($it['nombre'])."' style='min-width:160px'></td>
<td><select name='tipo_sexo'>$sOpts</select></td>
<td><select name='tipo'>$tOpts</select></td>
<td><input type='text' name='medida' value='".htmlspecialchars($it['medida']??'')."'></td>
<td><input type='number' name='vmin_ref' value='".($it['vmin_ref']??'')."' step='any'></td>
<td><input type='number' name='vmax_ref' value='".($it['vmax_ref']??'')."' step='any'></td>
<td><input type='number' name='orden2' value='{$it['orden']}' style='width:45px' disabled></td>
<td><input type='text' name='formula' value='".htmlspecialchars($it['formula']??'')."'></td>
<td><button type='button' class='btn btn-sm btn-outline-success py-0 px-1 me-1' onclick='saveItem(this)' title='Guardar'><i class='fas fa-check'></i></button>
<button type='button' class='btn btn-sm btn-outline-danger py-0 px-1' onclick='delItem(this)' title='Eliminar'><i class='fas fa-trash'></i></button></td>
";
}
?>
<script>
const API = '<?= $API ?>';
const EXAM_ID = <?= $id ?: 'null' ?>;
const COD_PROT = '<?= addslashes($exam['cod_protocolo'] ?? ($exam['codigo'] ?? '')) ?>';
document.addEventListener('DOMContentLoaded', () => {
document.getElementById('f-ayuno')?.addEventListener('change', e => {
document.getElementById('blq-ayuno').style.display = e.target.checked ? 'block' : 'none';
});
if (EXAM_ID) cargarTarifas();
});
// ── Guardar examen ─────────────────────────────────
async function guardarExamen() {
const payload = {
id: document.getElementById('exam-id').value || null,
codigo: document.getElementById('f-codigo').value.trim().toUpperCase(),
nombre: document.getElementById('f-nombre').value.trim(),
cups: document.getElementById('f-cups').value.trim(),
abreviatura: document.getElementById('f-abreviatura').value.trim(),
nivel: document.getElementById('f-nivel').value,
cod_protocolo: document.getElementById('f-protocolo').value,
tipo_muestra: document.getElementById('f-muestra').value,
seremite: document.getElementById('f-seremite').checked ? 1 : 0,
requiere_ayuno: document.getElementById('f-ayuno').checked ? 1 : 0,
horas_ayuno: document.getElementById('f-horas-ayuno')?.value || null,
instrucciones: document.getElementById('f-instrucciones').value.trim(),
serecibe: document.getElementById('f-serecibe').value.trim(),
activo: document.getElementById('f-activo').checked ? 1 : 0,
form_ids: [...document.querySelectorAll('.f-formulario-chk:checked')].map(c => parseInt(c.value)),
};
const r = await fetch(API+'save.php', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)}).then(r=>r.json());
if (r.ok) {
mostrarAlerta('success', r.message || 'Guardado');
if (!payload.id && r.id) setTimeout(() => location.href = location.href.split('?')[0] + '?m=lab_examenes&v=examen&id='+r.id, 800);
} else {
mostrarAlerta('danger', r.error || 'Error');
}
}
async function eliminar(id, nombre) {
if (!confirm(`¿Eliminar "${nombre}"? No se puede deshacer.`)) return;
const r = await fetch(API+'save.php', {method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id,_delete:true})}).then(r=>r.json());
if (r.ok) location.href = '<?= BASE_URL ?>erp.php?m=lab_examenes&v=index';
else mostrarAlerta('danger', r.error);
}
// ── Items ─────────────────────────────────────────
function addItem() {
const tr = document.createElement('tr');
tr.dataset.id = '0';
tr.dataset.cod = COD_PROT;
tr.innerHTML = `
<td><input type='number' name='orden' value='0' style='width:45px'></td>
<td><input type='text' name='nombre' placeholder='Nombre del item' style='min-width:160px'></td>
<td><select name='tipo_sexo'><option value=''>Ambos</option><option value='M'>M</option><option value='F'>F</option></select></td>
<td><select name='tipo'><option value='T'>Texto</option><option value='N'>Numérico</option></select></td>
<td><input type='text' name='medida'></td>
<td><input type='number' name='vmin_ref' step='any'></td>
<td><input type='number' name='vmax_ref' step='any'></td>
<td><input type='number' name='orden2' style='width:45px' disabled></td>
<td><input type='text' name='formula'></td>
<td><button type='button' class='btn btn-sm btn-outline-success py-0 px-1 me-1' onclick='saveItem(this)'><i class='fas fa-check'></i></button>
<button type='button' class='btn btn-sm btn-outline-danger py-0 px-1' onclick='this.closest("tr").remove()'><i class='fas fa-times'></i></button></td>`;
document.getElementById('items-body').appendChild(tr);
tr.querySelector('[name=nombre]').focus();
}
async function saveItem(btn) {
const tr = btn.closest('tr');
const g = n => tr.querySelector(`[name=${n}]`)?.value ?? '';
const payload = {
id: +tr.dataset.id || null,
cod_protocolo: tr.dataset.cod || COD_PROT,
nombre: g('nombre').trim(),
tipo_sexo: g('tipo_sexo') || null,
tipo: g('tipo') || 'T',
medida: g('medida'),
vmin_ref: g('vmin_ref'),
vmax_ref: g('vmax_ref'),
orden: +g('orden') || 0,
formula: g('formula'),
};
if (!payload.nombre) { alert('Nombre requerido'); return; }
const r = await fetch(API+'save_item.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)}).then(r=>r.json());
if (r.ok) { tr.dataset.id = r.id || tr.dataset.id; mostrarAlerta('success','Item guardado'); }
else mostrarAlerta('danger', r.error);
}
async function delItem(btn) {
const tr = btn.closest('tr');
const id = +tr.dataset.id;
if (id && !confirm('¿Eliminar este item?')) return;
if (id) {
const r = await fetch(API+'save_item.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({id,_delete:true})}).then(r=>r.json());
if (!r.ok) { mostrarAlerta('danger', r.error); return; }
}
tr.remove();
}
// ── Tarifas ──────────────────────────────────────
let _tarifas = [];
async function cargarTarifas() {
const r = await fetch(API+'get_tarifas.php?exam_id='+EXAM_ID).then(r=>r.json());
if (!r.ok) return;
_tarifas = r.data;
renderTarifas();
}
function renderTarifas() {
const body = document.getElementById('tar-body');
if (!_tarifas.length) { body.innerHTML='<tr><td colspan="7" class="text-center text-muted py-3">Sin tarifas.</td></tr>'; return; }
body.innerHTML = _tarifas.map((t,i) => {
const v = t.valor !== null ? parseFloat(t.valor).toLocaleString('es-CO') : '—';
return `<tr data-tidx="${i}">
<td class="text-muted" style="font-size:.75rem">${t.tarifa_id}</td>
<td>${esc(t.tarifa_nombre)}</td>
<td class="tar-val val-display" onclick="editTarifa(this)">${v}</td>
<td class="text-muted tar-val" style="font-size:.8rem">${t.recargo_urg>0?parseFloat(t.recargo_urg).toLocaleString('es-CO'):'—'}</td>
<td class="text-muted tar-val" style="font-size:.8rem">${t.recargo_fes>0?parseFloat(t.recargo_fes).toLocaleString('es-CO'):'—'}</td>
<td class="text-muted tar-val" style="font-size:.8rem">${t.recargo_esp>0?parseFloat(t.recargo_esp).toLocaleString('es-CO'):'—'}</td>
<td>
<button class="btn btn-outline-primary btn-sm py-0 px-2" onclick="abrirEditorTarifa(${i})" title="Editar precios">
<i class="fas fa-pencil-alt"></i>
</button>
</td>
</tr>`;
}).join('');
}
function abrirEditorTarifa(idx) {
const t = _tarifas[idx];
const modal = new bootstrap.Modal(document.getElementById('modalTarifa'));
document.getElementById('mt-nombre').textContent = t.tarifa_nombre;
document.getElementById('mt-idx').value = idx;
document.getElementById('mt-valor').value = t.valor ?? '';
document.getElementById('mt-urg').value = t.recargo_urg ?? 0;
document.getElementById('mt-fes').value = t.recargo_fes ?? 0;
document.getElementById('mt-esp').value = t.recargo_esp ?? 0;
modal.show();
document.getElementById('mt-valor').focus();
}
async function guardarTarifa() {
const idx = +document.getElementById('mt-idx').value;
const t = _tarifas[idx];
const payload = {
exam_tipo_id: EXAM_ID,
tarifa_id: t.tarifa_id,
valor: parseFloat(document.getElementById('mt-valor').value) || 0,
recargo_urg: parseFloat(document.getElementById('mt-urg').value) || 0,
recargo_fes: parseFloat(document.getElementById('mt-fes').value) || 0,
recargo_esp: parseFloat(document.getElementById('mt-esp').value) || 0,
};
const btn = document.getElementById('btn-guardar-tarifa');
btn.disabled = true;
const r = await fetch(API+'save_tarifa.php',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(payload)}).then(r=>r.json());
btn.disabled = false;
if (r.ok) {
bootstrap.Modal.getInstance(document.getElementById('modalTarifa')).hide();
cargarTarifas();
mostrarAlerta('success','Precio guardado');
} else {
mostrarAlerta('danger', r.error);
}
}
function mostrarAlerta(tipo, msg) {
const el = document.getElementById('alerta-global');
el.className = `alert alert-${tipo} py-2`;
el.textContent = msg;
el.classList.remove('d-none');
setTimeout(()=>el.classList.add('d-none'), 3500);
el.scrollIntoView({behavior:'smooth',block:'nearest'});
}
function esc(s){if(!s)return'';return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;')}
</script>
<!-- Modal editar tarifa -->
<div class="modal fade" id="modalTarifa" tabindex="-1">
<div class="modal-dialog modal-sm">
<div class="modal-content">
<div class="modal-header py-2">
<h6 class="modal-title"><i class="fas fa-tag me-1"></i><span id="mt-nombre"></span></h6>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<div class="modal-body">
<input type="hidden" id="mt-idx">
<div class="row g-2">
<div class="col-6">
<label class="form-label" style="font-size:.78rem;font-weight:600">Valor base</label>
<input type="number" id="mt-valor" class="form-control form-control-sm" step="1" min="0">
</div>
<div class="col-6">
<label class="form-label" style="font-size:.78rem;font-weight:600">R. Urgencia</label>
<input type="number" id="mt-urg" class="form-control form-control-sm" step="1" min="0">
</div>
<div class="col-6">
<label class="form-label" style="font-size:.78rem;font-weight:600">R. Festivo</label>
<input type="number" id="mt-fes" class="form-control form-control-sm" step="1" min="0">
</div>
<div class="col-6">
<label class="form-label" style="font-size:.78rem;font-weight:600">R. Especial</label>
<input type="number" id="mt-esp" class="form-control form-control-sm" step="1" min="0">
</div>
</div>
</div>
<div class="modal-footer py-2">
<button class="btn btn-secondary btn-sm" data-bs-dismiss="modal">Cancelar</button>
<button class="btn btn-primary btn-sm" id="btn-guardar-tarifa" onclick="guardarTarifa()">
<i class="fas fa-save me-1"></i>Guardar
</button>
</div>
</div>
</div>
</div>
<?php Layout::close(); ?>