feat: add vehicle edit page, image gallery with upload, print and CSV export
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
'use client';
|
||||
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import type { VehicleResponse } from '@/lib/vehicles';
|
||||
|
||||
interface VehicleActionsProps {
|
||||
vehicle: VehicleResponse;
|
||||
}
|
||||
|
||||
function escapeCsvValue(value: string | number | undefined | null): string {
|
||||
if (value === null || value === undefined) return '';
|
||||
const str = String(value);
|
||||
if (str.includes(',') || str.includes('"') || str.includes('\n')) {
|
||||
return `"${str.replace(/"/g, '""')}"`;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function downloadCsv(filename: string, csvContent: string): void {
|
||||
const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.href = url;
|
||||
link.download = filename;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
function vehicleToCsvRow(v: VehicleResponse): string {
|
||||
const headers = [
|
||||
'Make', 'Model', 'FIN', 'Year', 'Price', 'Vehicle Type',
|
||||
'Condition', 'Availability', 'Mileage (km)', 'Power (kW)',
|
||||
'Fuel Type', 'Transmission', 'Color', 'Location',
|
||||
'First Registration', 'Description',
|
||||
];
|
||||
return headers.map(h => {
|
||||
switch (h) {
|
||||
case 'Make': return escapeCsvValue(v.make);
|
||||
case 'Model': return escapeCsvValue(v.model);
|
||||
case 'FIN': return escapeCsvValue(v.fin);
|
||||
case 'Year': return escapeCsvValue(v.year);
|
||||
case 'Price': return escapeCsvValue(v.price);
|
||||
case 'Vehicle Type': return escapeCsvValue(v.vehicle_type);
|
||||
case 'Condition': return escapeCsvValue(v.condition);
|
||||
case 'Availability': return escapeCsvValue(v.availability);
|
||||
case 'Mileage (km)': return escapeCsvValue(v.mileage_km);
|
||||
case 'Power (kW)': return escapeCsvValue(v.power_kw);
|
||||
case 'Fuel Type': return escapeCsvValue(v.fuel_type);
|
||||
case 'Transmission': return escapeCsvValue(v.transmission);
|
||||
case 'Color': return escapeCsvValue(v.color);
|
||||
case 'Location': return escapeCsvValue(v.location);
|
||||
case 'First Registration': return escapeCsvValue(v.first_registration);
|
||||
case 'Description': return escapeCsvValue(v.description);
|
||||
default: return '';
|
||||
}
|
||||
}).join(',');
|
||||
}
|
||||
|
||||
export function VehicleActions({ vehicle }: VehicleActionsProps) {
|
||||
const handlePrint = () => {
|
||||
window.print();
|
||||
};
|
||||
|
||||
const handleExportPdf = () => {
|
||||
window.print();
|
||||
};
|
||||
|
||||
const handleExportCsv = () => {
|
||||
const headers = 'Make,Model,FIN,Year,Price,Vehicle Type,Condition,Availability,Mileage (km),Power (kW),Fuel Type,Transmission,Color,Location,First Registration,Description';
|
||||
const row = vehicleToCsvRow(vehicle);
|
||||
const csv = `${headers}\n${row}`;
|
||||
const filename = `vehicle_${vehicle.fin || vehicle.id}.csv`;
|
||||
downloadCsv(filename, csv);
|
||||
};
|
||||
|
||||
return (
|
||||
<div data-testid="vehicle-actions" className="flex gap-2 print:hidden">
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={handlePrint}
|
||||
data-testid="print-button"
|
||||
>
|
||||
Drucken
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={handleExportPdf}
|
||||
data-testid="export-pdf-button"
|
||||
>
|
||||
Als PDF exportieren
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
onClick={handleExportCsv}
|
||||
data-testid="export-csv-button"
|
||||
>
|
||||
Als CSV exportieren
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export function exportVehiclesToCsv(vehicles: VehicleResponse[]): void {
|
||||
const headers = 'Make,Model,FIN,Year,Price,Vehicle Type,Condition,Availability,Mileage (km),Power (kW),Fuel Type,Transmission,Color,Location,First Registration,Description';
|
||||
const rows = vehicles.map(v => vehicleToCsvRow(v));
|
||||
const csv = [headers, ...rows].join('\n');
|
||||
const now = new Date().toISOString().split('T')[0];
|
||||
downloadCsv(`vehicles_export_${now}.csv`, csv);
|
||||
}
|
||||
Reference in New Issue
Block a user