import { useEffect, useState } from 'react' import { useParams } from 'react-router-dom' import SignaturePad from '../components/SignaturePad' import { SLOTS_DOCUMENTOS, TAMANO_MAX_DOCUMENTO } from '../data/constantes' import { enviarFirmaRemota, ErrorLiga, obtenerClientePublico, subirDocumentoRemoto, type ClientePublico, } from '../services/api' const ACEPTADOS = '.pdf,.jpg,.jpeg,.png' /** * Pantalla PÚBLICA de firma en remoto (/client/firma/:token): sin login. * El cliente final firma y sube sus documentos; el token (scope firma-remota, * 72 h) va en la URL y lo verifica el API en cada llamada. */ export default function FirmaRemotaPage() { const { token = '' } = useParams() const [cliente, setCliente] = useState(null) const [errorCarga, setErrorCarga] = useState('') const [firmaDataUrl, setFirmaDataUrl] = useState('') const [enviandoFirma, setEnviandoFirma] = useState(false) const [firmaOk, setFirmaOk] = useState(false) const [errorFirma, setErrorFirma] = useState('') const [subiendoSlot, setSubiendoSlot] = useState('') const [erroresDoc, setErroresDoc] = useState>({}) useEffect(() => { obtenerClientePublico(token) .then((c) => { setCliente(c) setFirmaOk(c.firma) }) .catch((err) => setErrorCarga(err instanceof ErrorLiga ? err.message : 'No se pudo cargar la información. Intenta más tarde.'), ) }, [token]) const enviarFirma = async () => { if (!firmaDataUrl) { setErrorFirma('Primero dibuja tu firma en el recuadro.') return } setEnviandoFirma(true) setErrorFirma('') try { await enviarFirmaRemota(token, firmaDataUrl) setFirmaOk(true) } catch (err) { setErrorFirma(err instanceof ErrorLiga ? err.message : 'No se pudo guardar la firma. Intenta de nuevo.') } finally { setEnviandoFirma(false) } } const subirDocumento = async (slot: string, archivo: File | undefined) => { if (!archivo) return if (archivo.size > TAMANO_MAX_DOCUMENTO) { setErroresDoc((prev) => ({ ...prev, [slot]: 'El archivo supera 10 MB' })) return } setSubiendoSlot(slot) setErroresDoc((prev) => ({ ...prev, [slot]: '' })) try { await subirDocumentoRemoto(token, slot, archivo) // Refresca el estado de documentos desde el servidor setCliente(await obtenerClientePublico(token)) } catch (err) { setErroresDoc((prev) => ({ ...prev, [slot]: err instanceof ErrorLiga ? err.message : 'No se pudo subir el archivo. Intenta de nuevo.', })) } finally { setSubiendoSlot('') } } if (errorCarga) { return (
FRASA

{errorCarga}

) } if (!cliente) { return (

Cargando…

) } return (
FRASA

Expediente digital

Hola, {cliente.nombre}

Proyecto {cliente.proyecto} {cliente.unidad ? ` · Unidad ${cliente.unidad}` : ''}. Firma y sube los documentos de tu expediente desde aquí.

Tu firma

{firmaOk ? (

Firma registrada correctamente

) : (
{errorFirma &&

{errorFirma}

}
)}

Tus documentos

    {SLOTS_DOCUMENTOS.map(({ slot, etiqueta }) => { const subido = cliente.documentos.find((d) => d.tipo === slot) return (
  • {etiqueta}

    {subido ? (

    ✓ {subido.nombreArchivo}

    ) : (

    PDF/JPG/PNG · máx 10 MB

    )} {erroresDoc[slot] && (

    {erroresDoc[slot]}

    )}
  • ) })}
) }