No risks identified. Click 'Add New Risk' to start.
`;
return;
}
risks.sort((a, b) => b.score - a.score).forEach((risk, index) => {
// Render register item
const item = document.createElement('div');
item.className = 'bg-white p-3 rounded-lg shadow border';
item.innerHTML = `
${risk.description}
${risk.score}
Likelihood: ${scoreMap[risk.likelihood]} | Impact: ${scoreMap[risk.impact]}
`;
register.appendChild(item);
// Render matrix dot
const cell = document.querySelector(`.matrix-cell[data-impact="${risk.impact}"][data-likelihood="${risk.likelihood}"]`);
if (cell) {
const dot = document.createElement('div');
dot.className = 'risk-dot';
dot.title = risk.description;
// Stagger dots within a cell to avoid perfect overlap
const offsetX = 50 + ((index % 5) - 2) * 15;
const offsetY = 50 + (Math.floor(index / 5) - 1) * 15;
dot.style.left = `${offsetX}%`;
dot.style.top = `${offsetY}%`;
cell.appendChild(dot);
}
});
}
function openModal(risk = null) {
riskForm.reset();
if (risk) {
document.getElementById('modal-title').textContent = 'Edit Risk';
document.getElementById('risk-id').value = risk.id;
document.getElementById('risk-description').value = risk.description;
document.getElementById('risk-likelihood').value = risk.likelihood;
document.getElementById('risk-impact').value = risk.impact;
document.getElementById('risk-mitigation').value = risk.mitigation;
} else {
document.getElementById('modal-title').textContent = 'Add New Risk';
document.getElementById('risk-id').value = '';
}
riskModal.classList.remove('hidden');
}
function closeModal() {
riskModal.classList.add('hidden');
}
riskForm.addEventListener('submit', (e) => {
e.preventDefault();
const id = document.getElementById('risk-id').value;
const newRisk = {
id: id ? parseInt(id) : Date.now(),
description: document.getElementById('risk-description').value,
likelihood: document.getElementById('risk-likelihood').value,
impact: document.getElementById('risk-impact').value,
mitigation: document.getElementById('risk-mitigation').value,
};
newRisk.score = newRisk.likelihood * newRisk.impact;
if (id) {
risks = risks.map(r => r.id === newRisk.id ? newRisk : r);
} else {
risks.push(newRisk);
}
closeModal();
render();
});
document.getElementById('risk-register').addEventListener('click', (e) => {
if (e.target.classList.contains('edit-btn')) {
const risk = risks.find(r => r.id === parseInt(e.target.dataset.id));
openModal(risk);
}
if (e.target.classList.contains('delete-btn')) {
risks = risks.filter(r => r.id !== parseInt(e.target.dataset.id));
render();
}
});
document.getElementById('add-risk-btn').addEventListener('click', () => openModal());
document.getElementById('cancel-btn').addEventListener('click', closeModal);
document.getElementById('download-pdf-btn').addEventListener('click', () => {
if (risks.length === 0) return;
const { jsPDF } = window.jspdf;
const pdf = new jsPDF();
pdf.setFont('helvetica', 'bold').setFontSize(22).text('Risk Management Report', 105, 20, { align: 'center' });
const head = [['ID', 'Description', 'Likelihood', 'Impact', 'Score', 'Mitigation Plan']];
const body = risks.map(r => [
r.id, r.description, scoreMap[r.likelihood], scoreMap[r.impact], r.score, r.mitigation
]);
pdf.autoTable({ startY: 30, head, body, theme: 'grid', headStyles: { fillColor: '#1e293b' } });
pdf.save('Risk_Management_Report.pdf');
});
function loadSampleData() {
risks = [
{ id: 1, description: 'Cybersecurity breach leading to data loss.', likelihood: '2', impact: '3', mitigation: 'Implement MFA, conduct regular security audits.', score: 6 },
{ id: 2, description: 'Key employee departure.', likelihood: '2', impact: '2', mitigation: 'Cross-train staff and document key processes.', score: 4 },
{ id: 3, description: 'Economic downturn affecting sales.', likelihood: '3', impact: '3', mitigation: 'Diversify product offerings and explore new markets.', score: 9 },
{ id: 4, description: 'Supply chain disruption.', likelihood: '1', impact: '3', mitigation: 'Identify alternative suppliers and increase safety stock.', score: 3 }
];
render();
}
loadSampleData();
});