'use client';
import { useState, useEffect, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import { Card } from '@/components/ui/Card';
import { Button } from '@/components/ui/Button';
import { Table } from '@/components/ui/Table';
import { useI18n } from '@/lib/i18n';
import { listVehicles, type VehicleResponse } from '@/lib/vehicles';
interface DashboardStats {
total: number;
available: number;
reserved: number;
sold: number;
totalValue: number;
}
interface StatCardProps {
icon: React.ReactNode;
label: string;
value: string;
testId: string;
}
function StatCard({ icon, label, value, testId }: StatCardProps) {
return (
);
}
const CarIcon = (
);
const CheckCircleIcon = (
);
const ClockIcon = (
);
const TagIcon = (
);
const EuroIcon = (
);
export function Dashboard() {
const router = useRouter();
const { t } = useI18n();
const [recentVehicles, setRecentVehicles] = useState([]);
const [stats, setStats] = useState({
total: 0,
available: 0,
reserved: 0,
sold: 0,
totalValue: 0,
});
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const fetchDashboardData = useCallback(async () => {
setLoading(true);
setError(null);
try {
const [recentResponse, allResponse] = await Promise.all([
listVehicles({ page: 1, page_size: 5, sort: '-created_at' }),
listVehicles({ page: 1, page_size: 1000 }),
]);
setRecentVehicles(recentResponse.items);
const allVehicles = allResponse.items;
const computedStats: DashboardStats = {
total: allResponse.total,
available: allVehicles.filter(v => v.availability === 'available').length,
reserved: allVehicles.filter(v => v.availability === 'reserved').length,
sold: allVehicles.filter(v => v.availability === 'sold').length,
totalValue: allVehicles.reduce((sum, v) => sum + v.price, 0),
};
setStats(computedStats);
} catch (err: unknown) {
const apiErr = err as { error?: { message?: string } };
setError(apiErr?.error?.message || t('dashboard.error'));
} finally {
setLoading(false);
}
}, [t]);
useEffect(() => {
fetchDashboardData();
}, [fetchDashboardData]);
const currencyFormatter = new Intl.NumberFormat('de-DE', { style: 'currency', currency: 'EUR' });
const vehicleColumns = [
{
key: 'make',
label: t('dashboard.make'),
render: (row: VehicleResponse) => (
),
},
{ key: 'model', label: t('dashboard.model') },
{ key: 'fin', label: t('dashboard.fin') },
{
key: 'price',
label: t('dashboard.price'),
render: (row: VehicleResponse) => currencyFormatter.format(row.price),
},
{ key: 'availability', label: t('dashboard.availability') },
];
if (loading) {
return (
{t('common.loading')}
);
}
if (error) {
return (
{error}
);
}
return (
{t('dashboard.title')}
{EuroIcon}
{t('dashboard.totalValue')}
{currencyFormatter.format(stats.totalValue)}
{t('dashboard.quickActions')}
{t('dashboard.recentVehicles')}
{recentVehicles.length > 0 ? (
row.id} />
) : (
{t('dashboard.noVehicles')}
)}
);
}