104 lines
3.3 KiB
TypeScript
104 lines
3.3 KiB
TypeScript
import { useQuery } from "@tanstack/react-query"
|
|
import { CardHeader, CardTitle, CardContent } from "@/components/ui/card"
|
|
import { PieChart, Pie, ResponsiveContainer, Cell, Tooltip } from "recharts"
|
|
import config from "@/config"
|
|
import { formatCurrency } from "@/lib/utils"
|
|
|
|
interface PurchaseMetricsData {
|
|
activePurchaseOrders: number
|
|
overduePurchaseOrders: number
|
|
onOrderUnits: number
|
|
onOrderCost: number
|
|
onOrderRetail: number
|
|
vendorOrders: {
|
|
vendor: string
|
|
orders: number
|
|
units: number
|
|
cost: number
|
|
retail: number
|
|
}[]
|
|
}
|
|
|
|
const COLORS = [
|
|
"#0088FE",
|
|
"#00C49F",
|
|
"#FFBB28",
|
|
"#FF8042",
|
|
"#8884D8",
|
|
"#82CA9D",
|
|
"#FFC658",
|
|
"#FF7C43",
|
|
]
|
|
|
|
export function PurchaseMetrics() {
|
|
const { data } = useQuery<PurchaseMetricsData>({
|
|
queryKey: ["purchase-metrics"],
|
|
queryFn: async () => {
|
|
const response = await fetch(`${config.apiUrl}/dashboard/purchase/metrics`)
|
|
if (!response.ok) {
|
|
throw new Error("Failed to fetch purchase metrics")
|
|
}
|
|
return response.json()
|
|
},
|
|
})
|
|
|
|
return (
|
|
<>
|
|
<CardHeader>
|
|
<CardTitle className="text-lg font-medium">Purchase Overview</CardTitle>
|
|
</CardHeader>
|
|
<CardContent>
|
|
<div className="grid grid-cols-2 gap-4 mb-6">
|
|
<div>
|
|
<p className="text-sm font-medium text-muted-foreground">Active Orders</p>
|
|
<p className="text-2xl font-bold">{data?.activePurchaseOrders.toLocaleString() || 0}</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-medium text-muted-foreground">Overdue Orders</p>
|
|
<p className="text-2xl font-bold">{data?.overduePurchaseOrders.toLocaleString() || 0}</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-medium text-muted-foreground">Units On Order</p>
|
|
<p className="text-2xl font-bold">{data?.onOrderUnits.toLocaleString() || 0}</p>
|
|
</div>
|
|
<div>
|
|
<p className="text-sm font-medium text-muted-foreground">Order Cost</p>
|
|
<p className="text-2xl font-bold">{formatCurrency(data?.onOrderCost || 0)}</p>
|
|
</div>
|
|
<div className="col-span-2">
|
|
<p className="text-sm font-medium text-muted-foreground">Order Retail</p>
|
|
<p className="text-2xl font-bold">{formatCurrency(data?.onOrderRetail || 0)}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="h-[300px] w-full">
|
|
<ResponsiveContainer width="100%" height="100%">
|
|
<PieChart>
|
|
<Pie
|
|
data={data?.vendorOrders || []}
|
|
dataKey="cost"
|
|
nameKey="vendor"
|
|
cx="50%"
|
|
cy="50%"
|
|
innerRadius={60}
|
|
outerRadius={80}
|
|
paddingAngle={2}
|
|
>
|
|
{data?.vendorOrders?.map((entry, index) => (
|
|
<Cell
|
|
key={entry.vendor}
|
|
fill={COLORS[index % COLORS.length]}
|
|
/>
|
|
))}
|
|
</Pie>
|
|
<Tooltip
|
|
formatter={(value: number) => formatCurrency(value)}
|
|
labelFormatter={(label: string) => `Vendor: ${label}`}
|
|
/>
|
|
</PieChart>
|
|
</ResponsiveContainer>
|
|
</div>
|
|
</CardContent>
|
|
</>
|
|
)
|
|
}
|