let currentUser = null; let allShifts = []; let mySignups = []; // Initialize when DOM is loaded document.addEventListener('DOMContentLoaded', async () => { await checkAuth(); await loadShifts(); await loadMySignups(); setupEventListeners(); // Add clear filters button handler const clearBtn = document.getElementById('clear-filters-btn'); if (clearBtn) { clearBtn.addEventListener('click', clearFilters); } }); async function checkAuth() { try { const response = await fetch('/api/auth/check'); const data = await response.json(); if (!data.authenticated) { window.location.href = '/login.html'; return; } currentUser = data.user; document.getElementById('user-email').textContent = currentUser.email; // Add admin link if user is admin if (currentUser.isAdmin) { const headerActions = document.querySelector('.header-actions'); const adminLink = document.createElement('a'); adminLink.href = '/admin.html#shifts'; adminLink.className = 'btn btn-secondary'; adminLink.textContent = '⚙️ Manage Shifts'; headerActions.insertBefore(adminLink, headerActions.firstChild); } } catch (error) { console.error('Auth check failed:', error); window.location.href = '/login.html'; } } async function loadShifts() { try { const response = await fetch('/api/shifts'); const data = await response.json(); if (data.success) { allShifts = data.shifts; displayShifts(allShifts); } } catch (error) { showStatus('Failed to load shifts', 'error'); } } async function loadMySignups() { try { const response = await fetch('/api/shifts/my-signups'); const data = await response.json(); if (data.success) { mySignups = data.signups; displayMySignups(); } else { // Still display empty signups if the endpoint fails mySignups = []; displayMySignups(); } } catch (error) { console.error('Failed to load signups:', error); // Don't show error to user, just display empty signups mySignups = []; displayMySignups(); } } function displayShifts(shifts) { const grid = document.getElementById('shifts-grid'); if (shifts.length === 0) { grid.innerHTML = '

No shifts available at this time.

'; return; } grid.innerHTML = shifts.map(shift => { const shiftDate = new Date(shift.Date); const isSignedUp = mySignups.some(s => s.shift_id === shift.ID); const isFull = shift['Current Volunteers'] >= shift['Max Volunteers']; return `

${escapeHtml(shift.Title)}

📅 ${shiftDate.toLocaleDateString()}

⏰ ${shift['Start Time']} - ${shift['End Time']}

📍 ${escapeHtml(shift.Location || 'TBD')}

👥 ${shift['Current Volunteers']}/${shift['Max Volunteers']} volunteers

${shift.Description ? `
${escapeHtml(shift.Description)}
` : ''}
${isSignedUp ? `` : isFull ? '' : `` }
`; }).join(''); // Add event listeners after rendering setupShiftCardListeners(); } function displayMySignups() { const list = document.getElementById('my-signups-list'); if (mySignups.length === 0) { list.innerHTML = '

You haven\'t signed up for any shifts yet.

'; return; } // Need to match signups with shift details const signupsWithDetails = mySignups.map(signup => { const shift = allShifts.find(s => s.ID === signup.shift_id); return { ...signup, shift }; }).filter(s => s.shift); list.innerHTML = signupsWithDetails.map(signup => { const shiftDate = new Date(signup.shift.Date); return `

${escapeHtml(signup.shift.Title)}

📅 ${shiftDate.toLocaleDateString()} ⏰ ${signup.shift['Start Time']} - ${signup.shift['End Time']}

`; }).join(''); // Add event listeners after rendering setupMySignupsListeners(); } // New function to setup listeners for shift cards function setupShiftCardListeners() { const grid = document.getElementById('shifts-grid'); if (!grid) return; // Remove any existing listeners by cloning const newGrid = grid.cloneNode(true); grid.parentNode.replaceChild(newGrid, grid); // Add click listener for signup buttons newGrid.addEventListener('click', async (e) => { if (e.target.classList.contains('signup-btn')) { const shiftId = e.target.getAttribute('data-shift-id'); await signupForShift(shiftId); } else if (e.target.classList.contains('cancel-signup-btn')) { const shiftId = e.target.getAttribute('data-shift-id'); await cancelSignup(shiftId); } }); } // New function to setup listeners for my signups function setupMySignupsListeners() { const list = document.getElementById('my-signups-list'); if (!list) return; // Remove any existing listeners by cloning const newList = list.cloneNode(true); list.parentNode.replaceChild(newList, list); // Add click listener for cancel buttons newList.addEventListener('click', async (e) => { if (e.target.classList.contains('cancel-signup-btn')) { const shiftId = e.target.getAttribute('data-shift-id'); await cancelSignup(shiftId); } }); } async function signupForShift(shiftId) { try { const response = await fetch(`/api/shifts/${shiftId}/signup`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.success) { showStatus('Successfully signed up for shift!', 'success'); await loadShifts(); await loadMySignups(); } else { showStatus(data.error || 'Failed to sign up', 'error'); } } catch (error) { console.error('Error signing up:', error); showStatus('Failed to sign up for shift', 'error'); } } async function cancelSignup(shiftId) { if (!confirm('Are you sure you want to cancel your signup for this shift?')) { return; } try { const response = await fetch(`/api/shifts/${shiftId}/cancel`, { method: 'POST', headers: { 'Content-Type': 'application/json' } }); const data = await response.json(); if (data.success) { showStatus('Signup cancelled', 'success'); await loadShifts(); await loadMySignups(); } else { showStatus(data.error || 'Failed to cancel signup', 'error'); } } catch (error) { console.error('Error cancelling signup:', error); showStatus('Failed to cancel signup', 'error'); } } function setupEventListeners() { const dateFilter = document.getElementById('date-filter'); if (dateFilter) { dateFilter.addEventListener('change', filterShifts); } } function filterShifts() { const dateFilter = document.getElementById('date-filter').value; if (!dateFilter) { displayShifts(allShifts); return; } const filtered = allShifts.filter(shift => { return shift.Date === dateFilter; // Changed from shift.date to shift.Date }); displayShifts(filtered); } function clearFilters() { document.getElementById('date-filter').value = ''; loadShifts(); // Reload shifts without filters } function showStatus(message, type = 'info') { const container = document.getElementById('status-container'); if (!container) return; const messageDiv = document.createElement('div'); messageDiv.className = `status-message ${type}`; messageDiv.textContent = message; container.appendChild(messageDiv); setTimeout(() => { messageDiv.remove(); }, 5000); } function escapeHtml(text) { if (text === null || text === undefined) { return ''; } const div = document.createElement('div'); div.textContent = String(text); return div.innerHTML; }