mirror of
https://github.com/Dvorinka/PPve.git
synced 2026-06-04 04:22:58 +00:00
c
This commit is contained in:
+160
-54
@@ -1252,6 +1252,57 @@
|
||||
</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 -->
|
||||
<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">
|
||||
@@ -4314,38 +4365,34 @@ function displayReservations(reservations) {
|
||||
return;
|
||||
}
|
||||
|
||||
tbody.innerHTML = reservations.map(res => {
|
||||
const startDate = new Date(res.start);
|
||||
const endDate = new Date(res.end);
|
||||
|
||||
// Format date as DD.MM.YYYY
|
||||
const formatDate = (date) => {
|
||||
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 = (date) => {
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return `${hours}:${minutes}`;
|
||||
};
|
||||
|
||||
return `
|
||||
<tr class="hover:bg-gray-50">
|
||||
<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('');
|
||||
// Format date and time as DD.MM.YYYY HH:MM
|
||||
const formatDateTime = (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();
|
||||
const hours = String(date.getHours()).padStart(2, '0');
|
||||
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||
return `${day}.${month}.${year} ${hours}:${minutes}`;
|
||||
};
|
||||
|
||||
tbody.innerHTML = reservations.map(res => `
|
||||
<tr class="hover:bg-gray-50">
|
||||
<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">${formatDateTime(res.start)}</td>
|
||||
<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">
|
||||
<button onclick="editReservation('${res.id}')" class="text-blue-600 hover:text-blue-900 mr-3">
|
||||
<i class="fas fa-edit"></i> Upravit
|
||||
</button>
|
||||
<button onclick="deleteReservation('${res.id}')" class="text-red-600 hover:text-red-900">
|
||||
<i class="fas fa-trash"></i> Smazat
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
// Function to filter reservations
|
||||
@@ -4379,39 +4426,98 @@ function exportReservations() {
|
||||
const vehicleFilter = document.getElementById('vehicleFilter').value;
|
||||
const dateFilter = document.getElementById('dateFilter').value;
|
||||
|
||||
let dataToExport = window.allReservations;
|
||||
let dataToExport = [...window.allReservations];
|
||||
|
||||
// Apply filters if set
|
||||
if (vehicleFilter) {
|
||||
dataToExport = dataToExport.filter(res => res.vehicle === vehicleFilter);
|
||||
}
|
||||
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
|
||||
const headers = ['Řidič', 'Vozidlo', 'Datum od', 'Čas od', 'Datum do', 'Čas do', 'Účel', 'Doba trvání'];
|
||||
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');
|
||||
// Sort by start date
|
||||
dataToExport.sort((a, b) => new Date(a.start) - new Date(b.start));
|
||||
|
||||
// Create and trigger download
|
||||
const blob = new Blob(['\ufeff' + csvContent], { type: 'text/csv;charset=utf-8;' });
|
||||
// Format date as DD.MM.YYYY
|
||||
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 date = new Date().toISOString().split('T')[0];
|
||||
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
||||
link.href = URL.createObjectURL(blob);
|
||||
link.download = `rezervace_${date}.csv`;
|
||||
link.download = `rezervace_${timestamp}.csv`;
|
||||
link.style.display = 'none';
|
||||
document.body.appendChild(link);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user