Corporate Governance Compliance Tracker

Corporate Governance Compliance Tracker

Total Tasks

0

Completed

0

Pending

0

Overdue

0

Compliance Status Overview

Task / Requirement Category Due Date Responsible Status

${task.category} - Due: ${task.dueDate}

`; taskListContainer.insertAdjacentHTML('beforeend', item); }); }; /** * Updates the summary cards on the dashboard. */ const updateSummaryCards = () => { const total = tasks.length; const completed = tasks.filter(t => t.status === 'Completed').length; const pending = tasks.filter(t => t.status === 'In Progress' || t.status === 'Not Started').length; const overdue = tasks.filter(t => t.status === 'Overdue').length; document.getElementById('total-tasks').textContent = total; document.getElementById('completed-tasks').textContent = completed; document.getElementById('pending-tasks').textContent = pending; document.getElementById('overdue-tasks').textContent = overdue; }; /** * A master render function to update the entire UI based on the current state. */ const refreshUI = () => { // Check for overdue tasks before rendering const today = new Date().toISOString().split('T')[0]; tasks.forEach(task => { if (task.dueDate < today && task.status !== 'Completed') { task.status = 'Overdue'; } }); renderComplianceTable(); renderTaskList(); updateSummaryCards(); }; // --- CORE LOGIC & EVENT HANDLERS --- /** * Handles form submission for adding or updating a task. * @param {Event} e - The form submission event. */ const handleFormSubmit = (e) => { e.preventDefault(); const id = document.getElementById('task-id').value; const taskData = { name: document.getElementById('task-name').value, category: document.getElementById('task-category').value, dueDate: document.getElementById('task-due-date').value, responsible: document.getElementById('task-responsible').value, status: document.getElementById('task-status').value, }; if (id) { // Update existing task const index = tasks.findIndex(t => t.id == id); if (index !== -1) { tasks[index] = { ...tasks[index], ...taskData }; } } else { // Add new task taskData.id = tasks.length > 0 ? Math.max(...tasks.map(t => t.id)) + 1 : 1; tasks.push(taskData); } resetForm(); refreshUI(); }; /** * Resets the form to its default state for adding a new task. */ const resetForm = () => { taskForm.reset(); document.getElementById('task-id').value = ''; formTitle.textContent = 'Add New Compliance Task'; saveTaskBtn.textContent = 'Save Task'; cancelEditBtn.classList.add('hidden'); }; // --- GLOBAL FUNCTIONS FOR INLINE ONCLICK --- // To adhere to the specification allowing inline onclick, functions are attached to a global object. window.globalFuncs = { /** * Prepares the form for editing a specific task. * @param {number} id - The ID of the task to edit. */ editTask: (id) => { const task = tasks.find(t => t.id === id); if (!task) return; document.getElementById('task-id').value = task.id; document.getElementById('task-name').value = task.name; document.getElementById('task-category').value = task.category; document.getElementById('task-due-date').value = task.dueDate; document.getElementById('task-responsible').value = task.responsible; document.getElementById('task-status').value = task.status; formTitle.textContent = 'Edit Compliance Task'; saveTaskBtn.textContent = 'Update Task'; cancelEditBtn.classList.remove('hidden'); // Scroll to the form for better UX on small screens formTitle.scrollIntoView({ behavior: 'smooth' }); }, /** * Shows the delete confirmation modal. * @param {number} id - The ID of the task to be deleted. */ confirmDelete: (id) => { taskToDeleteId = id; deleteModal.classList.add('visible'); }, /** * Deletes the task after confirmation. */ deleteTask: () => { if (taskToDeleteId !== null) { tasks = tasks.filter(t => t.id !== taskToDeleteId); taskToDeleteId = null; deleteModal.classList.remove('visible'); refreshUI(); } } }; // --- TAB NAVIGATION LOGIC --- /** * Switches the visible tab content. * @param {string} tabName - The name of the tab to switch to ('dashboard' or 'config'). */ window.switchTab = (tabName) => { currentTab = tabName; // Update button styles Object.keys(tabs).forEach(key => { tabs[key].classList.toggle('active', key === tabName); tabs[key].classList.toggle('inactive', key !== tabName); }); // Show/hide content Object.keys(contents).forEach(key => { contents[key].classList.toggle('hidden', key !== tabName); }); updateNavButtons(); }; /** * Handles "Next" and "Previous" button clicks. * @param {string} direction - 'next' or 'prev'. */ window.navigateTabs = (direction) => { const tabKeys = Object.keys(tabs); const currentIndex = tabKeys.indexOf(currentTab); let newIndex; if (direction === 'next' && currentIndex < tabKeys.length - 1) { newIndex = currentIndex + 1; } else if (direction === 'prev' && currentIndex > 0) { newIndex = currentIndex - 1; } else { return; // Should not happen if buttons are disabled correctly } switchTab(tabKeys[newIndex]); }; /** * Updates the enabled/disabled state of the Next/Previous buttons. */ const updateNavButtons = () => { const tabKeys = Object.keys(tabs); const currentIndex = tabKeys.indexOf(currentTab); navButtons.prev.disabled = currentIndex === 0; navButtons.next.disabled = currentIndex === tabKeys.length - 1; }; // --- PDF GENERATION --- /** * Generates and downloads a PDF report of the compliance dashboard. */ const generatePdf = () => { const { jsPDF } = window.jspdf; const doc = new jsPDF(); // Set document title doc.setFontSize(18); doc.text('Corporate Governance Compliance Report', 14, 22); doc.setFontSize(11); doc.setTextColor(100); const reportDate = `Report generated on: ${new Date().toLocaleDateString()}`; doc.text(reportDate, 14, 30); // Add summary stats const summaryText = `Total Tasks: ${tasks.length} | Completed: ${tasks.filter(t=>t.status==='Completed').length} | Pending: ${tasks.filter(t=>t.status==='In Progress' || t.status==='Not Started').length} | Overdue: ${tasks.filter(t=>t.status==='Overdue').length}`; doc.setFontSize(12); doc.text(summaryText, 14, 40); // Prepare table data const tableColumn = ["Task / Requirement", "Category", "Due Date", "Responsible", "Status"]; const tableRows = []; tasks.forEach(task => { const taskData = [ task.name, task.category, task.dueDate, task.responsible, task.status, ]; tableRows.push(taskData); }); // Add table to PDF doc.autoTable({ head: [tableColumn], body: tableRows, startY: 50, theme: 'grid', headStyles: { fillColor: [79, 70, 229] }, // Indigo color for header didParseCell: function (data) { // Custom styling for status cells to match UI if (data.column.index === 4 && data.cell.section === 'body') { const status = data.cell.raw; if (status === 'Completed') data.cell.styles.textColor = [22, 163, 74]; // Green if (status === 'Overdue') data.cell.styles.textColor = [220, 38, 38]; // Red if (status === 'In Progress') data.cell.styles.textColor = [217, 119, 6]; // Yellow } } }); // Save the PDF doc.save('Corporate_Compliance_Report.pdf'); }; // --- INITIALIZATION & EVENT LISTENERS --- taskForm.addEventListener('submit', handleFormSubmit); cancelEditBtn.addEventListener('click', resetForm); downloadPdfBtn.addEventListener('click', generatePdf); // Modal event listeners modalCancelBtn.addEventListener('click', () => deleteModal.classList.remove('visible')); modalConfirmBtn.addEventListener('click', window.globalFuncs.deleteTask); deleteModal.addEventListener('click', (e) => { if (e.target === deleteModal) { deleteModal.classList.remove('visible'); } }); // Initial load tasks = [...sampleTasks]; refreshUI(); updateNavButtons(); });
Scroll to Top