New Roaster

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Student Shift Roster</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
    <style>
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
        }
        
        body {
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #1a2a6c);
            color: #333;
            padding: 20px;
            min-height: 100vh;
        }
        
        .container {
            max-width: 1400px;
            margin: 20px auto;
            background: rgba(255, 255, 255, 0.95);
            border-radius: 15px;
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
            overflow: hidden;
        }
        
        header {
            background: linear-gradient(to right, #2c3e50, #1a2a6c);
            color: white;
            padding: 25px;
            text-align: center;
            position: relative;
        }
        
        header h1 {
            font-size: 2.5rem;
            margin-bottom: 10px;
            font-weight: 700;
        }
        
        .subtitle {
            font-size: 1.2rem;
            opacity: 0.9;
            max-width: 700px;
            margin: 0 auto;
        }
        
        .controls {
            display: flex;
            justify-content: space-between;
            padding: 20px;
            background: #f8f9fa;
            border-bottom: 1px solid #e0e0e0;
            flex-wrap: wrap;
            gap: 15px;
        }
        
        .week-navigation {
            display: flex;
            align-items: center;
            gap: 10px;
        }
        
        .week-navigation button {
            background: #3498db;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 30px;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .week-navigation button:hover {
            background: #2980b9;
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        }
        
        .current-week {
            font-weight: 700;
            font-size: 1.2rem;
            background: #2c3e50;
            color: white;
            padding: 8px 20px;
            border-radius: 30px;
            min-width: 300px;
        }
        
        .action-buttons {
            display: flex;
            gap: 10px;
        }
        
        .action-buttons button {
            background: #27ae60;
            color: white;
            border: none;
            padding: 10px 20px;
            border-radius: 30px;
            cursor: pointer;
            font-weight: 600;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .action-buttons button:hover {
            background: #219653;
            transform: translateY(-2px);
            box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        }
        
        .action-buttons button.add-leave {
            background: #e74c3c;
        }
        
        .action-buttons button.add-leave:hover {
            background: #c0392b;
        }
        
        .shift-legend {
            display: flex;
            justify-content: center;
            gap: 10px;
            margin: 20px 0;
            padding: 0 20px;
            flex-wrap: wrap;
        }
        
        .legend-item {
            display: flex;
            align-items: center;
            gap: 5px;
            padding: 8px 15px;
            border-radius: 30px;
            font-size: 0.9rem;
            font-weight: 500;
            background: #f0f0f0;
        }
        
        .legend-color {
            width: 20px;
            height: 20px;
            border-radius: 50%;
        }
        
        .roster-container {
            overflow-x: auto;
            padding: 20px;
        }
        
        .roster-table {
            width: 100%;
            border-collapse: collapse;
            margin: 20px 0;
            box-shadow: 0 0 20px rgba(0, 0, 0, 0.08);
        }
        
        .roster-table th {
            background-color: #2c3e50;
            color: white;
            padding: 15px;
            text-align: center;
            position: sticky;
            top: 0;
            z-index: 10;
        }
        
        .roster-table th.day-header {
            background: #34495e;
        }
        
        .roster-table td {
            padding: 15px;
            text-align: center;
            border: 1px solid #e0e0e0;
            position: relative;
        }
        
        .date-display {
            font-size: 0.9rem;
            font-weight: 600;
            margin-top: 5px;
            color: #f1c40f;
        }
        
        .student-name-cell {
            font-weight: 700;
            background-color: #f8f9fa;
            position: sticky;
            left: 0;
            z-index: 5;
            min-width: 180px;
            text-align: left;
            padding-left: 20px;
        }
        
        .student-name-cell .contact {
            font-size: 0.85rem;
            color: #7f8c8d;
            font-weight: 400;
            margin-top: 5px;
        }
        
        .student-name-cell .remove-btn {
            position: absolute;
            right: 10px;
            top: 50%;
            transform: translateY(-50%);
            background: transparent;
            border: none;
            color: #e74c3c;
            cursor: pointer;
            opacity: 0;
            transition: opacity 0.3s;
        }
        
        .student-name-cell:hover .remove-btn {
            opacity: 1;
        }
        
        .shift-cell {
            font-weight: 600;
            cursor: pointer;
            min-width: 120px;
            height: 80px;
            transition: all 0.2s;
            position: relative;
        }
        
        .shift-cell:hover {
            transform: scale(1.03);
            z-index: 2;
            box-shadow: 0 0 15px rgba(0, 0, 0, 0.1);
        }
        
        .shift-10-7 { background-color: #e74c3c; color: white; }
        .shift-9-6 { background-color: #f39c12; color: white; }
        .shift-7-4 { background-color: #3498db; color: white; }
        .shift-1-10 { background-color: #2ecc71; color: white; }
        
        .off-day {
            background: linear-gradient(135deg, #bdc3c7, #95a5a6);
            color: #2c3e50;
            font-style: italic;
            font-weight: 600;
        }
        
        .leave-day {
            background: linear-gradient(135deg, #9b59b6, #8e44ad);
            color: white;
            font-weight: 600;
        }
        
        .long-leave {
            background: repeating-linear-gradient(
                45deg,
                #9b59b6,
                #9b59b6 10px,
                #8e44ad 10px,
                #8e44ad 20px
            );
            color: white;
            font-weight: 600;
        }
        
        .shift-info {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
            padding: 10px;
            opacity: 0;
            transition: opacity 0.3s;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            font-size: 0.9rem;
            text-align: center;
        }
        
        .shift-cell:hover .shift-info {
            opacity: 1;
        }
        
        .student-form {
            background-color: #f8f9fa;
            padding: 25px;
            border-radius: 10px;
            margin: 20px;
        }
        
        .form-title {
            text-align: center;
            margin-bottom: 20px;
            color: #2c3e50;
            font-size: 1.5rem;
        }
        
        .form-row {
            display: flex;
            gap: 20px;
            margin-bottom: 20px;
            flex-wrap: wrap;
        }
        
        .form-group {
            flex: 1;
            min-width: 250px;
        }
        
        label {
            display: block;
            margin-bottom: 8px;
            font-weight: 600;
            color: #2c3e50;
        }
        
        input, select {
            width: 100%;
            padding: 12px 15px;
            border: 1px solid #ddd;
            border-radius: 8px;
            font-size: 1rem;
            transition: border 0.3s;
        }
        
        input:focus, select:focus {
            outline: none;
            border-color: #3498db;
            box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.2);
        }
        
        .form-actions {
            display: flex;
            justify-content: center;
            gap: 15px;
            margin-top: 20px;
        }
        
        .form-actions button {
            padding: 12px 25px;
            border: none;
            border-radius: 8px;
            cursor: pointer;
            font-weight: 600;
            font-size: 1rem;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            gap: 8px;
        }
        
        .form-actions button.add-btn {
            background: #27ae60;
            color: white;
        }
        
        .form-actions button.add-btn:hover {
            background: #219653;
            transform: translateY(-3px);
        }
        
        .form-actions button.cancel-btn {
            background: #e74c3c;
            color: white;
        }
        
        .form-actions button.cancel-btn:hover {
            background: #c0392b;
            transform: translateY(-3px);
        }
        
        .footer-note {
            margin: 20px;
            padding: 20px;
            background: #e8f4fd;
            border-radius: 10px;
            border-left: 5px solid #3498db;
            font-size: 0.95rem;
        }
        
        .footer-note h3 {
            margin-bottom: 10px;
            color: #2c3e50;
        }
        
        .stats {
            display: flex;
            justify-content: space-around;
            margin: 20px 0;
            padding: 15px;
            background: #f8f9fa;
            border-radius: 10px;
        }
        
        .stat-card {
            text-align: center;
            padding: 15px;
            border-radius: 10px;
            background: white;
            box-shadow: 0 4px 8px rgba(0,0,0,0.1);
            min-width: 150px;
        }
        
        .stat-value {
            font-size: 2rem;
            font-weight: 700;
            color: #3498db;
        }
        
        .stat-label {
            font-size: 0.9rem;
            color: #7f8c8d;
        }
        
        .empty-roster {
            text-align: center;
            padding: 50px;
            color: #7f8c8d;
            font-size: 1.2rem;
        }
        
        .empty-roster i {
            font-size: 3rem;
            margin-bottom: 20px;
            color: #bdc3c7;
        }
        
        .notification {
            position: fixed;
            top: 20px;
            right: 20px;
            padding: 15px 25px;
            border-radius: 8px;
            background: #2ecc71;
            color: white;
            font-weight: 600;
            box-shadow: 0 4px 12px rgba(0,0,0,0.15);
            transform: translateX(120%);
            transition: transform 0.3s ease-in-out;
            z-index: 1000;
        }
        
        .notification.show {
            transform: translateX(0);
        }
        
        .notification.error {
            background: #e74c3c;
        }
        
        @media (max-width: 768px) {
            .controls {
                flex-direction: column;
                align-items: center;
            }
            
            .action-buttons {
                width: 100%;
                justify-content: center;
            }
            
            .roster-table {
                font-size: 0.85rem;
            }
            
            .roster-table th, 
            .roster-table td {
                padding: 10px 8px;
            }
            
            .shift-cell {
                height: 70px;
            }
            
            .stats {
                flex-direction: column;
                gap: 10px;
            }
        }
    </style>
</head>
<body>
    <div class="container">
        <header>
            <h1><i class="fas fa-calendar-alt"></i> Student Shift Roster</h1>
            <p class="subtitle">Automated shift scheduling with leave management for students</p>
        </header>
        
        <div class="stats">
            <div class="stat-card">
                <div class="stat-value" id="student-count">0</div>
                <div class="stat-label">Students</div>
            </div>
            <div class="stat-card">
                <div class="stat-value">4</div>
                <div class="stat-label">Shift Types</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="shift-count">0</div>
                <div class="stat-label">Shifts This Week</div>
            </div>
            <div class="stat-card">
                <div class="stat-value" id="leave-count">0</div>
                <div class="stat-label">Leaves</div>
            </div>
        </div>
        
        <div class="controls">
            <div class="week-navigation">
                <button id="prev-week"><i class="fas fa-chevron-left"></i> Previous Week</button>
                <div class="current-week" id="current-week">Week of June 10, 2024 - June 16, 2024</div>
                <button id="next-week">Next Week <i class="fas fa-chevron-right"></i></button>
            </div>
            <div class="action-buttons">
                <button id="add-leave"><i class="fas fa-plus-circle"></i> Add Sudden Leave</button>
                <button id="add-long-leave" class="add-leave"><i class="fas fa-calendar-times"></i> Add Extended Leave</button>
            </div>
        </div>
        
        <div class="shift-legend">
            <div class="legend-item"><div class="legend-color" style="background-color: #e74c3c"></div> 10:30 AM - 7:30 PM</div>
            <div class="legend-item"><div class="legend-color" style="background-color: #f39c12"></div> 9:30 AM - 6:30 PM</div>
            <div class="legend-item"><div class="legend-color" style="background-color: #3498db"></div> 7:30 AM - 4:30 PM</div>
            <div class="legend-item"><div class="legend-color" style="background-color: #2ecc71"></div> 1:30 PM - 10:30 PM</div>
            <div class="legend-item"><div class="legend-color" style="background: linear-gradient(135deg, #bdc3c7, #95a5a6)"></div> Week Off</div>
            <div class="legend-item"><div class="legend-color" style="background: linear-gradient(135deg, #9b59b6, #8e44ad)"></div> Sudden Leave</div>
            <div class="legend-item"><div class="legend-color" style="background: repeating-linear-gradient(45deg, #9b59b6, #9b59b6 10px, #8e44ad 10px, #8e44ad 20px)"></div> Extended Leave</div>
        </div>
        
        <div class="roster-container">
            <table class="roster-table">
                <thead>
                    <tr>
                        <th>Student / Contact</th>
                        <!-- Days will be populated by JavaScript -->
                    </tr>
                </thead>
                <tbody id="roster-body">
                    <!-- Roster will be generated here -->
                </tbody>
            </table>
        </div>
        
        <div class="student-form">
            <h2 class="form-title"><i class="fas fa-user-graduate"></i> Add New Student</h2>
            <div class="form-row">
                <div class="form-group">
                    <label for="student-name"><i class="fas fa-user"></i> Student Name</label>
                    <input type="text" id="student-name" placeholder="Enter student name">
                </div>
                <div class="form-group">
                    <label for="student-contact"><i class="fas fa-phone"></i> Contact (Optional)</label>
                    <input type="text" id="student-contact" placeholder="Phone or email">
                </div>
                <div class="form-group">
                    <label for="shift-type"><i class="fas fa-clock"></i> Shift Type</label>
                    <select id="shift-type">
                        <option value="shift-7-4">7:30 AM - 4:30 PM</option>
                        <option value="shift-9-6">9:30 AM - 6:30 PM</option>
                        <option value="shift-10-7">10:30 AM - 7:30 PM</option>
                        <option value="shift-1-10">1:30 PM - 10:30 PM</option>
                    </select>
                </div>
            </div>
            <div class="form-row">
                <div class="form-group">
                    <label for="week-off-day"><i class="fas fa-calendar-day"></i> Week Off Day</label>
                    <select id="week-off-day">
                        <option value="0">Monday</option>
                        <option value="1">Tuesday</option>
                        <option value="2">Wednesday</option>
                        <option value="3">Thursday</option>
                        <option value="4">Friday</option>
                        <option value="5">Saturday</option>
                        <option value="6">Sunday</option>
                    </select>
                </div>
            </div>
            <div class="form-actions">
                <button class="add-btn" id="add-student"><i class="fas fa-user-plus"></i> Add Student</button>
                <button class="cancel-btn" id="reset-form"><i class="fas fa-times"></i> Clear Form</button>
            </div>
        </div>
        
        <div class="footer-note">
            <h3><i class="fas fa-info-circle"></i> Roster Information</h3>
            <p>• This roster automatically rotates shifts at the end of each week. Each student gets one week off per week (mostly on Sunday).</p>
            <p>• At least 4 students are scheduled for each shift every day to ensure proper coverage.</p>
            <p>• Hover over any shift to see detailed information about the student and schedule.</p>
            <p>• Extended leaves can be added for up to 4 weeks. During leave periods, shifts are automatically reassigned.</p>
        </div>
    </div>
    
    <div class="notification" id="notification">Student added successfully!</div>

    <script>
        // Start with an empty roster
        let students = [];
        let suddenLeaves = [];
        let extendedLeaves = [];

        // Current week tracking
        let currentWeekStart = new Date();
        currentWeekStart.setDate(currentWeekStart.getDate() - currentWeekStart.getDay() + 1);
        currentWeekStart.setHours(0, 0, 0, 0);

        // DOM Elements
        const rosterBody = document.getElementById('roster-body');
        const rosterHead = document.querySelector('.roster-table thead');
        const currentWeekEl = document.getElementById('current-week');
        const prevWeekBtn = document.getElementById('prev-week');
        const nextWeekBtn = document.getElementById('next-week');
        const addLeaveBtn = document.getElementById('add-leave');
        const addLongLeaveBtn = document.getElementById('add-long-leave');
        const addStudentBtn = document.getElementById('add-student');
        const resetFormBtn = document.getElementById('reset-form');
        const studentCountEl = document.getElementById('student-count');
        const shiftCountEl = document.getElementById('shift-count');
        const leaveCountEl = document.getElementById('leave-count');
        const notification = document.getElementById('notification');

        // Initialize the roster
        function initRoster() {
            updateWeekDisplay();
            renderRoster();
            updateStats();
        }

        // Update the current week display
        function updateWeekDisplay() {
            const startDate = new Date(currentWeekStart);
            const endDate = new Date(currentWeekStart);
            endDate.setDate(endDate.getDate() + 6);
            
            const options = { month: 'long', day: 'numeric', year: 'numeric' };
            currentWeekEl.textContent = `Week of ${startDate.toLocaleDateString('en-US', options)} - ${endDate.toLocaleDateString('en-US', options)}`;
        }

        // Show notification
        function showNotification(message, isError = false) {
            notification.textContent = message;
            notification.className = isError ? 'notification error' : 'notification';
            notification.classList.add('show');
            
            setTimeout(() => {
                notification.classList.remove('show');
            }, 3000);
        }

        // Render the roster table
        function renderRoster() {
            // Clear existing content
            rosterHead.innerHTML = '<tr><th>Student / Contact</th></tr>';
            rosterBody.innerHTML = '';
            
            if (students.length === 0) {
                rosterBody.innerHTML = `
                    <tr>
                        <td colspan="8" class="empty-roster">
                            <i class="fas fa-user-graduate"></i>
                            <h3>No Students Added</h3>
                            <p>Add students using the form below to start creating your roster</p>
                        </td>
                    </tr>
                `;
                return;
            }
            
            // Create header row with dates
            const headerRow = document.createElement('tr');
            const studentHeader = document.createElement('th');
            studentHeader.textContent = 'Student / Contact';
            headerRow.appendChild(studentHeader);
            
            // Add day headers with dates
            for (let i = 0; i < 7; i++) {
                const date = new Date(currentWeekStart);
                date.setDate(date.getDate() + i);
                
                const dayHeader = document.createElement('th');
                dayHeader.className = 'day-header';
                
                const dayName = date.toLocaleDateString('en-US', { weekday: 'short' });
                const dateStr = date.toLocaleDateString('en-US', { month: 'short', day: 'numeric' });
                
                dayHeader.innerHTML = `${dayName}<div class="date-display">${dateStr}</div>`;
                headerRow.appendChild(dayHeader);
            }
            
            rosterHead.appendChild(headerRow);
            
            // Add student rows
            students.forEach(student => {
                const row = document.createElement('tr');
                
                // Student name cell
                const nameCell = document.createElement('td');
                nameCell.className = 'student-name-cell';
                nameCell.innerHTML = `
                    <div>
                        ${student.name}
                        <button class="remove-btn" data-id="${student.id}" title="Remove student">
                            <i class="fas fa-trash-alt"></i>
                        </button>
                    </div>
                    <div class="contact">${student.contact || 'No contact'}</div>
                `;
                row.appendChild(nameCell);
                
                // Create cells for each day of the week
                for (let day = 0; day < 7; day++) {
                    const cell = document.createElement('td');
                    const date = new Date(currentWeekStart);
                    date.setDate(date.getDate() + day);
                    const dateStr = date.toISOString().split('T')[0];
                    
                    // Check for extended leave
                    const onExtendedLeave = isOnExtendedLeave(student.id, dateStr);
                    
                    if (onExtendedLeave) {
                        cell.className = 'shift-cell long-leave';
                        cell.innerHTML = `
                            <div>Extended Leave</div>
                            <div class="shift-info">
                                ${student.name}<br>
                                ${getLeaveReason(student.id, dateStr)}<br>
                                ${formatDateRange(onExtendedLeave.start, onExtendedLeave.end)}
                            </div>
                        `;
                    } else if (day === student.weekOff) {
                        // Week off day
                        cell.className = 'shift-cell off-day';
                        cell.innerHTML = `
                            <div>Week Off</div>
                            <div class="shift-info">
                                ${student.name}<br>
                                Weekly day off<br>
                                ${getShiftTime(student.shift)} shift on other days
                            </div>
                        `;
                    } else if (isOnSuddenLeave(student.id, day, dateStr)) {
                        // Sudden leave
                        cell.className = 'shift-cell leave-day';
                        cell.innerHTML = `
                            <div>Sudden Leave</div>
                            <div class="shift-info">
                                ${student.name}<br>
                                ${getLeaveReason(student.id, dateStr) || 'Emergency leave'}<br>
                                Normally: ${getShiftTime(student.shift)}
                            </div>
                        `;
                    } else {
                        // Regular shift
                        cell.className = `shift-cell ${student.shift}`;
                        cell.innerHTML = `
                            <div>${getShiftTime(student.shift)}</div>
                            <div class="shift-info">
                                ${student.name}<br>
                                ${student.contact ? `Contact: ${student.contact}` : ''}<br>
                                Week Off: ${getDayName(student.weekOff)}
                            </div>
                        `;
                    }
                    
                    row.appendChild(cell);
                }
                
                rosterBody.appendChild(row);
            });
            
            // Add event listeners to remove buttons
            document.querySelectorAll('.remove-btn').forEach(button => {
                button.addEventListener('click', function() {
                    const studentId = this.getAttribute('data-id');
                    removeStudent(studentId);
                });
            });
            
            updateStats();
        }

        // Remove a student from the roster
        function removeStudent(studentId) {
            if (confirm('Are you sure you want to remove this student from the roster?')) {
                const studentIndex = students.findIndex(s => s.id == studentId);
                if (studentIndex !== -1) {
                    const studentName = students[studentIndex].name;
                    students.splice(studentIndex, 1);
                    
                    // Remove any leaves associated with this student
                    suddenLeaves = suddenLeaves.filter(leave => leave.studentId != studentId);
                    extendedLeaves = extendedLeaves.filter(leave => leave.studentId != studentId);
                    
                    renderRoster();
                    showNotification(`${studentName} has been removed from the roster`);
                }
            }
        }

        // Update statistics
        function updateStats() {
            studentCountEl.textContent = students.length;
            
            // Calculate shift count (total shifts minus week offs and leaves)
            let shiftCount = 0;
            if (students.length > 0) {
                shiftCount = students.length * 7; // 7 days per student
                
                // Subtract week offs
                students.forEach(student => {
                    shiftCount--; // for the week off
                });
                
                // Subtract sudden leaves
                shiftCount -= suddenLeaves.length;
                
                // Subtract extended leaves
                extendedLeaves.forEach(leave => {
                    const start = new Date(leave.start);
                    const end = new Date(leave.end);
                    const days = Math.ceil((end - start) / (1000 * 60 * 60 * 24)) + 1;
                    shiftCount -= days;
                });
            }
            
            shiftCountEl.textContent = shiftCount;
            leaveCountEl.textContent = suddenLeaves.length + extendedLeaves.length;
        }

        // Get formatted shift time
        function getShiftTime(shiftType) {
            switch(shiftType) {
                case 'shift-7-4': return '7:30-4:30';
                case 'shift-9-6': return '9:30-6:30';
                case 'shift-10-7': return '10:30-7:30';
                case 'shift-1-10': return '1:30-10:30';
                default: return '';
            }
        }

        // Get day name from index
        function getDayName(dayIndex) {
            const days = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
            return days[dayIndex];
        }

        // Format date range
        function formatDateRange(start, end) {
            const startDate = new Date(start);
            const endDate = new Date(end);
            
            return `${startDate.toLocaleDateString()} - ${endDate.toLocaleDateString()}`;
        }

        // Check if student is on sudden leave
        function isOnSuddenLeave(studentId, day, dateStr) {
            return suddenLeaves.some(leave => 
                leave.studentId === studentId && 
                (leave.day === day || leave.date === dateStr)
            );
        }

        // Check if student is on extended leave
        function isOnExtendedLeave(studentId, dateStr) {
            const date = new Date(dateStr);
            return extendedLeaves.find(leave => 
                leave.studentId === studentId && 
                new Date(leave.start) <= date && 
                new Date(leave.end) >= date
            );
        }

        // Get leave reason
        function getLeaveReason(studentId, dateStr) {
            const suddenLeave = suddenLeaves.find(leave => 
                leave.studentId === studentId && 
                (leave.date === dateStr || leave.day === new Date(dateStr).getDay())
            );
            
            if (suddenLeave) return suddenLeave.reason;
            
            const extendedLeave = extendedLeaves.find(leave => 
                leave.studentId === studentId && 
                new Date(leave.start) <= new Date(dateStr) && 
                new Date(leave.end) >= new Date(dateStr)
            );
            
            if (extendedLeave) return extendedLeave.reason;
            
            return null;
        }

        // Add a new student
        function addStudent() {
            const nameInput = document.getElementById('student-name');
            const contactInput = document.getElementById('student-contact');
            const shiftSelect = document.getElementById('shift-type');
            const weekOffSelect = document.getElementById('week-off-day');
            
            if (!nameInput.value.trim()) {
                showNotification('Please enter a student name', true);
                return;
            }
            
            const newStudent = {
                id: Date.now(), // Use timestamp for unique ID
                name: nameInput.value.trim(),
                contact: contactInput.value.trim(),
                shift: shiftSelect.value,
                weekOff: parseInt(weekOffSelect.value)
            };
            
            students.push(newStudent);
            
            // Clear form
            nameInput.value = '';
            contactInput.value = '';
            shiftSelect.value = 'shift-7-4';
            weekOffSelect.value = '6';
            
            renderRoster();
            showNotification(`${newStudent.name} added to the roster`);
        }

        // Add a sudden leave
        function addSuddenLeave() {
            if (students.length === 0) {
                showNotification('No students in roster', true);
                return;
            }
            
            const studentName = prompt("Enter student name for leave:");
            if (!studentName) return;
            
            const student = students.find(s => s.name === studentName);
            if (!student) {
                showNotification('Student not found', true);
                return;
            }
            
            const leaveDay = prompt("Enter day for leave (Mon, Tue, etc):");
            if (!leaveDay) return;
            
            const dayIndex = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun']
                .indexOf(leaveDay.toLowerCase().substring(0, 3));
                
            if (dayIndex === -1) {
                showNotification('Invalid day entered', true);
                return;
            }
            
            // Can't add leave on week off day
            if (dayIndex === student.weekOff) {
                showNotification('Cannot add leave on student\'s week off day', true);
                return;
            }
            
            const reason = prompt("Enter reason for leave:") || "Emergency leave";
            
            suddenLeaves.push({
                studentId: student.id,
                day: dayIndex,
                reason: reason
            });
            
            renderRoster();
            showNotification(`Added sudden leave for ${student.name} on ${getDayName(dayIndex)}: ${reason}`);
        }

        // Add an extended leave
        function addExtendedLeave() {
            if (students.length === 0) {
                showNotification('No students in roster', true);
                return;
            }
            
            const studentName = prompt("Enter student name for extended leave:");
            if (!studentName) return;
            
            const student = students.find(s => s.name === studentName);
            if (!student) {
                showNotification('Student not found', true);
                return;
            }
            
            const startDate = prompt("Enter start date (YYYY-MM-DD):");
            if (!startDate || !isValidDate(startDate)) {
                showNotification('Invalid start date', true);
                return;
            }
            
            const endDate = prompt("Enter end date (YYYY-MM-DD):");
            if (!endDate || !isValidDate(endDate)) {
                showNotification('Invalid end date', true);
                return;
            }
            
            if (new Date(endDate) < new Date(startDate)) {
                showNotification('End date must be after start date', true);
                return;
            }
            
            const reason = prompt("Enter reason for leave:") || "Extended leave";
            
            extendedLeaves.push({
                studentId: student.id,
                start: startDate,
                end: endDate,
                reason: reason
            });
            
            renderRoster();
            showNotification(`Added extended leave for ${student.name} from ${startDate} to ${endDate}: ${reason}`);
        }

        // Validate date format
        function isValidDate(dateString) {
            const regEx = /^\d{4}-\d{2}-\d{2}$/;
            if (!dateString.match(regEx)) return false;
            const d = new Date(dateString);
            return d instanceof Date && !isNaN(d);
        }

        // Rotate shifts for the next week
        function rotateShifts() {
            students.forEach(student => {
                // Sunday off students keep Sunday off
                if (student.weekOff === 6) return;
                
                // Rotate week off day to next day (with wrap around)
                student.weekOff = (student.weekOff + 1) % 7;
            });
        }

        // Event Listeners
        prevWeekBtn.addEventListener('click', () => {
            currentWeekStart.setDate(currentWeekStart.getDate() - 7);
            updateWeekDisplay();
            renderRoster();
        });

        nextWeekBtn.addEventListener('click', () => {
            currentWeekStart.setDate(currentWeekStart.getDate() + 7);
            
            // If we're moving to a new week, rotate shifts
            if (currentWeekStart > new Date()) {
                rotateShifts();
            }
            
            updateWeekDisplay();
            renderRoster();
        });

        addLeaveBtn.addEventListener('click', addSuddenLeave);
        addLongLeaveBtn.addEventListener('click', addExtendedLeave);
        addStudentBtn.addEventListener('click', addStudent);
        resetFormBtn.addEventListener('click', () => {
            document.getElementById('student-name').value = '';
            document.getElementById('student-contact').value = '';
            document.getElementById('shift-type').value = 'shift-7-4';
            document.getElementById('week-off-day').value = '6';
        });

        // Initialize the roster
        initRoster();
    </script>
</body>
</html>

Comments

Popular posts from this blog

Learn Termux Command

All Customer Care Contact: