/* ============================================================
Contracts hub — the customer-contract domain model (registry).
Reuses the SAME CX_DASH framework as Finance: the Artifacts page
is a grid of data-product cards; clicking a card opens the full
artifact in the drawer (Artifact / Data / Control / Context).
Content pack: window.CON_DASH (tabs/contracts_dashboard_content.js).
============================================================ */
function ContractsDashboard() {
const hostRef = React.useRef(null);
React.useEffect(() => {
const con = window.CON_DASH;
const host = hostRef.current;
if (!window.ensureFinCxGlobal || !window.ensureFinCxGlobal() || !con || !host) return;
if (window.registerCxPack) window.registerCxPack(con);
host.innerHTML =
'
' +
'
' + con.cardsHtml + '
' +
'
';
return () => {
try { if (window.closeFull) window.closeFull(); } catch (e) {}
try { if (window.closeDrawer) window.closeDrawer(); } catch (e) {}
document.body.style.overflow = '';
host.innerHTML = '';
};
}, []);
return ;
}
window.ContractsDashboard = ContractsDashboard;
/* ============================================================
Contracts — Model page. A registry domain's "model" is the
ENCODING: what we extracted from the documents, where each
field came from, and who consumes it. Not a Finance-style
statement stack — its own shape.
============================================================ */
function ContractsModel() {
const C = {
ink: 'var(--fg-dark)', base: 'var(--fg-base)', muted: 'var(--fg-muted)',
line: 'var(--border-subtle, rgba(38,24,17,0.10))', panel: 'var(--bg-panel)',
green: 'var(--accent-green)', blue: 'var(--accent-blue)', purple: 'var(--accent-purple-ai)',
grey: '#8A8580', red: 'var(--accent-red)',
};
const s = (window.CONTRACTS_REVIEW || { stats: {} }).stats || {};
// Lineage: source → extraction → ODP → ADP → consumer
const LINEAGE = [
{ label: 'Legal corpus', sub: s.total ? s.total + ' signed PDFs' : 'signed PDFs', color: C.blue },
{ label: 'AI extraction', sub: 'read each document', color: C.purple, proc: true },
{ label: 'Tabular Review', sub: 'ODP · structured', color: C.grey },
{ label: 'Expiration Schedule', sub: 'ADP · computed', color: C.purple },
{ label: 'Finance', sub: 'consumes terms', color: C.green },
];
// The encoding schema — what we've pulled out of each contract.
const FIELDS = [
['Party', 'entity ref', 'MSA cover / signature block', 'link → Customers', 'Commercial', false],
['Contract type', 'enum · MSA / SOW', 'Document header', 'attribute', '—', false],
['Model', 'enum · Turnkey / Tolling', 'Pricing clause', 'attribute', 'Finance · COGS', false],
['Committed value', 'money', 'Volume-commitment clause', 'attribute', 'Finance · revenue backlog', false],
['Term start / end', 'date', 'Term clause', 'attribute', 'Expiration schedule · Finance', false],
['Renewal type', 'enum', 'Renewal clause', 'attribute', 'Expiration schedule', false],
['Pricing basis', 'text', 'Pricing clause', 'attribute', 'Finance · margin', false],
['Status', 'enum', 'Register + events', 'attribute', 'Finance · AR', false],
['Quality certs · indemnity · insurance · LoL', 'flags / text', 'Obligations clause', 'not yet extracted', 'future', true],
];
const HEAD = ['Field', 'Type', 'Extracted from', 'Encoded as', 'Feeds'];
const CHECKS = [
['Coverage', (s.total || 0) + ' of ' + (s.total || 0) + ' contracts have a source PDF (100%)'],
['Reconciliation', 'Extracted committed value reconciles to the CLM register'],
['Cross-domain tie', 'Committed ' + (s.committed || '') + ' ties to Finance’s revenue backlog'],
['Scope', '8 fields extracted per contract · clause-level fields (obligations) not yet extracted'],
];
const Chip = (n, i) => (
{i > 0 && →}
);
return (
{/* topbar */}
Contracts Model
A registry — {s.total} contracts encoded from their signed documents
{/* lineage */}
Lineage
{LINEAGE.map(Chip)}
{/* encoding schema */}
What we’ve encoded
the fields extracted from every contract, with provenance and consumer
{HEAD.map((h) => (
| {h} |
))}
{FIELDS.map((f, ri) => (
| {f[0]} |
{f[1]} |
{f[2]} |
{f[3]} |
{f[4]} |
))}
{/* coverage & checks */}
Coverage & checks
{CHECKS.map(([k, v]) => (
))}
);
}
window.ContractsModel = ContractsModel;