xpeditis2.0/apps/frontend/app/dashboard/page.tsx
David-Henri ARNAUD b31d325646 feature phase 2
2025-10-10 15:07:05 +02:00

183 lines
6.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* Dashboard Home Page
*
* Main dashboard with KPIs and recent bookings
*/
'use client';
import { useQuery } from '@tanstack/react-query';
import { bookingsApi } from '@/lib/api';
import Link from 'next/link';
export default function DashboardPage() {
const { data: bookings, isLoading } = useQuery({
queryKey: ['bookings', 'recent'],
queryFn: () => bookingsApi.list({ limit: 5 }),
});
const stats = [
{ name: 'Total Bookings', value: bookings?.total || 0, icon: '📦', change: '+12%' },
{ name: 'This Month', value: '8', icon: '📅', change: '+4.3%' },
{ name: 'Pending', value: '3', icon: '⏳', change: '-2%' },
{ name: 'Completed', value: '45', icon: '✅', change: '+8%' },
];
return (
<div className="space-y-6">
{/* Welcome Section */}
<div className="bg-gradient-to-r from-blue-600 to-blue-700 rounded-lg shadow-lg p-6 text-white">
<h1 className="text-3xl font-bold mb-2">Welcome back!</h1>
<p className="text-blue-100">
Here's what's happening with your shipments today.
</p>
</div>
{/* KPI Cards */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{stats.map((stat) => (
<div
key={stat.name}
className="bg-white rounded-lg shadow p-6 hover:shadow-md transition-shadow"
>
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-600">{stat.name}</p>
<p className="text-3xl font-bold text-gray-900 mt-2">{stat.value}</p>
</div>
<div className="text-4xl">{stat.icon}</div>
</div>
<div className="mt-4">
<span
className={`text-sm font-medium ${
stat.change.startsWith('+')
? 'text-green-600'
: 'text-red-600'
}`}
>
{stat.change}
</span>
<span className="text-sm text-gray-500 ml-2">vs last month</span>
</div>
</div>
))}
</div>
{/* Quick Actions */}
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<Link
href="/dashboard/search"
className="bg-white rounded-lg shadow p-6 hover:shadow-md transition-shadow group"
>
<div className="flex items-center space-x-4">
<div className="w-12 h-12 bg-blue-100 rounded-lg flex items-center justify-center text-2xl group-hover:bg-blue-200 transition-colors">
🔍
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900">Search Rates</h3>
<p className="text-sm text-gray-500">Find the best shipping rates</p>
</div>
</div>
</Link>
<Link
href="/dashboard/bookings/new"
className="bg-white rounded-lg shadow p-6 hover:shadow-md transition-shadow group"
>
<div className="flex items-center space-x-4">
<div className="w-12 h-12 bg-green-100 rounded-lg flex items-center justify-center text-2xl group-hover:bg-green-200 transition-colors">
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900">New Booking</h3>
<p className="text-sm text-gray-500">Create a new shipment</p>
</div>
</div>
</Link>
<Link
href="/dashboard/bookings"
className="bg-white rounded-lg shadow p-6 hover:shadow-md transition-shadow group"
>
<div className="flex items-center space-x-4">
<div className="w-12 h-12 bg-purple-100 rounded-lg flex items-center justify-center text-2xl group-hover:bg-purple-200 transition-colors">
📋
</div>
<div>
<h3 className="text-lg font-semibold text-gray-900">View Bookings</h3>
<p className="text-sm text-gray-500">Track all your shipments</p>
</div>
</div>
</Link>
</div>
{/* Recent Bookings */}
<div className="bg-white rounded-lg shadow">
<div className="px-6 py-4 border-b flex items-center justify-between">
<h2 className="text-lg font-semibold text-gray-900">Recent Bookings</h2>
<Link
href="/dashboard/bookings"
className="text-sm font-medium text-blue-600 hover:text-blue-700"
>
View all
</Link>
</div>
<div className="divide-y">
{isLoading ? (
<div className="px-6 py-12 text-center text-gray-500">
Loading bookings...
</div>
) : bookings?.data && bookings.data.length > 0 ? (
bookings.data.map((booking) => (
<Link
key={booking.id}
href={`/dashboard/bookings/${booking.id}`}
className="block px-6 py-4 hover:bg-gray-50 transition-colors"
>
<div className="flex items-center justify-between">
<div className="flex-1">
<div className="flex items-center space-x-3">
<span className="text-sm font-medium text-gray-900">
{booking.bookingNumber}
</span>
<span
className={`px-2 py-1 text-xs font-medium rounded-full ${
booking.status === 'confirmed'
? 'bg-green-100 text-green-800'
: booking.status === 'pending'
? 'bg-yellow-100 text-yellow-800'
: 'bg-gray-100 text-gray-800'
}`}
>
{booking.status}
</span>
</div>
<p className="text-sm text-gray-500 mt-1">
{booking.cargoDescription}
</p>
</div>
<div className="text-right">
<p className="text-sm text-gray-500">
{new Date(booking.createdAt).toLocaleDateString()}
</p>
</div>
</div>
</Link>
))
) : (
<div className="px-6 py-12 text-center">
<p className="text-gray-500 mb-4">No bookings yet</p>
<Link
href="/dashboard/search"
className="inline-flex items-center px-4 py-2 border border-transparent text-sm font-medium rounded-md text-white bg-blue-600 hover:bg-blue-700"
>
Search for rates
</Link>
</div>
)}
</div>
</div>
</div>
);
}