From 8e62c29ca98ebd5e95aa118f3930793d4320ea09 Mon Sep 17 00:00:00 2001 From: Lizandro Guarnizo <77708265+lizandrogd@users.noreply.github.com> Date: Tue, 17 Mar 2026 15:55:56 -0500 Subject: [PATCH] firma_profesional: canvas en ver_formulario_enviado + endpoint firmar_profesional --- api/lab/firmar_profesional.php | 84 +++++++++++++++++++++++ ver_formulario_enviado.php | 117 ++++++++++++++++++++++++++++++++- 2 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 api/lab/firmar_profesional.php diff --git a/api/lab/firmar_profesional.php b/api/lab/firmar_profesional.php new file mode 100644 index 0000000..3deacd8 --- /dev/null +++ b/api/lab/firmar_profesional.php @@ -0,0 +1,84 @@ + true] + $data); + exit; +} +function err(string $msg, int $code = 400): void { + http_response_code($code); + echo json_encode(['ok' => false, 'error' => $msg]); + exit; +} + +// ── Auth ───────────────────────────────────────────────────────────── +if (!isUserLoggedIn()) { + err('No autenticado', 401); +} + +// ── Input ──────────────────────────────────────────────────────────── +$body = json_decode(file_get_contents('php://input'), true); +if (!$body) $body = $_POST; + +$envioId = (int)($body['envio_id'] ?? 0); +$campoId = trim($body['campo_id'] ?? ''); +$svg = $body['svg'] ?? ''; + +if (!$envioId) err('envio_id requerido'); +if ($campoId === '') err('campo_id requerido'); +if ($svg === '') err('svg requerido'); + +// Validar que el SVG sea data URI de imagen (evita inyección de contenido) +if (!preg_match('/^data:image\/(svg\+xml|png|jpeg|webp);base64,/i', $svg)) { + err('Formato de firma no válido'); +} + +// ── Cargar envío ───────────────────────────────────────────────────── +$db = Database::getInstance(); +$envio = $db->fetch('SELECT id, datos_cliente, estado, formulario_id FROM lab_form_envios WHERE id = ?', [$envioId]); + +if (!$envio) err('Envío no encontrado', 404); + +// Enfermero: solo puede firmar sus propios envíos +if (isEnfermero()) { + $uid = (int)($_SESSION['admin_user']['id'] ?? 0); + $propio = $db->fetch('SELECT id FROM lab_form_envios WHERE id = ? AND enviado_por = ?', [$envioId, $uid]); + if (!$propio) err('Sin acceso', 403); +} + +// ── Validar que campo_id corresponde a una firma_profesional ───────── +$form = $db->fetch('SELECT esquema FROM lab_formularios WHERE id = ?', [$envio['formulario_id']]); +if (!$form) err('Formulario no encontrado', 404); + +$esquema = json_decode($form['esquema'], true) ?? []; +$campoDef = null; +foreach ($esquema as $c) { + if (($c['id'] ?? '') === $campoId) { $campoDef = $c; break; } +} + +if (!$campoDef || ($campoDef['tipo'] ?? '') !== 'firma_profesional') { + err('El campo no es una firma_profesional'); +} + +// ── Actualizar datos_cliente ───────────────────────────────────────── +$datos = json_decode($envio['datos_cliente'] ?? '{}', true) ?? []; +$datos[$campoId . '_svg'] = $svg; + +$nuevosDatos = json_encode($datos, JSON_UNESCAPED_UNICODE); +$nuevoEstado = $envio['estado'] === 'firmado' ? 'firmado' : 'firmado'; + +$db->query( + 'UPDATE lab_form_envios SET datos_cliente = ?, estado = ?, completado_en = COALESCE(completado_en, NOW()) WHERE id = ?', + [$nuevosDatos, $nuevoEstado, $envioId] +); + +ok(['mensaje' => 'Firma del profesional guardada correctamente']); diff --git a/ver_formulario_enviado.php b/ver_formulario_enviado.php index 72d1e06..4c8171c 100644 --- a/ver_formulario_enviado.php +++ b/ver_formulario_enviado.php @@ -166,6 +166,11 @@ function esc2(mixed $v): string { .hash-seal-header { background: #000 !important; -webkit-print-color-adjust:exact; print-color-adjust:exact; } } + /* ── Canvas firma profesional ───────────────────── */ + .firma-pro-widget { max-width: 520px; margin-top: 8px; } + .fpw-canvas { border: 2px solid #198754; border-radius: 8px; background: #f8fff9; + cursor: crosshair; display: block; max-width: 100%; touch-action: none; } + /* ═══════ ESTILOS DE IMPRESIÓN ═══════════════════ */ @media print { body { background: #fff !important; font-size: 12px; } @@ -283,11 +288,12 @@ function esc2(mixed $v): string { if (!$cid) continue; $fSvg = $datosCliente[$cid . '_svg'] ?? null; $fFoto = $datosCliente[$cid . '_foto'] ?? null; - if (!$fSvg && !$fFoto) continue; $isPro = ($tipo === 'firma_profesional'); $fIcon = $isPro ? 'fa-user-md' : 'fa-signature'; $fColor = $isPro ? '#198754' : '#1565c0'; $fLabel = htmlspecialchars($campo['label'] ?? ($isPro ? 'Firma profesional' : 'Firma paciente')); + // Firma paciente sin contenido: omitir + if (!$isPro && !$fSvg && !$fFoto) continue; ?>
@@ -296,11 +302,22 @@ function esc2(mixed $v): string {
<?= $fLabel ?>
- - +
Foto - <?= $fLabel ?>
+ + +
+

Dibuje su firma en el recuadro:

+ +
+ + +
+
+
+