Smart HR Onboarding & Exit Process Automation
Manage a Process
Select an employee to manage their process.
Manage Teams
Manage Employees
Onboarding Checklist Template
Exit Checklist Template
No active processes match the current filters.
'; } function renderProcessManager() { processEmployeeSelect.innerHTML = state.employees.map(e => ``).join(''); const process = state.activeProcesses.find(p => p.processId === state.currentManagedProcessId); if (process) { const employee = state.employees.find(e => e.id === process.employeeId); checklistTitle.textContent = `${employee.name}'s ${process.type} Checklist`; checklistDisplay.innerHTML = process.tasks.map(task => `${t.name}
`).join('');
employeeTeamSelect.innerHTML = state.teams.map(t => ``).join('');
employeesList.innerHTML = state.employees.map(e => `${e.name}
`).join('');
// Templates
onboardingTasksList.innerHTML = state.onboardingTemplate.map(t => `${t.text}
`).join('');
exitTasksList.innerHTML = state.exitTemplate.map(t => `${t.text}
`).join('');
}
// SECTION: Event Handlers
function handleTabClick(tabName) { state.activeTab = tabName; render(); }
function handleNavClick(dir) { const i = TABS.indexOf(state.activeTab); const newI = i + dir; if (newI >= 0 && newI < TABS.length) { state.activeTab = TABS[newI]; render(); } }
function handleAddTeam(e) { e.preventDefault(); const name = teamNameInput.value.trim(); if(name){ state.teams.push({id: Date.now(), name}); teamNameInput.value = ''; saveState(); render(); } }
function handleDelete(type, id) { if(confirm(`Delete this ${type}?`)){ state[type+'s'] = state[type+'s'].filter(item => item.id !== id); saveState(); render(); } }
function handleAddEmployee(e) { e.preventDefault(); const name = employeeNameInput.value.trim(); const teamId = parseInt(employeeTeamSelect.value); if(name && teamId){ state.employees.push({id: Date.now(), name, teamId}); employeeNameInput.value = ''; saveState(); render(); } }
function handleAddTemplateTask(type, text) { const template = type === 'onboarding' ? state.onboardingTemplate : state.exitTemplate; template.push({id: Date.now(), text}); saveState(); render(); }
function handleDeleteTemplateTask(type, id) { if(confirm('Delete this task from the template?')){ const template = type === 'onboarding' ? 'onboardingTemplate' : 'exitTemplate'; state[template] = state[template].filter(t => t.id !== id); saveState(); render(); } }
function handleInitiateProcess(e) {
e.preventDefault();
const employeeId = parseInt(processEmployeeSelect.value);
const type = processTypeSelect.value;
const date = processDateInput.value;
let process = state.activeProcesses.find(p => p.employeeId === employeeId && p.type === type);
if (!process) {
const template = type === 'onboarding' ? state.onboardingTemplate : state.exitTemplate;
process = {
processId: Date.now(), employeeId, type, date,
tasks: template.map(t => ({...t, completed: false}))
};
state.activeProcesses.push(process);
}
state.currentManagedProcessId = process.processId;
saveState();
renderProcessManager();
}
function handleTaskToggle(e) {
if (e.target.type === 'checkbox') {
const taskId = parseInt(e.target.dataset.taskId);
const process = state.activeProcesses.find(p => p.processId === state.currentManagedProcessId);
if (process) {
const task = process.tasks.find(t => t.id === taskId);
if (task) {
task.completed = e.target.checked;
saveState();
renderProcessManager(); // Re-render to show visual change
}
}
}
}
function generatePDF(processId) {
const process = state.activeProcesses.find(p => p.processId === processId);
if (!process) return;
const employee = state.employees.find(e => e.id === process.employeeId);
const team = state.teams.find(t => t.id === employee.teamId);
const { jsPDF } = window.jspdf;
const doc = new jsPDF({ orientation: 'p', unit: 'mm', format: 'a4' });
const typeText = process.type.charAt(0).toUpperCase() + process.type.slice(1);
const completedTasks = process.tasks.filter(t => t.completed).length;
const totalTasks = process.tasks.length;
const progress = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 100;
doc.setFontSize(22); doc.setFont('helvetica', 'bold'); doc.text(`${typeText} Process Report`, 105, 20, { align: 'center' });
doc.setFontSize(12); doc.setFont('helvetica', 'normal');
doc.text(`Employee: ${employee.name}`, 14, 35);
doc.text(`Team: ${team.name}`, 14, 42);
doc.text(`Process Start Date: ${new Date(process.date).toLocaleDateString()}`, 14, 49);
doc.text(`Overall Progress: ${progress}% (${completedTasks}/${totalTasks} tasks complete)`, 14, 56);
const tableBody = process.tasks.map(task => [task.text, task.completed ? '✅ Completed' : '🔲 Pending']);
doc.autoTable({
head: [['Task', 'Status']], body: tableBody, startY: 65, theme: 'grid',
headStyles: { fillColor: [37, 99, 235] },
didDrawPage: data => { doc.setFontSize(8); doc.setTextColor(150); doc.text('Page ' + data.pageNumber, data.settings.margin.left, doc.internal.pageSize.height - 10); }
});
doc.save(`${employee.name}_${process.type}_Report.pdf`);
}
// SECTION: Event Listeners
Object.keys(tabButtons).forEach(id => tabButtons[id]?.addEventListener('click', () => handleTabClick(id)));
prevTabBtn?.addEventListener('click', () => handleNavClick(-1));
nextTabBtn?.addEventListener('click', () => handleNavClick(1));
teamFilter?.addEventListener('change', renderDashboard);
processFilter?.addEventListener('change', renderDashboard);
processDisplay.addEventListener('click', e => { if(e.target.classList.contains('download-pdf-btn')) generatePDF(parseInt(e.target.dataset.processId)); });
initiateProcessForm?.addEventListener('submit', handleInitiateProcess);
checklistDisplay?.addEventListener('change', handleTaskToggle);
addTeamForm?.addEventListener('submit', handleAddTeam);
addEmployeeForm?.addEventListener('submit', handleAddEmployee);
addOnboardingTaskForm?.addEventListener('submit', e => { e.preventDefault(); handleAddTemplateTask('onboarding', onboardingTaskTextInput.value); onboardingTaskTextInput.value = ''; });
addExitTaskForm?.addEventListener('submit', e => { e.preventDefault(); handleAddTemplateTask('exit', exitTaskTextInput.value); exitTaskTextInput.value = ''; });
teamsList?.addEventListener('click', e => { if(e.target.classList.contains('delete-team-btn')) handleDelete('team', parseInt(e.target.dataset.id)); });
employeesList?.addEventListener('click', e => { if(e.target.classList.contains('delete-employee-btn')) handleDelete('employee', parseInt(e.target.dataset.id)); });
onboardingTasksList?.addEventListener('click', e => { if(e.target.classList.contains('delete-onboarding-task-btn')) handleDeleteTemplateTask('onboarding', parseInt(e.target.dataset.id)); });
exitTasksList?.addEventListener('click', e => { if(e.target.classList.contains('delete-exit-task-btn')) handleDeleteTemplateTask('exit', parseInt(e.target.dataset.id)); });
// SECTION: Initial Load
loadState();
render();
});
