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 (| Category | {COLS.map(c => ({c} | ))}Total |
|---|---|---|
| {CAT_LABEL[cat] || cat} | {COLS.map((level) => { const n = row[level].length const firstRisk = row[level][0] return (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} |