Online Smart Shift Scheduling System

Smart Shift Scheduling System

Organize your team's schedule with ease.

${emp.role}

Unavailable: ${emp.unavailable.join(', ') || 'None'}

`; list.appendChild(empEl); }); }; // --- MODAL & FORM LOGIC --- app.showShiftModal = (dateStr, shiftId = null) => { const modal = document.getElementById('shiftModal'); const title = document.getElementById('shiftModalTitle'); const date = new Date(dateStr + 'T00:00:00'); title.textContent = shiftId ? `Edit Shift for ${date.toLocaleDateString()}` : `Add Shift for ${date.toLocaleDateString()}`; document.getElementById('shiftDateInput').value = dateStr; document.getElementById('shiftIdInput').value = shiftId || ''; const employeeSelect = document.getElementById('employeeSelect'); employeeSelect.innerHTML = ''; employees.forEach(e => { const isUnavailable = e.unavailable.includes(DAYS[date.getDay()]); employeeSelect.innerHTML += ``; }); const deleteBtn = document.getElementById('deleteShiftButton'); if (shiftId) { const shift = shifts[dateStr].find(s => s.id === shiftId); employeeSelect.value = shift.employeeId; document.getElementById('startTimeInput').value = shift.start; document.getElementById('endTimeInput').value = shift.end; document.getElementById('shiftNotesInput').value = shift.notes; deleteBtn.classList.remove('hidden'); } else { document.getElementById('shiftModal').querySelector('form') ? document.getElementById('shiftModal').querySelector('form').reset() : null; employeeSelect.value = ''; document.getElementById('startTimeInput').value = '09:00'; document.getElementById('endTimeInput').value = '17:00'; document.getElementById('shiftNotesInput').value = ''; deleteBtn.classList.add('hidden'); } modal.classList.remove('hidden'); }; app.showEmployeeModal = (employeeId = null) => { const modal = document.getElementById('employeeModal'); const title = document.getElementById('employeeModalTitle'); const idInput = document.getElementById('employeeIdInput'); const nameInput = document.getElementById('employeeNameInput'); const roleInput = document.getElementById('employeeRoleInput'); const availabilityDiv = document.getElementById('availabilityCheckboxes'); availabilityDiv.innerHTML = ''; DAYS.forEach(day => { availabilityDiv.innerHTML += ` `; }); if (employeeId) { const emp = employees.find(e => e.id === employeeId); title.textContent = 'Edit Employee'; idInput.value = emp.id; nameInput.value = emp.name; roleInput.value = emp.role; emp.unavailable.forEach(day => { const checkbox = availabilityDiv.querySelector(`input[value="${day}"]`); if (checkbox) checkbox.checked = true; }); } else { title.textContent = 'Add New Employee'; idInput.value = ''; nameInput.value = ''; roleInput.value = ''; } modal.classList.remove('hidden'); }; app.hideModal = (modalId) => document.getElementById(modalId).classList.add('hidden'); // --- CORE LOGIC --- app.saveShift = () => { const date = document.getElementById('shiftDateInput').value; const id = document.getElementById('shiftIdInput').value; const employeeId = parseInt(document.getElementById('employeeSelect').value); if (!employeeId) { alert('Please select an employee.'); return; } const newShift = { id: id ? parseInt(id) : Date.now(), employeeId, start: document.getElementById('startTimeInput').value, end: document.getElementById('endTimeInput').value, notes: document.getElementById('shiftNotesInput').value }; if (!shifts[date]) shifts[date] = []; if (id) { const index = shifts[date].findIndex(s => s.id === newShift.id); shifts[date][index] = newShift; } else { shifts[date].push(newShift); } saveShifts(); renderSchedule(); app.hideModal('shiftModal'); }; app.deleteShift = () => { const date = document.getElementById('shiftDateInput').value; const id = parseInt(document.getElementById('shiftIdInput').value); if (confirm('Are you sure you want to delete this shift?')) { shifts[date] = shifts[date].filter(s => s.id !== id); if (shifts[date].length === 0) delete shifts[date]; saveShifts(); renderSchedule(); app.hideModal('shiftModal'); } }; app.saveEmployee = () => { const id = document.getElementById('employeeIdInput').value; const name = document.getElementById('employeeNameInput').value; if (!name.trim()) { alert('Employee name is required.'); return; } const unavailable = Array.from(document.getElementById('availabilityCheckboxes').querySelectorAll('input:checked')).map(cb => cb.value); const employeeData = { name, role: document.getElementById('employeeRoleInput').value, unavailable }; if (id) { const emp = employees.find(e => e.id === parseInt(id)); Object.assign(emp, employeeData); } else { employees.push({ id: Date.now(), ...employeeData }); } saveEmployees(); renderEmployees(); app.hideModal('employeeModal'); }; app.deleteEmployee = (id) => { if (confirm('Are you sure you want to delete this employee? This will not remove their assigned shifts.')) { employees = employees.filter(e => e.id !== id); saveEmployees(); renderEmployees(); } }; app.changeWeek = (delta) => { currentWeekStartDate.setDate(currentWeekStartDate.getDate() + (delta * 7)); renderSchedule(); }; // --- TAB NAVIGATION --- app.changeTab = (tabIndex) => { document.getElementById(`tabContent-${currentTab}`).classList.add('hidden'); document.getElementById(`tab-${currentTab}`).classList.replace('tab-active', 'tab-inactive'); document.getElementById(`tabContent-${tabIndex}`).classList.remove('hidden'); document.getElementById(`tab-${tabIndex}`).classList.replace('tab-inactive', 'tab-active'); currentTab = tabIndex; }; // --- PDF DOWNLOAD --- app.downloadSchedulePDF = () => { const { jsPDF } = window.jspdf; const doc = new jsPDF(); const startDate = new Date(currentWeekStartDate); doc.setFontSize(20); doc.text(`Weekly Schedule: ${startDate.toLocaleDateString()}`, 105, 15, { align: 'center' }); const head = [['Day', 'Employee', 'Shift Time', 'Role', 'Notes']]; const body = []; for (let i = 0; i < 7; i++) { const dayDate = new Date(startDate); dayDate.setDate(startDate.getDate() + i); const dateStr = formatDate(dayDate); const dayShifts = shifts[dateStr] || []; if (dayShifts.length > 0) { dayShifts.forEach(shift => { const emp = employees.find(e => e.id === shift.employeeId); body.push([ `${DAYS[i]}, ${dayDate.toLocaleDateString()}`, emp ? emp.name : 'N/A', `${shift.start} - ${shift.end}`, emp ? emp.role : 'N/A', shift.notes ]); }); } else { body.push([`${DAYS[i]}, ${dayDate.toLocaleDateString()}`, '(No Shifts)', '', '', '']); } } doc.autoTable({ head, body, startY: 25 }); doc.save('weekly_schedule.pdf'); }; // --- INITIALIZATION --- loadData(); renderSchedule(); renderEmployees(); });
Scroll to Top