import React from 'react' const CAT_LABEL = { termination: 'Termination', auto_renewal: 'Auto-renewal', term: 'Term / Duration', liability_cap: 'Liability Cap', indemnification: 'Indemnification', governing_law: 'Governing Law', confidentiality: 'Confidentiality', payment_terms: 'Payment Terms', sla: 'Service Levels', data_protection: 'Data Protection', ip_ownership: 'IP Ownership', insurance: 'Insurance', audit_rights: 'Audit Rights', assignment: 'Assignment', exclusivity: 'Exclusivity', force_majeure: 'Force Majeure', warranty: 'Warranty', notice: 'Notice', deliverables: 'Deliverables', } const COLS = ['HIGH', 'MEDIUM', 'LOW'] function cellBg(level, count) { if (count === 0) return 'transparent' const alpha = Math.min(0.18 + count * 0.28, 0.92) if (level === 'HIGH') return `rgba(201,42,42,${alpha})` if (level === 'MEDIUM') return `rgba(217,117,11,${alpha})` return `rgba(91,100,120,${alpha})` } function cellColor(level, count) { if (count === 0) return '#ccc' if (count >= 2) return '#fff' if (level === 'HIGH') return '#c92a2a' if (level === 'MEDIUM') return '#d9750b' return '#5b6478' } export default function RiskHeatmap({ risks, onSelect }) { if (!risks.length) return

No risks to display.

// build grid: category -> { HIGH, MEDIUM, LOW } -> [risk, ...] const grid = {} risks.forEach((r) => { if (!grid[r.category]) grid[r.category] = { HIGH: [], MEDIUM: [], LOW: [] } grid[r.category][r.level].push(r) }) const cats = Object.keys(grid).sort((a, b) => { const maxSev = (cat) => Math.max(...risks.filter(r => r.category === cat).map(r => r.severity)) return maxSev(b) - maxSev(a) }) return (
HIGH MEDIUM LOW — click a cell to see its risks
{COLS.map(c => ( ))} {cats.map((cat) => { const row = grid[cat] const total = COLS.reduce((s, l) => s + row[l].length, 0) return ( {COLS.map((level) => { const n = row[level].length const firstRisk = row[level][0] return ( ) })} ) })}
Category{c}Total
{CAT_LABEL[cat] || cat} 0 ? 'pointer' : 'default', }} title={n > 0 ? row[level].map(r => r.title).join('; ') : ''} onClick={() => n > 0 && firstRisk && onSelect(firstRisk.clause_id)} > {n > 0 ? n : ·} {total}
) }