This commit is contained in:
Tomas Dvorak
2025-06-11 22:17:58 +02:00
parent 56488e2919
commit 3cd83b9e24
+160 -54
View File
@@ -1252,6 +1252,57 @@
</div> </div>
</div> </div>
<!-- Reservations Management Section -->
<div class="card" style="margin: 2rem auto; max-width: 1200px;">
<h3>Správa rezervací vozidel</h3>
<!-- Filters -->
<div class="mb-6 bg-gray-50 p-4 rounded-lg">
<div class="grid grid-cols-1 md:grid-cols-3 gap-4 mb-4">
<div>
<label for="vehicleFilter" class="block text-sm font-medium text-gray-700 mb-1">Filtrovat dle vozidla:</label>
<select id="vehicleFilter" class="form-control w-full">
<option value="">Všechna vozidla</option>
<!-- Vehicle options will be populated by JavaScript -->
</select>
</div>
<div>
<label for="dateFilter" class="block text-sm font-medium text-gray-700 mb-1">Filtrovat dle data:</label>
<input type="date" id="dateFilter" class="form-control w-full">
</div>
<div class="flex items-end">
<button id="exportButton" class="btn btn-primary w-full">
<i class="fas fa-file-export mr-2"></i>Exportovat do Excelu
</button>
</div>
</div>
</div>
<!-- Reservations Table -->
<div class="overflow-x-auto">
<table id="reservationsTable" class="min-w-full divide-y divide-gray-200">
<thead class="bg-gray-50">
<tr>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Řidič</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Vozidlo</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Od</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Do</th>
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Účel</th>
<th scope="col" class="px-6 py-3 text-right text-xs font-medium text-gray-500 uppercase tracking-wider">Akce</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<!-- Rows will be populated by JavaScript -->
<tr>
<td colspan="6" class="px-6 py-4 text-center text-gray-500">
Načítám data o rezervacích...
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Icon Picker Modal --> <!-- Icon Picker Modal -->
<div id="iconPickerModal" class="fixed inset-0 z-50 hidden"> <div id="iconPickerModal" class="fixed inset-0 z-50 hidden">
<div id="iconPickerContainer" class="bg-white rounded-xl shadow-2xl overflow-hidden flex flex-col"> <div id="iconPickerContainer" class="bg-white rounded-xl shadow-2xl overflow-hidden flex flex-col">
@@ -4314,38 +4365,34 @@ function displayReservations(reservations) {
return; return;
} }
tbody.innerHTML = reservations.map(res => { // Format date and time as DD.MM.YYYY HH:MM
const startDate = new Date(res.start); const formatDateTime = (dateString) => {
const endDate = new Date(res.end); const date = new Date(dateString);
const day = String(date.getDate()).padStart(2, '0');
// Format date as DD.MM.YYYY const month = String(date.getMonth() + 1).padStart(2, '0');
const formatDate = (date) => { const year = date.getFullYear();
const day = String(date.getDate()).padStart(2, '0'); const hours = String(date.getHours()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0'); const minutes = String(date.getMinutes()).padStart(2, '0');
const year = date.getFullYear(); return `${day}.${month}.${year} ${hours}:${minutes}`;
return `${day}.${month}.${year}`; };
};
tbody.innerHTML = reservations.map(res => `
// Format time as HH:MM <tr class="hover:bg-gray-50">
const formatTime = (date) => { <td class="px-6 py-4">${res.driverName || '-'}</td>
const hours = String(date.getHours()).padStart(2, '0'); <td class="px-6 py-4">${res.vehicle || '-'}</td>
const minutes = String(date.getMinutes()).padStart(2, '0'); <td class="px-6 py-4 whitespace-nowrap">${formatDateTime(res.start)}</td>
return `${hours}:${minutes}`; <td class="px-6 py-4 whitespace-nowrap">${formatDateTime(res.end)}</td>
}; <td class="px-6 py-4">${res.purpose || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap">
return ` <button onclick="editReservation('${res.id}')" class="text-blue-600 hover:text-blue-900 mr-3">
<tr class="hover:bg-gray-50"> <i class="fas fa-edit"></i> Upravit
<td class="px-6 py-4">${res.driverName || '-'}</td> </button>
<td class="px-6 py-4">${res.vehicle || '-'}</td> <button onclick="deleteReservation('${res.id}')" class="text-red-600 hover:text-red-900">
<td class="px-6 py-4 whitespace-nowrap">${formatDate(startDate)}</td> <i class="fas fa-trash"></i> Smazat
<td class="px-6 py-4 whitespace-nowrap">${formatTime(startDate)}</td> </button>
<td class="px-6 py-4 whitespace-nowrap">${formatDate(endDate)}</td> </td>
<td class="px-6 py-4 whitespace-nowrap">${formatTime(endDate)}</td> </tr>
<td class="px-6 py-4">${res.purpose || '-'}</td> `).join('');
<td class="px-6 py-4 whitespace-nowrap">${calculateDuration(res)}</td>
</tr>
`;
}).join('');
} }
// Function to filter reservations // Function to filter reservations
@@ -4379,39 +4426,98 @@ function exportReservations() {
const vehicleFilter = document.getElementById('vehicleFilter').value; const vehicleFilter = document.getElementById('vehicleFilter').value;
const dateFilter = document.getElementById('dateFilter').value; const dateFilter = document.getElementById('dateFilter').value;
let dataToExport = window.allReservations; let dataToExport = [...window.allReservations];
// Apply filters if set
if (vehicleFilter) { if (vehicleFilter) {
dataToExport = dataToExport.filter(res => res.vehicle === vehicleFilter); dataToExport = dataToExport.filter(res => res.vehicle === vehicleFilter);
} }
if (dateFilter) { if (dateFilter) {
dataToExport = dataToExport.filter(res => res.startDate === dateFilter); dataToExport = dataToExport.filter(res => {
const resDate = new Date(res.start).toISOString().split('T')[0];
return resDate === dateFilter;
});
} }
// Create CSV content // Sort by start date
const headers = ['Řidič', 'Vozidlo', 'Datum od', 'Čas od', 'Datum do', 'Čas do', 'Účel', 'Doba trvání']; dataToExport.sort((a, b) => new Date(a.start) - new Date(b.start));
const csvContent = [
headers.join(','),
...dataToExport.map(res => [
`"${res.driverName}"`,
`"${res.vehicle}"`,
res.startDate,
res.startTime,
res.endDate,
res.endTime,
`"${res.purpose || ''}"`,
`"${calculateDuration(res)}"`
].join(','))
].join('\n');
// Create and trigger download // Format date as DD.MM.YYYY
const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' }); const formatDate = (dateString) => {
const date = new Date(dateString);
const day = String(date.getDate()).padStart(2, '0');
const month = String(date.getMonth() + 1).padStart(2, '0');
const year = date.getFullYear();
return `${day}.${month}.${year}`;
};
// Format time as HH:MM
const formatTime = (dateString) => {
const date = new Date(dateString);
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${hours}:${minutes}`;
};
// Format date and time for Excel (YYYY-MM-DD HH:MM)
const excelDateTime = (dateString) => {
const date = new Date(dateString);
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${year}-${month}-${day} ${hours}:${minutes}`;
};
// Create CSV content with semicolon as delimiter for better Excel compatibility
const headers = [
'Řidič',
'Vozidlo',
'Začátek rezervace',
'Konec rezervace',
'Doba trvání',
'Účel cesty'
];
const csvContent = [
headers.join(';'),
...dataToExport.map(res => {
const start = new Date(res.start);
const end = new Date(res.end);
return [
`"${res.driverName || 'Neznámý řidič'}"`,
`"${res.vehicle || 'Neznámé vozidlo'}"`,
`"${excelDateTime(start)}"`,
`"${excelDateTime(end)}"`,
`"${calculateDuration(res)}"`,
`"${res.purpose || 'Nespecifikováno'}"`
].join(';');
})
].join('\r\n');
// Create and trigger download with proper encoding for Excel
const blob = new Blob([
'\ufeff', // UTF-8 BOM for Excel
csvContent
], {
type: 'text/csv;charset=utf-8;'
});
const link = document.createElement('a'); const link = document.createElement('a');
const date = new Date().toISOString().split('T')[0]; const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
link.href = URL.createObjectURL(blob); link.href = URL.createObjectURL(blob);
link.download = `rezervace_${date}.csv`; link.download = `rezervace_${timestamp}.csv`;
link.style.display = 'none';
document.body.appendChild(link); document.body.appendChild(link);
link.click(); link.click();
document.body.removeChild(link);
// Clean up
setTimeout(() => {
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
}, 100);
} }
// Helper function to format date and time // Helper function to format date and time