This commit is contained in:
Tomas Dvorak
2025-06-11 22:17:58 +02:00
parent 56488e2919
commit 3cd83b9e24
+159 -53
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');
const month = String(date.getMonth() + 1).padStart(2, '0');
const year = date.getFullYear();
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
return `${day}.${month}.${year} ${hours}:${minutes}`;
};
// Format date as DD.MM.YYYY tbody.innerHTML = reservations.map(res => `
const formatDate = (date) => { <tr class="hover:bg-gray-50">
const day = String(date.getDate()).padStart(2, '0'); <td class="px-6 py-4">${res.driverName || '-'}</td>
const month = String(date.getMonth() + 1).padStart(2, '0'); <td class="px-6 py-4">${res.vehicle || '-'}</td>
const year = date.getFullYear(); <td class="px-6 py-4 whitespace-nowrap">${formatDateTime(res.start)}</td>
return `${day}.${month}.${year}`; <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">
// Format time as HH:MM <button onclick="editReservation('${res.id}')" class="text-blue-600 hover:text-blue-900 mr-3">
const formatTime = (date) => { <i class="fas fa-edit"></i> Upravit
const hours = String(date.getHours()).padStart(2, '0'); </button>
const minutes = String(date.getMinutes()).padStart(2, '0'); <button onclick="deleteReservation('${res.id}')" class="text-red-600 hover:text-red-900">
return `${hours}:${minutes}`; <i class="fas fa-trash"></i> Smazat
}; </button>
</td>
return ` </tr>
<tr class="hover:bg-gray-50"> `).join('');
<td class="px-6 py-4">${res.driverName || '-'}</td>
<td class="px-6 py-4">${res.vehicle || '-'}</td>
<td class="px-6 py-4 whitespace-nowrap">${formatDate(startDate)}</td>
<td class="px-6 py-4 whitespace-nowrap">${formatTime(startDate)}</td>
<td class="px-6 py-4 whitespace-nowrap">${formatDate(endDate)}</td>
<td class="px-6 py-4 whitespace-nowrap">${formatTime(endDate)}</td>
<td class="px-6 py-4">${res.purpose || '-'}</td>
<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(','), // Format date as DD.MM.YYYY
...dataToExport.map(res => [ const formatDate = (dateString) => {
`"${res.driverName}"`, const date = new Date(dateString);
`"${res.vehicle}"`, const day = String(date.getDate()).padStart(2, '0');
res.startDate, const month = String(date.getMonth() + 1).padStart(2, '0');
res.startTime, const year = date.getFullYear();
res.endDate, return `${day}.${month}.${year}`;
res.endTime, };
`"${res.purpose || ''}"`,
`"${calculateDuration(res)}"` // Format time as HH:MM
].join(',')) const formatTime = (dateString) => {
].join('\n'); 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;'
});
// Create and trigger download
const blob = new Blob(['\ufeff' + 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