Probation Period Dashboard
Probation Health Overview
Total on Probation
0
On Track
0
High Risk
0
Recently Completed
0
Performance Rating Distribution
Probation Status Pipeline
Probationary Employee List
| Employee | Manager | End Date | Days Left | Status |
|---|
Log Performance Review
Submit New Review
Recent Reviews
Add New Employee
Rating: ${'★'.repeat(r.rating)}${'☆'.repeat(5-r.rating)}
${r.comments}
`; list.appendChild(reviewEl); }); } function renderConfigForm() { const managerSelect = document.getElementById('employee-manager'); managerSelect.innerHTML = ''; state.managers.forEach(m => { const option = document.createElement('option'); option.value = m.id; option.textContent = m.name; managerSelect.appendChild(option); }); } // --- EVENT HANDLERS & LOGIC --- // function attachEventListeners() { prevBtn.addEventListener('click', () => changeTab(state.activeTab - 1)); nextBtn.addEventListener('click', () => changeTab(state.activeTab + 1)); downloadPdfBtn.addEventListener('click', handleDownloadPdf); document.getElementById('add-review-form').addEventListener('submit', handleAddReview); document.getElementById('add-employee-form').addEventListener('submit', handleAddEmployee); } window.changeTab = (tabIndex) => { if (tabIndex < 0 || tabIndex >= tabButtons.length) return; state.activeTab = tabIndex; updateTabUI(); }; function updateTabUI() { tabButtons.forEach((b, i) => b.classList.toggle('active', i === state.activeTab)); tabButtons.forEach((b, i) => b.classList.toggle('inactive', i !== state.activeTab)); tabPanes.forEach((p, i) => p.classList.toggle('hidden', i !== state.activeTab)); prevBtn.disabled = state.activeTab === 0; nextBtn.disabled = state.activeTab === tabButtons.length - 1; prevBtn.classList.toggle('opacity-50', prevBtn.disabled); nextBtn.classList.toggle('opacity-50', nextBtn.disabled); } function handleAddReview(e) { e.preventDefault(); const form = e.target; const employeeId = parseInt(form.elements['review-employee-select'].value); const employee = state.employees.find(e => e.id === employeeId); if (employee) { employee.reviews.push({ date: form.elements['review-date'].value, rating: parseInt(form.elements['review-rating'].value), comments: form.elements['review-comments'].value, }); form.reset(); render(); changeTab(2); // Stay on the tab } } function handleAddEmployee(e) { e.preventDefault(); const form = e.target; state.employees.push({ id: Date.now(), name: form.elements['employee-name'].value, managerId: parseInt(form.elements['employee-manager'].value), startDate: form.elements['probation-start-date'].value, length: parseInt(form.elements['probation-length'].value), reviews: [], }); form.reset(); render(); changeTab(1); // Switch to employee list } async function handleDownloadPdf() { const downloadBtn = document.getElementById('download-pdf-btn'); if (!downloadBtn || downloadBtn.disabled) return; const originalBtnContent = downloadBtn.innerHTML; downloadBtn.disabled = true; downloadBtn.innerHTML = `Generating PDF...`; try { const { jsPDF } = window.jspdf; const contentToClone = document.getElementById('probation-dashboard-container'); const contentToExport = contentToClone.cloneNode(true); contentToExport.querySelectorAll('.pdf-hide').forEach(el => el.remove()); contentToExport.querySelectorAll('.tab-pane:not(#tab-0-content)').forEach(el => el.remove()); contentToExport.querySelector('#tab-0-content').classList.remove('hidden'); document.body.appendChild(contentToExport); contentToExport.style.cssText = 'position:absolute; left:0; top:0; width:1024px; z-index:-1; background-color:white; padding:2rem;'; const canvas = await html2canvas(contentToExport, { scale: 2, useCORS: true, logging: false }); document.body.removeChild(contentToExport); const imgData = canvas.toDataURL('image/png'); const pdf = new jsPDF({ orientation: 'p', unit: 'pt', format: 'a4' }); const pdfWidth = pdf.internal.pageSize.getWidth(); const scaledHeight = (canvas.height * pdfWidth) / canvas.width; pdf.addImage(imgData, 'PNG', 0, 0, pdfWidth, scaledHeight); pdf.save('Probation_Period_Summary.pdf'); } catch (error) { console.error("Failed to generate PDF:", error); } finally { downloadBtn.disabled = false; downloadBtn.innerHTML = originalBtnContent; } } // --- UTILITY FUNCTIONS --- // function updateEmployeeStatus() { state.employees.forEach(e => { const startDate = new Date(e.startDate); const endDate = new Date(startDate); endDate.setDate(startDate.getDate() + e.length); e.endDate = endDate.toISOString().split('T')[0]; e.daysLeft = Math.ceil((endDate - today) / (1000 * 60 * 60 * 24)); e.daysOnProbation = Math.floor((today - startDate) / (1000 * 60 * 60 * 24)); if (today > endDate) { e.status = 'Completed'; return; } const latestReview = e.reviews.length > 0 ? e.reviews.sort((a,b) => new Date(b.date) - new Date(a.date))[0] : null; if (latestReview && latestReview.rating <= 2) { e.status = 'High Risk'; } else { e.status = 'On Track'; } }); } // --- START THE APP --- // initialize(); });