diff --git a/web-v2/src/pages/DocumentDeliveryPage.tsx b/web-v2/src/pages/DocumentDeliveryPage.tsx index 7eb2683..baeaa3c 100644 --- a/web-v2/src/pages/DocumentDeliveryPage.tsx +++ b/web-v2/src/pages/DocumentDeliveryPage.tsx @@ -1,16 +1,144 @@ import { FormEvent, useEffect, useState } from 'react'; +import { useAuth } from '../auth/AuthContext'; import { Alert, LoadingBlock, errorMessage } from '../components/Feedback'; import { Icon } from '../components/Icon'; -import { getDocumentDeliverySettings, listDocumentDeliveries, retryDocumentDelivery, retryPendingDocumentDeliveries, updateDocumentDeliverySettings } from '../lib/api'; +import { + getDocumentDeliverySettings, + listDocumentDeliveries, + retryDocumentDelivery, + retryPendingDocumentDeliveries, + updateDocumentDeliverySettings, +} from '../lib/api'; import type { DocumentDeliveryItem, DocumentDeliverySettings } from '../lib/api'; -import { useAuth } from '../auth/AuthContext'; -const statusLabel:Record={PENDING:'Pendiente',WAITING_RECIPIENT:'Falta destinatario',WAITING_TRANSPORT:'SMTP sin configurar',WAITING_ARTIFACT:'Documento pendiente',SENT:'Enviado',FAILED:'Error'}; -export function DocumentDeliveryPage(){ const {hasPermission}=useAuth(); const canManage=hasPermission('document_delivery.manage'); const [settings,setSettings]=useState(null); const [items,setItems]=useState([]); const [officeEmail,setOfficeEmail]=useState(''); const [directorEmail,setDirectorEmail]=useState(''); const [loading,setLoading]=useState(true); const [saving,setSaving]=useState(false); const [error,setError]=useState(''); const [success,setSuccess]=useState(''); - const load=async()=>{const [s,o]=await Promise.all([getDocumentDeliverySettings(),listDocumentDeliveries()]);setSettings(s);setOfficeEmail(s.officeEmail??'');setDirectorEmail(s.directorEmail??'');setItems(o.data);}; useEffect(()=>{load().catch(e=>setError(errorMessage(e))).finally(()=>setLoading(false));},[]); - const save=async(e:FormEvent)=>{e.preventDefault();setSaving(true);setError('');setSuccess('');try{const s=await updateDocumentDeliverySettings({officeEmail:officeEmail||null,directorEmail:directorEmail||null});setSettings(s);setSuccess('Destinatarios institucionales actualizados');}catch(err){setError(errorMessage(err));}finally{setSaving(false);}}; - const retryAll=async()=>{setSaving(true);setError('');setSuccess('');try{const r=await retryPendingDocumentDeliveries();await load();setSuccess(`Se procesaron ${r.processed} entrega/s pendientes.`);}catch(err){setError(errorMessage(err));}finally{setSaving(false);}}; - if(loading)return ; return
DOCUMENTOS

Entrega documental

Configurá los destinatarios institucionales y controlá el envío automático de Actas e Informes.

{canManage&&}
{error&&{error}}{success&&{success}} -

Destinatarios institucionales

El email de cada empresa se configura dentro de su ficha de Inventario. Las credenciales SMTP permanecen fuera de la base de datos.

{settings?.smtpConfigured?'Servidor de correo configurado':'Servidor de correo pendiente'}{settings?.mailFrom?` · Remitente ${settings.mailFrom}`:' · Falta configurar SMTP_HOST y MAIL_FROM en el servidor.'}

{canManage&&
}
-
TRAZABILIDAD

Últimas entregas

{items.length}
{items.length===0?
Todavía no existen entregas documentales.
:
{items.map(item=>)}
DocumentoDestinoEstadoIntentos
{item.documentKind==='ACT_PDF'?item.actCode:item.reportCode}{item.documentKind==='ACT_PDF'?'Acta PDF':'Informe Word'}{item.recipientAssetName??(item.recipientKind==='COMPANY'?'Empresa sin identificar':item.recipientKind==='OFFICE'?'Oficina':'Director')}{item.recipientEmail??'Sin email configurado'}{statusLabel[item.status]}{item.lastError&&{item.lastError}}{item.attempts}{canManage&&item.status!=='SENT'&&}
}
-
; } +const statusLabel: Record = { + PENDING: 'Pendiente', + WAITING_RECIPIENT: 'Falta destinatario', + WAITING_TRANSPORT: 'SMTP sin configurar', + WAITING_ARTIFACT: 'Documento pendiente', + SENT: 'Enviado', + FAILED: 'Error', +}; + +type DeliveryWithInspector = DocumentDeliveryItem & { + recipientUserId?: string | null; + recipientUserName?: string | null; +}; + +function recipientLabel(item: DeliveryWithInspector): string { + if (item.recipientAssetName) return item.recipientAssetName; + if (item.recipientUserName) return item.recipientUserName; + const kind = String(item.recipientKind); + if (kind === 'COMPANY') return 'Empresa sin identificar'; + if (kind === 'OFFICE') return 'Oficina'; + if (kind === 'INSPECTOR') return 'Inspector responsable'; + return 'Director'; +} + +export function DocumentDeliveryPage() { + const { hasPermission } = useAuth(); + const canManage = hasPermission('document_delivery.manage'); + const [settings, setSettings] = useState(null); + const [items, setItems] = useState([]); + const [officeEmail, setOfficeEmail] = useState(''); + const [directorEmail, setDirectorEmail] = useState(''); + const [loading, setLoading] = useState(true); + const [saving, setSaving] = useState(false); + const [error, setError] = useState(''); + const [success, setSuccess] = useState(''); + + const load = async () => { + const [currentSettings, outbox] = await Promise.all([ + getDocumentDeliverySettings(), + listDocumentDeliveries(), + ]); + setSettings(currentSettings); + setOfficeEmail(currentSettings.officeEmail ?? ''); + setDirectorEmail(currentSettings.directorEmail ?? ''); + setItems(outbox.data); + }; + + useEffect(() => { + load().catch((requestError) => setError(errorMessage(requestError))).finally(() => setLoading(false)); + }, []); + + const save = async (event: FormEvent) => { + event.preventDefault(); + setSaving(true); + setError(''); + setSuccess(''); + try { + const currentSettings = await updateDocumentDeliverySettings({ + officeEmail: officeEmail || null, + directorEmail: directorEmail || null, + }); + setSettings(currentSettings); + setSuccess('Destinatarios institucionales actualizados'); + } catch (requestError) { + setError(errorMessage(requestError)); + } finally { + setSaving(false); + } + }; + + const retryAll = async () => { + setSaving(true); + setError(''); + setSuccess(''); + try { + const result = await retryPendingDocumentDeliveries(); + await load(); + setSuccess(`Se procesaron ${result.processed} entrega/s pendientes.`); + } catch (requestError) { + setError(errorMessage(requestError)); + } finally { + setSaving(false); + } + }; + + if (loading) return ; + + return
+
+
+ DOCUMENTOS +

Entrega documental

+

Configurá los destinatarios institucionales y controlá el envío automático de Actas e Informes.

+
+ {canManage && } +
+ {error && {error}} + {success && {success}} + +
+
+
+

Destinatarios institucionales

+

El email de cada empresa se configura dentro de su ficha de Inventario. El Inspector responsable usa automáticamente el email declarado en su Usuario. Las credenciales SMTP permanecen fuera de la base de datos.

+
+
+ + +
+

{settings?.smtpConfigured ? 'Servidor de correo configurado' : 'Servidor de correo pendiente'}{settings?.mailFrom ? ` · Remitente ${settings.mailFrom}` : ' · Falta configurar SMTP_HOST y MAIL_FROM en el servidor.'}

+ {canManage &&
} +
+
+ +
+
TRAZABILIDAD

Últimas entregas

{items.length}
+ {items.length === 0 + ?
Todavía no existen entregas documentales.
+ :
{items.map((baseItem) => { + const item = baseItem as DeliveryWithInspector; + return + + + + + + ; + })}
DocumentoDestinoEstadoIntentos
{item.documentKind === 'ACT_PDF' ? item.actCode : item.reportCode}{item.documentKind === 'ACT_PDF' ? 'Acta PDF' : 'Informe Word'}{recipientLabel(item)}{item.recipientEmail ?? 'Sin email configurado'}{statusLabel[item.status]}{item.lastError && {item.lastError}}{item.attempts}{canManage && item.status !== 'SENT' && }
} +
+
; +}