From aa2a0133b2ccd8d85bfa931e1748fa2542276af7 Mon Sep 17 00:00:00 2001 From: Tomas Dvorak Date: Fri, 13 Jun 2025 15:14:46 +0200 Subject: [PATCH] test --- rezervace-aut.html | 442 ++++++++++++++------------------------------- 1 file changed, 134 insertions(+), 308 deletions(-) diff --git a/rezervace-aut.html b/rezervace-aut.html index c5de475..ea50bf9 100644 --- a/rezervace-aut.html +++ b/rezervace-aut.html @@ -209,16 +209,14 @@ .fc-event-title { font-weight: 500; font-size: 0.875rem; - } - - /* Enhanced calendar event styles */ + } /* Enhanced calendar event styles */ .fc-event { border: none !important; border-radius: 6px !important; padding: 4px 6px !important; box-shadow: 0 2px 4px rgba(0,0,0,0.1) !important; margin: 2px 0 !important; - background: white !important; + color: white !important; } .fc-event-title { @@ -229,32 +227,29 @@ .fc-event-time { font-weight: 600 !important; opacity: 0.8 !important; - } - - /* Vehicle-specific event colors */ - .event-vw-caddy { - border-left: 4px solid #1a73e8 !important; - background: #e6f3ff !important; + } /* Vehicle-specific event colors */ + .event-vw-caddy---4z1-8241 { + background-color: rgb(59, 130, 246) !important; /* blue-500 */ } - .event-vw-golf { - border-left: 4px solid #28a745 !important; - background: #e6ffe6 !important; + .event-vw-golf---5z5-8694 { + background-color: rgb(34, 197, 94) !important; /* green-500 */ } - .event-skoda-fabia { - border-left: 4px solid #fd7e14 !important; - background: #fff3e6 !important; + .event-skoda-fabia---1z3-5789 { + background-color: rgb(249, 115, 22) !important; /* orange-500 */ } - .event-bmw-218d { - border-left: 4px solid #6f42c1 !important; - background: #f3e6ff !important; + .event-bmw-218d---6z5-4739 { + background-color: rgb(168, 85, 247) !important; /* purple-500 */ } - .event-skoda-superb { - border-left: 4px solid #dc3545 !important; - background: #ffe6e6 !important; + .event-bmw-218d---6z5-4740 { + background-color: rgb(99, 102, 241) !important; /* indigo-500 */ + } + + .event-skoda-superb---2by-2398 { + background-color: rgb(239, 68, 68) !important; /* red-500 */ } /* Reservation list styles */ @@ -640,6 +635,37 @@
+
+

Přehled vozidel

+
+
+
+ VW Caddy - 4Z1 8241 +
+
+
+ VW Golf - 5Z5 8694 +
+
+
+ Škoda Fabia - 1Z3 5789 +
+
+
+ BMW 218d - 6Z5 4739 +
+
+
+ BMW 218d - 6Z5 4740 +
+
+
+ Škoda Superb - 2BY 2398 +
+
+
+ +
@@ -687,13 +713,13 @@
- + + + + + +
@@ -1071,306 +1097,106 @@ const events = calendar.getEvents(); // Sort events by start date - events.sort((a, b) => a.start - b.start); - - // Filter future events - const futureEvents = events.filter(event => event.start >= new Date()); + const now = new Date(); + const futureEvents = events + .filter(event => event.start >= now) + .sort((a, b) => a.start.getTime() - b.start.getTime()); if (futureEvents.length === 0) { - reservationsList.innerHTML = '
Žádné nadcházející rezervace
'; + reservationsList.innerHTML = '
Žádné nadcházející rezervace
'; return; } - reservationsList.innerHTML = futureEvents.map(event => { + const html = futureEvents.map(event => { const vehicleClass = 'event-' + event.extendedProps.vehicle.toLowerCase().replace(/\s+/g, '-'); + const startDate = formatDateTime(event.start); + const endDate = formatDateTime(event.end); + return ` -
-
- ${event.extendedProps.vehicle} -
-
-
${event.extendedProps.driverName}
-
- ${formatDateTime(event.start)} - ${formatDateTime(event.end)} +
+
+
+
+
${event.extendedProps.driverName}
+
${event.extendedProps.vehicle}
+
+
+ ${startDate} - ${endDate}
-
-
- ${event.extendedProps.purpose || 'Bez účelu'}
`; }).join(''); + + reservationsList.innerHTML = html; } - // Update the eventContent function to add vehicle-specific styling - // (Already defined in calendarConfig above, so this duplicate is removed) + // Enhanced date/time formatting function + function formatDateTime(date) { + const options = { + day: '2-digit', + month: '2-digit', + hour: '2-digit', + minute: '2-digit', + hour12: false + }; + return new Date(date).toLocaleString('cs-CZ', options); + } - // Call updateReservationsList when events change + // Function to check for high traffic + async function checkHighTraffic(vehicle, date) { + if (!vehicle || !date) return; + + const startOfDay = new Date(date); + startOfDay.setHours(0, 0, 0, 0); + + const endOfDay = new Date(date); + endOfDay.setHours(23, 59, 59, 999); + + const events = calendar.getEvents(); + const vehicleEventsCount = events.filter(event => + event.extendedProps.vehicle === vehicle && + event.start >= startOfDay && + event.start <= endOfDay + ).length; + + const warningEl = document.getElementById('highTrafficWarning'); + if (vehicleEventsCount >= 3) { + warningEl.querySelector('.warning-message').textContent = + `Toto vozidlo má v daný den již ${vehicleEventsCount} rezervací.`; + warningEl.classList.remove('hidden'); + } else { + warningEl.classList.add('hidden'); + } + + return vehicleEventsCount; + } + + // Add event listeners for high traffic checking + document.getElementById('vehicle').addEventListener('change', function() { + const startDate = document.getElementById('startDate').value; + if (startDate) { + checkHighTraffic(this.value, new Date(startDate)); + } + }); + + document.getElementById('startDate').addEventListener('change', function() { + const vehicle = document.getElementById('vehicle').value; + if (vehicle) { + checkHighTraffic(vehicle, new Date(this.value)); + } + }); + + // Update reservations list when calendar events change calendar.on('eventAdd', updateReservationsList); calendar.on('eventRemove', updateReservationsList); calendar.on('eventChange', updateReservationsList); // Initial update of reservations list + calendar.on('eventSourceSuccess', updateReservationsList); + + // Update initial state updateReservationsList(); - - // Vehicle select change handler - document.getElementById('vehicle').addEventListener('change', async function() { - const startDate = document.getElementById('startDate').value; - const startTime = document.getElementById('startTime').value; - const endDate = document.getElementById('endDate').value; - const endTime = document.getElementById('endTime').value; - - if (startDate && startTime && endDate && endTime) { - await checkVehicleAvailability(this.value, startDate, endDate); - } - }); - - // Check vehicle availability - async function checkVehicleAvailability(vehicle, startDate, endDate) { - try { - // Format dates for API - const startDateTime = new Date(startDate); - const endDateTime = new Date(endDate); - - const params = new URLSearchParams({ - vehicle: vehicle, - startDate: startDateTime.toISOString().split('T')[0], - startTime: startDateTime.toTimeString().split(' ')[0].slice(0, 5), - endDate: endDateTime.toISOString().split('T')[0], - endTime: endDateTime.toTimeString().split(' ')[0].slice(0, 5) - }); - - const response = await fetch(`/api/check-availability?${params}`); - if (!response.ok) { - throw new Error('Failed to check availability'); - } - - const data = await response.json(); - return data.available; - } catch (error) { - console.error('Error checking availability:', error); - throw new Error('Could not verify vehicle availability'); - } - } - - // Show status message function - function showMessage(text, type) { - const statusContainer = document.getElementById('statusMessage'); - if (!statusContainer) { - console.error('Status message container not found'); - return; - } - - statusContainer.className = 'mt-4 p-4 rounded-md'; - statusContainer.classList.remove('hidden'); - - switch (type) { - case 'success': - statusContainer.classList.add('bg-green-100', 'text-green-700'); - break; - case 'error': - statusContainer.classList.add('bg-red-100', 'text-red-700'); - break; - case 'info': - statusContainer.classList.add('bg-blue-100', 'text-blue-700'); - break; - } - - statusContainer.textContent = text; - - // Auto hide after 5 seconds - setTimeout(() => { - statusContainer.classList.add('hidden'); - }, 5000); - } - - // Handle form submission - reservationForm.addEventListener('submit', async function(e) { - e.preventDefault(); - - const startDate = document.getElementById('startDate').value; - const startTime = document.getElementById('startTime').value; - const endDate = document.getElementById('endDate').value; - const endTime = document.getElementById('endTime').value; - - // Create ISO datetime strings - const startDateTime = new Date(`${startDate}T${startTime}`); - const endDateTime = new Date(`${endDate}T${endTime}`); - - // Validate dates - if (endDateTime <= startDateTime) { - showMessage('Konec musí být později než začátek', 'error'); - return; - } - - // Check vehicle availability - const vehicle = document.getElementById('vehicle').value; - const isAvailable = await checkVehicleAvailability(vehicle, startDateTime, endDateTime); - - if (!isAvailable) { - showMessage('Vozidlo není v tomto čase dostupné', 'error'); - return; - } - - // Prepare reservation data - const reservationData = { - driverName: document.getElementById('driverName').value, - vehicle: vehicle, - startDate: startDate, - startTime: startTime, - endDate: endDate, - endTime: endTime, - purpose: document.getElementById('purpose').value - }; - - try { - const response = await fetch('/api/reservations', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify(reservationData) - }); - - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.message || 'Failed to create reservation'); - } - - showMessage('Rezervace byla úspěšně vytvořena', 'success'); - reservationForm.reset(); - calendar.refetchEvents(); - } catch (error) { - console.error('Error:', error); - showMessage(error.message || 'Chyba při vytváření rezervace', 'error'); - } - }); - - // Populate time dropdowns with full hours - function populateTimeDropdowns() { - const timeSelects = [document.getElementById('startTime'), document.getElementById('endTime')]; - - for (let hour = 6; hour <= 22; hour++) { // 6:00 to 22:00 - const hourStr = hour.toString().padStart(2, '0'); - const timeStr = `${hourStr}:00`; - const option = new Option(timeStr, timeStr); - - timeSelects.forEach(select => { - select.appendChild(option.cloneNode(true)); - }); - } - } - - // Event modal functions - function showEventModal(event) { - const startDate = new Date(event.start); - const endDate = new Date(event.end); - - document.getElementById('modalDriver').textContent = event.extendedProps.driverName; - document.getElementById('modalVehicle').textContent = event.extendedProps.vehicle; - document.getElementById('modalStart').textContent = formatDateTime(startDate); - document.getElementById('modalEnd').textContent = formatDateTime(endDate); - document.getElementById('modalPurpose').textContent = event.extendedProps.purpose || '(není uvedeno)'; - - // Show delete button only for user's own reservations - // You might want to add user authentication here - const deleteBtn = document.getElementById('deleteReservation'); - deleteBtn.classList.remove('hidden'); - - modal.style.display = 'block'; - } - - function formatDateTime(date) { - return date.toLocaleString('cs-CZ', { - day: 'numeric', - month: 'long', - year: 'numeric', - hour: '2-digit', - minute: '2-digit' - }); - } - - // Close modal when clicking the close button or outside - document.querySelector('.modal-close').onclick = function() { - modal.style.display = 'none'; - } - - window.onclick = function(event) { - if (event.target == modal) { - modal.style.display = 'none'; - } - } - - // Delete reservation handler - document.getElementById('deleteReservation').onclick = async function() { - if (!currentEventId) return; - - if (confirm('Opravdu chcete zrušit tuto rezervaci?')) { - try { - const response = await fetch(`/api/reservations/${currentEventId}`, { - method: 'DELETE' - }); - - if (!response.ok) throw new Error('Failed to delete reservation'); - - calendar.getEventById(currentEventId).remove(); - modal.style.display = 'none'; - showMessage('Rezervace byla úspěšně zrušena', 'success'); - } catch (error) { - console.error('Error:', error); - showMessage('Nepodařilo se zrušit rezervaci', 'error'); - } - } - } - - // Initialize time dropdowns when page loads - document.addEventListener('DOMContentLoaded', function() { - populateTimeDropdowns(); - - // Set default dates to today - const today = new Date(); - const dateStr = today.toISOString().split('T')[0]; - document.getElementById('startDate').value = dateStr; - document.getElementById('endDate').value = dateStr; - }); - - // New reservation button handler - document.getElementById('newReservationBtn').addEventListener('click', function() { - // Set default date and time to current time rounded to next hour - const now = new Date(); - now.setMinutes(0); - now.setHours(now.getHours() + 1); - - const endDate = new Date(now); - endDate.setHours(endDate.getHours() + 1); - - // Format dates for the form - const formattedDate = now.getFullYear() + '-' + - String(now.getMonth() + 1).padStart(2, '0') + '-' + - String(now.getDate()).padStart(2, '0'); - const formattedTime = String(now.getHours()).padStart(2, '0') + ':00'; - const formattedEndTime = String(endDate.getHours()).padStart(2, '0') + ':00'; - - // Set the form values - document.getElementById('startDate').value = formattedDate; - document.getElementById('startTime').value = formattedTime; - document.getElementById('endDate').value = formattedDate; - document.getElementById('endTime').value = formattedEndTime; - - // Show the modal - reservationModal.style.display = 'block'; - }); - - // Initialize time dropdowns when page loads - document.addEventListener('DOMContentLoaded', function() { - populateTimeDropdowns(); - - // Set default dates to today - const today = new Date(); - const dateStr = today.toISOString().split('T')[0]; - document.getElementById('startDate').value = dateStr; - document.getElementById('endDate').value = dateStr; - }); });