import { useEffect, useMemo, useState } from 'react'; import { useAuth } from '../../auth/AuthContext'; import { Alert, LoadingBlock, errorMessage } from '../../components/Feedback'; import { Icon } from '../../components/Icon'; import { getInspectionClosure, getInspectionSignatureBlob } from '../../lib/api'; import type { InspectionAct, InspectionActSignature, InspectionClosure } from '../../lib/api'; import { formatDate } from '../../lib/format'; function signatureStatusLabel(value: InspectionActSignature['status']): string { if (value === 'SIGNED') return 'Firmada'; if (value === 'REFUSED') return 'Se negó a firmar'; return 'Ausente'; } function signerTypeLabel(value: InspectionActSignature['signerType']): string { return value === 'INSPECTOR' ? 'Inspector/a' : 'Responsable de la empresa'; } export function InspectionClosurePanel({ act }: { act: InspectionAct }) { const { hasPermission } = useAuth(); const canRead = hasPermission('inspection_closure.read'); const [closure, setClosure] = useState(null); const [loading, setLoading] = useState(canRead); const [error, setError] = useState(''); useEffect(() => { if (!canRead) return; setLoading(true); getInspectionClosure(act.id) .then(setClosure) .catch((requestError) => setError(errorMessage(requestError))) .finally(() => setLoading(false)); }, [act.id, canRead]); const inspectorSignatures = useMemo( () => closure?.signatures.filter((item) => item.signerType === 'INSPECTOR') ?? [], [closure], ); const companyOutcome = useMemo( () => closure?.signatures.find((item) => item.signerType === 'COMPANY_RESPONSIBLE') ?? null, [closure], ); const viewSignature = async (signature: InspectionActSignature) => { const tab = window.open('about:blank', '_blank'); if (tab) tab.opener = null; try { const blob = await getInspectionSignatureBlob(signature.id); const url = URL.createObjectURL(blob); if (tab) tab.location.href = url; else window.open(url, '_blank', 'noopener,noreferrer'); window.setTimeout(() => URL.revokeObjectURL(url), 60_000); } catch (requestError) { tab?.close(); setError(errorMessage(requestError)); } }; if (!canRead) return null; if (loading || !closure) return
; const constanciasCompletas = inspectorSignatures.length > 0 && Boolean(companyOutcome); return
CIERRE DEL ACTA · SÓLO LECTURA

Responsable, firmas y sellado

La preparación y firma del acta se realizan desde la APK. La inspección puede continuar con otras actas.

{act.status === 'CLOSED' ? 'Cierre sellado' : act.status === 'READY' ? 'Esperando firmas' : 'Pendiente en APK'}
{error && {error}}

Operación exclusiva en APK. El dashboard muestra las constancias sincronizadas, pero no permite identificar al responsable, firmar, reabrir ni cerrar el acta.

1Responsable{closure.responsible ? 'Registrado' : 'Pendiente'}
2Congelado{closure.closure?.isCurrent ? 'SHA-256 listo' : 'Pendiente'}
3Constancias{inspectorSignatures.length} inspector · {companyOutcome ? 'empresa OK' : 'empresa pendiente'}
4Cierre{act.status === 'CLOSED' ? 'Sellado' : 'Pendiente'}
{closure.responsible &&
Situación{closure.responsible.attendanceStatus === 'PRESENT' ? 'Presente' : 'Ausente'}
Responsable{closure.responsible.fullName ?? 'No estuvo presente'}
Documento / cargo{closure.responsible.documentNumber ? `${closure.responsible.documentType} ${closure.responsible.documentNumber}` : 'No informado'}{closure.responsible.position ? ` · ${closure.responsible.position}` : ''}
Contacto{closure.responsible.email ?? closure.responsible.phone ?? 'No informado'}
} {closure.closure?.isCurrent &&
CONTENIDO CONGELADO{closure.closure.schemaVersion}Preparado {formatDate(closure.closure.preparedAt)}
{closure.closure.preparedSha256}
} {closure.signatures.length > 0 &&
{closure.signatures.map((signature) =>
{signatureStatusLabel(signature.status)}{signature.signerName}{signerTypeLabel(signature.signerType)} · {formatDate(signature.createdAt)}
{signature.signaturePayloadSha256}{signature.status === 'SIGNED' ? <>{signature.signerType === 'COMPANY_RESPONSIBLE' &&

{signature.companyManifestation === 'DISSENT' ? 'Firma en disidencia' : 'Firma en conformidad'}{signature.companyStatement ? ` · ${signature.companyStatement}` : ''}

} :

{signature.reason}

}
)}
} {act.status === 'CLOSED' && closure.closure?.finalSha256 &&
ACTA CERRADA{formatDate(closure.closure.serverClosedAt)}

El acta quedó sellada. La inspección y las demás actas tienen un ciclo independiente.

{closure.closure.finalSha256}
}
; }