// Student dashboard functionality let items = []; // Check authentication function checkAuth() { const token = localStorage.getItem('token'); const role = localStorage.getItem('userRole'); if (!token || role !== 'student') { window.location.href = '/index.html'; } } // Initialize page async function initializePage() { checkAuth(); await loadItems(); setupEventListeners(); displayUserInfo(); initializeModal(); startAutoRefresh(); } // Reload content when language changes function reloadContent() { displayItems(); loadMyReservations(); } // Make reloadContent available globally for translation manager window.reloadContent = reloadContent; // Display user info function displayUserInfo() { const username = localStorage.getItem('username'); document.getElementById('userInfo').textContent = `Student: ${username}`; } // Load items from server async function loadItems() { try { const response = await fetch('/api/items', { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); items = await response.json(); displayItems(); } catch (error) { console.error('Error loading items:', error); alert('Kon artikelen niet laden'); } } let itemDetailsModal = null; let currentItem = null; // Initialize Bootstrap modal function initializeModal() { const modalElement = document.getElementById('itemDetailsModal'); itemDetailsModal = new bootstrap.Modal(modalElement); // Set up modal reserve button document.getElementById('modalReserveButton').addEventListener('click', () => { if (currentItem) { const quantity = parseInt(document.getElementById('reserveQuantity').value); reserveItem(currentItem._id, quantity); } }); } // Show item details in modal function showItemDetails(item) { currentItem = item; const availableQuantity = item.quantity - (item.reserved || 0); // Set modal content document.getElementById('modalItemImage').src = item.imageUrl || '/images/default-item.png'; document.getElementById('modalItemName').textContent = item.name; document.getElementById('modalItemDescription').textContent = item.description || 'No description available'; document.getElementById('modalItemLocation').textContent = item.location; document.getElementById('modalItemQuantity').textContent = availableQuantity; // Populate quantity select const quantitySelect = document.getElementById('reserveQuantity'); quantitySelect.innerHTML = ''; for (let i = 1; i <= availableQuantity; i++) { const option = document.createElement('option'); option.value = i; option.textContent = i; quantitySelect.appendChild(option); } // Show/hide reserve button and quantity select based on availability const reserveButton = document.getElementById('modalReserveButton'); const quantityGroup = document.getElementById('quantitySelectGroup'); if (availableQuantity > 0) { reserveButton.style.display = 'block'; quantityGroup.style.display = 'block'; reserveButton.disabled = false; } else { reserveButton.style.display = 'none'; quantityGroup.style.display = 'none'; } itemDetailsModal.show(); } // Track current view mode let currentViewMode = localStorage.getItem('studentViewMode') || 'grid'; // Display items based on current view mode function displayItems() { const locationFilter = document.getElementById('locationFilter').value; const searchTerm = document.getElementById('searchInput').value.toLowerCase(); let filteredItems = items; // Apply location filter if (locationFilter !== 'all') { filteredItems = filteredItems.filter(item => item.location === locationFilter); } // Apply search filter with translation support if (searchTerm.trim() !== '') { filteredItems = filteredItems.filter(item => { const translationManager = window.ensureTranslationManager ? window.ensureTranslationManager() : null; if (translationManager) { const localizedItem = translationManager.getLocalizedItem(item); return localizedItem.name.toLowerCase().includes(searchTerm) || (localizedItem.description && localizedItem.description.toLowerCase().includes(searchTerm)); } else if (window.getItemDisplayText) { const currentLang = localStorage.getItem('language') || 'nl'; const name = window.getItemDisplayText(item, 'name', currentLang); const description = window.getItemDisplayText(item, 'description', currentLang); return name.toLowerCase().includes(searchTerm) || description.toLowerCase().includes(searchTerm); } else { // Fallback for when translation manager isn't loaded yet (default to Dutch) const name = item.name?.nl || item.name?.en || item.name || ''; const description = item.description?.nl || item.description?.en || item.description || ''; return name.toLowerCase().includes(searchTerm) || description.toLowerCase().includes(searchTerm); } }); } // Update view mode buttons active state const viewButtons = document.querySelectorAll('.view-mode-btn'); viewButtons.forEach(btn => { btn.classList.toggle('active', btn.getAttribute('data-mode') === currentViewMode); }); // Show/hide appropriate containers document.getElementById('itemsGrid').classList.toggle('d-none', currentViewMode !== 'grid'); document.getElementById('itemsList').classList.toggle('d-none', currentViewMode !== 'list'); if (currentViewMode === 'grid') { // Display items in grid view const gridContainer = document.getElementById('itemsGrid'); gridContainer.innerHTML = filteredItems.map(item => { // Use multiple fallback strategies const translationManager = window.ensureTranslationManager ? window.ensureTranslationManager() : null; let localizedItem; if (translationManager) { localizedItem = translationManager.getLocalizedItem(item); } else if (window.getItemDisplayText) { // Use debug helper fallback const currentLang = localStorage.getItem('language') || 'nl'; localizedItem = { ...item, name: window.getItemDisplayText(item, 'name', currentLang), description: window.getItemDisplayText(item, 'description', currentLang) }; } else { // Final fallback localizedItem = { ...item, name: (typeof item.name === 'object') ? (item.name?.nl || item.name?.en || 'Onbekend Artikel') : (item.name || 'Onbekend Artikel'), description: (typeof item.description === 'object') ? (item.description?.nl || item.description?.en || 'Geen beschrijving beschikbaar') : (item.description || 'Geen beschrijving beschikbaar') }; } return `
${localizedItem.name}
${localizedItem.name}

${localizedItem.description || 'No description available'}

Location: ${item.location}
Available: ${item.quantity - (item.reserved || 0)}

${item.quantity - (item.reserved || 0) > 0 ? 'Available' : 'Not Available' }
`; }).join(''); } else { // Display items in list view const itemsListBody = document.getElementById('itemsListBody'); itemsListBody.innerHTML = filteredItems.map(item => { // Use multiple fallback strategies const translationManager = window.ensureTranslationManager ? window.ensureTranslationManager() : null; let localizedItem; if (translationManager) { localizedItem = translationManager.getLocalizedItem(item); } else if (window.getItemDisplayText) { // Use debug helper fallback const currentLang = localStorage.getItem('language') || 'nl'; localizedItem = { ...item, name: window.getItemDisplayText(item, 'name', currentLang), description: window.getItemDisplayText(item, 'description', currentLang) }; } else { // Final fallback localizedItem = { ...item, name: (typeof item.name === 'object') ? (item.name?.nl || item.name?.en || 'Onbekend Artikel') : (item.name || 'Onbekend Artikel'), description: (typeof item.description === 'object') ? (item.description?.nl || item.description?.en || 'Geen beschrijving beschikbaar') : (item.description || 'Geen beschrijving beschikbaar') }; } return ` ${localizedItem.name} ${localizedItem.name} ${localizedItem.description || 'No description available'} ${item.location} ${item.quantity - (item.reserved || 0)} ${item.quantity - (item.reserved || 0) > 0 ? 'Available' : 'Not Available' } `; }).join(''); } } // Load user's reservations async function loadMyReservations() { try { const response = await fetch('/api/reservations/my', { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); myReservations = await response.json(); displayMyReservations(); } catch (error) { console.error('Error loading reservations:', error); alert('Kon reserveringen niet laden'); } } // Display user's reservations function displayMyReservations() { const reservationsList = document.getElementById('reservationsList'); reservationsList.innerHTML = myReservations.map(reservation => ` ${reservation.itemName} ${reservation.location} ${new Date(reservation.reservedDate).toLocaleDateString()} ${reservation.status} `).join(''); } // Reserve an item async function reserveItem(itemId, quantity = 1) { try { const response = await fetch('/api/reservations', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${localStorage.getItem('token')}` }, body: JSON.stringify({ itemId, quantity }) }); if (response.ok) { await loadItems(); itemDetailsModal.hide(); // Redirect to reservations page after successful reservation window.location.href = '/student-reservations.html'; } else { const error = await response.json(); alert(error.message || 'Kon artikel niet reserveren'); } } catch (error) { console.error('Error reserving item:', error); alert('Kon artikel niet reserveren'); } } // Switch view mode function switchViewMode(mode) { currentViewMode = mode; localStorage.setItem('studentViewMode', mode); displayItems(); } // Set up event listeners function setupEventListeners() { document.getElementById('locationFilter').addEventListener('change', displayItems); document.getElementById('logoutBtn').addEventListener('click', () => { localStorage.clear(); window.location.href = '/index.html'; }); // Search functionality const searchInput = document.getElementById('searchInput'); const clearSearch = document.getElementById('clearSearch'); searchInput.addEventListener('input', displayItems); searchInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { displayItems(); } }); clearSearch.addEventListener('click', () => { searchInput.value = ''; displayItems(); searchInput.focus(); }); // View mode toggle listeners document.querySelectorAll('.view-mode-btn').forEach(btn => { btn.addEventListener('click', () => switchViewMode(btn.getAttribute('data-mode'))); }); } // Auto refresh functionality let refreshInterval; let lastItemsChecksum = ''; function startAutoRefresh() { // Refresh every 30 seconds refreshInterval = setInterval(async () => { await checkForUpdates(); }, 30000); } function stopAutoRefresh() { if (refreshInterval) { clearInterval(refreshInterval); } } async function checkForUpdates() { try { const response = await fetch('/api/items', { headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } }); const currentItems = await response.json(); // Create a simple checksum of the items data const currentChecksum = JSON.stringify(currentItems.map(item => ({ id: item._id, quantity: item.quantity, reserved: item.reserved || 0 }))); // If items changed, refresh the display if (lastItemsChecksum && currentChecksum !== lastItemsChecksum) { items = currentItems; displayItems(); // Show update notification showUpdateNotification(); } lastItemsChecksum = currentChecksum; } catch (error) { console.error('Error checking for updates:', error); } } function showUpdateNotification() { const notification = document.createElement('div'); notification.className = 'alert alert-info alert-dismissible fade show'; notification.innerHTML = ` Items updated! `; const container = document.querySelector('.container'); container.prepend(notification); setTimeout(() => notification.remove(), 3000); } // Initialize the page when DOM is loaded document.addEventListener('DOMContentLoaded', initializePage);