mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-26 18:42:49 +00:00
109 lines
4.0 KiB
TypeScript
109 lines
4.0 KiB
TypeScript
'use client';
|
|
|
|
import { useQuery } from '@tanstack/react-query';
|
|
import { Ticket, Users, DollarSign, TrendingUp } from 'lucide-react';
|
|
import StatCard from '@/components/dashboard/StatCard';
|
|
import DataTable from '@/components/ui/DataTable';
|
|
import Badge from '@/components/ui/Badge';
|
|
import { dashboardApi } from '@/lib/api/dashboard';
|
|
import { formatCurrency, formatDateTime } from '@/lib/utils';
|
|
import { LineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts';
|
|
|
|
export default function DashboardPage() {
|
|
const { data: stats, isLoading: statsLoading } = useQuery({
|
|
queryKey: ['dashboard-stats'],
|
|
queryFn: dashboardApi.getStats,
|
|
});
|
|
|
|
const { data: revenueData, isLoading: revenueLoading } = useQuery({
|
|
queryKey: ['revenue-chart'],
|
|
queryFn: () => dashboardApi.getRevenueChart(30),
|
|
});
|
|
|
|
const { data: recentBookingsData, isLoading: bookingsLoading } = useQuery({
|
|
queryKey: ['recent-bookings'],
|
|
queryFn: () => dashboardApi.getRecentBookings(10),
|
|
});
|
|
|
|
const recentBookings = Array.isArray(recentBookingsData)
|
|
? recentBookingsData
|
|
: recentBookingsData?.items || recentBookingsData?.data || [];
|
|
|
|
const columns = [
|
|
{ key: 'reference', label: 'Reference', render: (item: any) => item.bookingRef || item.reference },
|
|
{ key: 'passenger', label: 'Passenger', render: (item: any) => item.passenger?.fullName || item.contactEmail || 'N/A' },
|
|
{ key: 'amount', label: 'Amount', render: (item: any) => formatCurrency(item.totalMinor || item.amount, item.currency || 'ETB') },
|
|
{
|
|
key: 'status',
|
|
label: 'Status',
|
|
render: (item: any) => (
|
|
<Badge variant="status" status={item.status}>
|
|
{item.status}
|
|
</Badge>
|
|
)
|
|
},
|
|
{ key: 'createdAt', label: 'Created', render: (item: any) => formatDateTime(item.createdAt) },
|
|
];
|
|
|
|
return (
|
|
<div className="space-y-6">
|
|
<div>
|
|
<h1 className="text-3xl font-bold text-foreground">Dashboard</h1>
|
|
<p className="text-muted-foreground mt-1">Welcome back! Here's what's happening today.</p>
|
|
</div>
|
|
|
|
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4">
|
|
<StatCard
|
|
title="Total Bookings"
|
|
value={statsLoading ? '...' : (stats?.totalBookings || 0).toLocaleString()}
|
|
icon={Ticket}
|
|
color="blue"
|
|
/>
|
|
<StatCard
|
|
title="Total Revenue"
|
|
value={statsLoading ? '...' : formatCurrency(stats?.totalRevenue || 0, 'ETB')}
|
|
icon={DollarSign}
|
|
color="green"
|
|
/>
|
|
<StatCard
|
|
title="Total Passengers"
|
|
value={statsLoading ? '...' : (stats?.totalPassengers || 0).toLocaleString()}
|
|
icon={Users}
|
|
color="purple"
|
|
/>
|
|
<StatCard
|
|
title="Occupancy Rate"
|
|
value={statsLoading ? '...' : `${stats?.occupancyRate || 0}%`}
|
|
icon={TrendingUp}
|
|
color="green"
|
|
/>
|
|
</div>
|
|
|
|
{!revenueLoading && revenueData && revenueData.length > 0 && (
|
|
<div className="card">
|
|
<h2 className="mb-4 text-lg font-semibold text-foreground">Revenue Trend (Last 30 Days)</h2>
|
|
<ResponsiveContainer width="100%" height={300}>
|
|
<LineChart data={revenueData}>
|
|
<CartesianGrid strokeDasharray="3 3" className="stroke-border" />
|
|
<XAxis dataKey="date" tick={{ fontSize: 12 }} className="text-muted-foreground" />
|
|
<YAxis tick={{ fontSize: 12 }} className="text-muted-foreground" />
|
|
<Tooltip formatter={(value: number) => formatCurrency(value, 'ETB')} />
|
|
<Line type="monotone" dataKey="revenue" stroke="#2563eb" strokeWidth={2} />
|
|
</LineChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
)}
|
|
|
|
<div className="card">
|
|
<h2 className="mb-4 text-lg font-semibold text-foreground">Recent Bookings</h2>
|
|
<DataTable
|
|
data={recentBookings}
|
|
columns={columns}
|
|
loading={bookingsLoading}
|
|
emptyMessage="No recent bookings"
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|