/** * SidePanel — right-side drawer for document upload and rule testing. * Slides in over the ReviewScreen without navigation. */ import React, { useState, useRef } from 'react' import { extractDocuments, executeRules, sendReport } from '../api/client' const STATUS_CONFIG = { PASS: { label: 'Pass', cls: 'bg-emerald-500/20 text-emerald-300 border-emerald-500/30' }, VIOLATION: { label: 'Violation', cls: 'bg-red-500/20 text-red-300 border-red-500/30' }, SKIPPED: { label: 'Skipped', cls: 'bg-slate-500/20 text-slate-400 border-slate-500/30' }, } function UploadZone({ label, sublabel, file, onChange, accept = '.pdf' }) { const inputRef = useRef() function handleDrop(e) { e.preventDefault() const dropped = e.dataTransfer.files[0] if (dropped) onChange(dropped) } return (
inputRef.current?.click()} onDragOver={(e) => e.preventDefault()} onDrop={handleDrop} className={`relative border-2 border-dashed rounded-xl p-4 cursor-pointer transition-all duration-200 text-center ${file ? 'border-emerald-500/50 bg-emerald-950/20' : 'border-slate-600 hover:border-slate-500 bg-slate-800/30' }`} > onChange(e.target.files[0])} />

{label}

{sublabel}

{file ? (

✓ {file.name}

) : (

Click or drag PDF here

)}
) } function ResultRow({ result }) { const cfg = STATUS_CONFIG[result.status] || STATUS_CONFIG.SKIPPED const [expanded, setExpanded] = useState(result.status === 'VIOLATION') return (
{expanded && result.deviation_details && (

{result.deviation_details.reason}

{result.action && (

→ Action: {result.action}

)}
)}
) } export default function SidePanel({ open, onClose }) { const [files, setFiles] = useState({ invoice: null, po: null, grn: null }) const [email, setEmail] = useState('') const [loading, setLoading] = useState(false) const [loadingMsg, setLoadingMsg] = useState('') const [results, setResults] = useState(null) const [payload, setPayload] = useState(null) const [error, setError] = useState('') const [sending, setSending] = useState(false) const [sent, setSent] = useState(false) function setFile(key) { return (file) => setFiles((f) => ({ ...f, [key]: file })) } async function handleRunAnalysis() { if (!files.invoice && !files.po && !files.grn) { setError('Upload at least one document.') return } setError('') setResults(null) setLoading(true) try { setLoadingMsg('Extracting document data…') const extractRes = await extractDocuments(files) const extractedPayload = extractRes.data.payload setPayload(extractedPayload) setLoadingMsg('Running rule engine…') const execRes = await executeRules(extractedPayload) setResults(execRes.data.results) } catch (e) { setError(e.response?.data?.detail || e.message || 'Analysis failed.') } finally { setLoading(false) setLoadingMsg('') } } async function handleSendReport() { if (!email) { setError('Enter a recipient email.'); return } if (!results) return setSending(true) setError('') try { const invoiceNum = payload?.Invoice_table?.invoice_number ?? null await sendReport(results, email, invoiceNum) setSent(true) } catch (e) { setError(e.response?.data?.detail || e.message || 'Failed to send report.') } finally { setSending(false) } } const passed = results?.filter((r) => r.status === 'PASS').length ?? 0 const failed = results?.filter((r) => r.status === 'VIOLATION').length ?? 0 const skipped = results?.filter((r) => r.status === 'SKIPPED').length ?? 0 return ( <> {/* Backdrop */} {open && (
)} {/* Drawer */}
{/* Header */}

Test These Rules

Upload documents to validate against your finalized ruleset

{/* Upload zones */}

Documents

{/* Email */}
setEmail(e.target.value)} placeholder="ap-team@company.com" className="w-full bg-slate-800 border border-slate-600 rounded-lg px-3 py-2 text-sm text-slate-100 placeholder-slate-500 focus:outline-none focus:border-cyan-500 transition-colors" />
{/* Run Analysis */} {error && (

{error}

)} {/* Results */} {results && (
{/* Summary row */}
{passed}
Pass
{failed}
Violations
{skipped}
Skipped
{/* Overall status */}
{failed === 0 ? '✓ COMPLIANT' : `✗ NON-COMPLIANT — ${failed} violation${failed > 1 ? 's' : ''}`}
{/* Rule rows */}
{results.map((r) => ( ))}
{/* Send report */}
)}
) }