Succession Planning Dashboard
Key Succession Metrics
Succession Pipeline Overview
Succession Insights
No insights generated yet. Please configure your data.
Data Configuration
Define your critical roles, potential successors, their readiness, and development needs. Click 'Add Role' to add more.
Succession Planning Dashboard Report
Key Succession Metrics
Succession Pipeline Overview
Succession Insights
No roles defined to generate insights. Please add roles in the Data Configuration tab.
'; } else { const criticalRoles = successionData.filter(role => role.critical); const rolesWithoutReadySuccessors = criticalRoles.filter(role => !role.successors.some(s => s.readiness === 5)); const rolesWithMultipleReadySuccessors = criticalRoles.filter(role => role.successors.filter(s => s.readiness === 5).length >= 2); const allDevelopmentNeeds = {}; successionData.forEach(role => { role.successors.forEach(s => { if (s.developmentNeeds && s.developmentNeeds.trim() !== '') { s.developmentNeeds.split(',').forEach(need => { const trimmedNeed = need.trim(); if (trimmedNeed) { allDevelopmentNeeds[trimmedNeed] = (allDevelopmentNeeds[trimmedNeed] || 0) + 1; } }); } }); }); const sortedDevelopmentNeeds = Object.entries(allDevelopmentNeeds) .sort(([, countA], [, countB]) => countB - countA) .map(([need]) => need); insightsHtml += `Overall Succession Health: Currently managing ${criticalRoles.length} critical roles.
`; if (rolesWithoutReadySuccessors.length > 0) { insightsHtml += `Urgent Attention Needed: The following critical roles currently lack a "Ready Now" successor: ${rolesWithoutReadySuccessors.map(r => r.name).join(', ')}. Prioritize identifying and developing candidates for these positions.
`; } else if (criticalRoles.length > 0) { insightsHtml += `Strong Coverage: All critical roles currently have at least one "Ready Now" successor identified. Good job!
`; } if (rolesWithMultipleReadySuccessors.length > 0) { insightsHtml += `Robust Pipeline: Roles with multiple "Ready Now" successors, indicating a strong talent pipeline: ${rolesWithMultipleReadySuccessors.map(r => r.name).join(', ')}.
`; } if (sortedDevelopmentNeeds.length > 0) { insightsHtml += `Common Development Themes: Recurring development needs across successors include: ${sortedDevelopmentNeeds.slice(0, 3).join(', ')}${sortedDevelopmentNeeds.length > 3 ? '...' : ''}. Consider group training or generalized programs for these areas.
`; } else { insightsHtml += `No common development themes identified. Ensure development needs are specified for successors.
`; } } successionInsights.innerHTML = insightsHtml; } // --- Event Handlers (Globally accessible for onclick attributes) --- /** * Switches between dashboard and data configuration tabs. * @param {string} tabName - 'dashboard' or 'dataConfig'. */ window.switchTab = function(tabName) { // Guard clauses for elements if (!dashboardTabBtn || !dataConfigTabBtn || !dashboardTabContent || !dataConfigTabContent || !prevTabBtn || !nextTabBtn) { console.error("One or more tab elements not found."); return; } currentTab = tabName; // Update button styles dashboardTabBtn.classList.remove('active'); dataConfigTabBtn.classList.remove('active'); dashboardTabContent.classList.add('hidden'); dataConfigTabContent.classList.add('hidden'); if (tabName === 'dashboard') { dashboardTabBtn.classList.add('active'); dashboardTabContent.classList.remove('hidden'); prevTabBtn.disabled = true; nextTabBtn.disabled = false; renderKpiMetrics(); // Re-render dashboard KPI content renderPipelineOverview(); // Re-render pipeline overview generateSuccessionInsights(); // Re-generate insights } else if (tabName === 'dataConfig') { dataConfigTabBtn.classList.add('active'); dataConfigTabContent.classList.remove('hidden'); prevTabBtn.disabled = false; nextTabBtn.disabled = true; renderAllRoleInputSections(); // Re-render input rows when tab is active } }; /** * Navigates between tabs using 'Next' and 'Previous' buttons. * @param {string} direction - 'prev' or 'next'. */ window.navigateTabs = function(direction) { if (direction === 'next') { if (currentTab === 'dashboard') { switchTab('dataConfig'); } } else if (direction === 'prev') { if (currentTab === 'dataConfig') { switchTab('dashboard'); } } }; /** * Adds a new empty role section to the data configuration. */ if (addRoleBtn) { // Null check for addRoleBtn addRoleBtn.onclick = function() { const newRoleId = generateUniqueRoleId(); const newRole = { id: newRoleId, name: '', critical: false, successors: [] }; successionData.push(newRole); renderRoleInputSection(newRole); showMessage('New role added.', 'info'); }; } /** * Updates a specific property of a role in the successionData array. * This function is called directly from input fields' oninput/onchange. * @param {string} roleId - The ID of the role to update. * @param {string} property - The property to update ('name', 'critical'). * @param {*} value - The new value for the property. */ window.updateRoleValue = function(roleId, property, value) { const roleIndex = successionData.findIndex(r => r.id === roleId); if (roleIndex !== -1) { successionData[roleIndex][property] = value; } }; /** * Removes a role from the successionData array and its corresponding section. * @param {string} roleId - The ID of the role to remove. */ window.removeRole = function(roleId) { successionData = successionData.filter(r => r.id !== roleId); const roleSection = document.getElementById(`role-section-${roleId}`); if (roleSection) { roleSection.remove(); showMessage('Role removed successfully.', 'success'); } else { console.warn(`Role section with ID ${roleId} not found for removal.`); } }; /** * Adds a new empty successor card to a specific role. * @param {string} roleId - The ID of the role to add a successor to. */ window.addSuccessor = function(roleId) { const role = successionData.find(r => r.id === roleId); if (role) { const newSuccessorId = `${roleId}_${generateUniqueSuccessorId()}`; // Ensure unique ID per role const newSuccessor = { id: newSuccessorId, name: '', readiness: null, developmentNeeds: '' }; role.successors.push(newSuccessor); renderSuccessorInputCard(roleId, newSuccessor); showMessage('New successor added.', 'info'); } }; /** * Updates a specific property of a successor within a role. * @param {string} roleId - The ID of the parent role. * @param {string} successorId - The ID of the successor to update. * @param {string} property - The property to update ('name', 'readiness', 'developmentNeeds'). * @param {*} value - The new value for the property. */ window.updateSuccessorValue = function(roleId, successorId, property, value) { const role = successionData.find(r => r.id === roleId); if (role) { const successorIndex = role.successors.findIndex(s => s.id === successorId); if (successorIndex !== -1) { role.successors[successorIndex][property] = value; } } }; /** * Removes a successor from a specific role. * @param {string} roleId - The ID of the parent role. * @param {string} successorId - The ID of the successor to remove. */ window.removeSuccessor = function(roleId, successorId) { const role = successionData.find(r => r.id === roleId); if (role) { role.successors = role.successors.filter(s => s.id !== successorId); const successorCard = document.getElementById(`successor-card-${successorId}`); if (successorCard) { successorCard.remove(); showMessage('Successor removed successfully.', 'success'); } else { console.warn(`Successor card with ID ${successorId} not found for removal.`); } } }; /** * Saves the data (which is already updated via oninput) and refreshes the dashboard. */ if (saveDataBtn) { // Null check for saveDataBtn saveDataBtn.onclick = function() { // Clean up data: remove empty roles or successors if needed successionData = successionData.filter(role => role.name.trim() !== '' || role.successors.length > 0 ).map(role => { role.successors = role.successors.filter(s => s.name.trim() !== ''); return role; }); renderKpiMetrics(); // Re-render dashboard KPIs renderPipelineOverview(); // Re-render pipeline overview generateSuccessionInsights(); // Re-generate insights showMessage('Data saved and dashboard updated!', 'success'); }; } /** * Handles the PDF download functionality. */ if (downloadPdfBtn) { // Null check for downloadPdfBtn downloadPdfBtn.onclick = async function() { if (!pdfContent || !pdfKpiMetrics || !pdfPipelineOverview || !pdfSuccessionInsights) { console.error("PDF content elements not found."); showMessage('Error: PDF content elements missing.', 'error'); return; } // Populate the hidden PDF content div with current dashboard data // KPI Metrics for PDF pdfKpiMetrics.innerHTML = `Key Succession Metrics
`; const totalCriticalRoles = successionData.filter(role => role.critical).length; let rolesWithReadySuccessors = 0; let totalReadinessScore = 0; let totalSuccessors = 0; let readyNowSuccessors = 0; successionData.forEach(role => { if (role.critical) { const readySuccessorsInRole = role.successors.filter(s => s.readiness === 5).length; if (readySuccessorsInRole > 0) { rolesWithReadySuccessors++; } } role.successors.forEach(s => { totalReadinessScore += s.readiness || 0; totalSuccessors++; if (s.readiness === 5) { readyNowSuccessors++; } }); }); const avgReadinessScore = totalSuccessors > 0 ? (totalReadinessScore / totalSuccessors).toFixed(1) : 'N/A'; pdfKpiMetrics.innerHTML += `Total Critical Roles: ${totalCriticalRoles}
Roles with Ready Now Successors: ${rolesWithReadySuccessors}
Average Successor Readiness: ${avgReadinessScore}
Ready Now Successors Identified: ${readyNowSuccessors}
Succession Pipeline Overview
`; if (successionData.length === 0) { pdfPipelineOverview.innerHTML += 'No roles defined for the pipeline overview.
'; } else { successionData.forEach(role => { pdfPipelineOverview.innerHTML += `${role.name} ${role.critical ? '(Critical Role)' : ''}
${role.successors.length === 0 ? 'No successors identified for this role.
' : ''}| Successor Name | Readiness | Development Needs |
|---|---|---|
| ${successor.name || 'N/A'} | ${getReadinessDescription(successor.readiness)} | ${successor.developmentNeeds || 'None'} |
Succession Insights
`; let insightsForPdf = ''; if (successionData.length === 0) { insightsForPdf = 'No insights generated. Please configure your data.
'; } else { const criticalRoles = successionData.filter(role => role.critical); const rolesWithoutReadySuccessors = criticalRoles.filter(role => !role.successors.some(s => s.readiness === 5)); const rolesWithMultipleReadySuccessors = criticalRoles.filter(role => role.successors.filter(s => s.readiness === 5).length >= 2); const allDevelopmentNeeds = {}; successionData.forEach(role => { role.successors.forEach(s => { if (s.developmentNeeds && s.developmentNeeds.trim() !== '') { s.developmentNeeds.split(',').forEach(need => { const trimmedNeed = need.trim(); if (trimmedNeed) { allDevelopmentNeeds[trimmedNeed] = (allDevelopmentNeeds[trimmedNeed] || 0) + 1; } }); } }); }); const sortedDevelopmentNeeds = Object.entries(allDevelopmentNeeds) .sort(([, countA], [, countB]) => countB - countA) .map(([need]) => need); insightsForPdf += `Overall Succession Health: Currently managing ${criticalRoles.length} critical roles.
`; if (rolesWithoutReadySuccessors.length > 0) { insightsForPdf += `Urgent Attention Needed: The following critical roles currently lack a "Ready Now" successor: ${rolesWithoutReadySuccessors.map(r => r.name).join(', ')}. Prioritize identifying and developing candidates for these positions.
`; } else if (criticalRoles.length > 0) { insightsForPdf += `Strong Coverage: All critical roles currently have at least one "Ready Now" successor identified. Good job!
`; } if (rolesWithMultipleReadySuccessors.length > 0) { insightsForPdf += `Robust Pipeline: Roles with multiple "Ready Now" successors, indicating a strong talent pipeline: ${rolesWithMultipleReadySuccessors.map(r => r.name).join(', ')}.
`; } if (sortedDevelopmentNeeds.length > 0) { insightsForPdf += `Common Development Themes: Recurring development needs across successors include: ${sortedDevelopmentNeeds.slice(0, 3).join(', ')}${sortedDevelopmentNeeds.length > 3 ? '...' : ''}. Consider group training or generalized programs for these areas.
`; } else { insightsForPdf += `No common development themes identified. Ensure development needs are specified for successors.
`; } insightsForPdf += `