"use client"
import { BarChart, Bar, LineChart, Line, XAxis, YAxis, Tooltip, ResponsiveContainer, CartesianGrid } from "recharts" import { useLazyGetProductVendorsQuery } from "../../../../redux/services/thrintServiceApi" import { useEffect, useState } from "react"
interface ChartData { name: string [key: string]: string | number }
export default function VendorProductCharts() { const [getProductVendors, { data, isLoading, error }] = useLazyGetProductVendorsQuery() const [vendorChartData, setVendorChartData] = useState<ChartData[]>([]) const [productChartData, setProductChartData] = useState<ChartData[]>([])
useEffect(() => { getProductVendors() }, [getProductVendors])
useEffect(() => { if (data) { // Transform vendor data const topVendors = Object.entries(data.vendors) .sort(([, a], [, b]) => (b as number) - (a as number)) .slice(0, 10)
const vendorData: ChartData[] = topVendors.map(([vendor, count]) => ({
name: vendor.length > 15 ? vendor.substring(0, 15) + "..." : vendor,
fullName: vendor,
count: count as number,
}))
// Transform product data
const topProducts = Object.entries(data.products)
.sort(([, a], [, b]) => (b as number) - (a as number))
.slice(0, 10)
const productData: ChartData[] = topProducts.map(([product, count]) => ({
name: product.length > 20 ? product.substring(0, 20) + "..." : product,
fullName: product,
count: count as number,
}))
setVendorChartData(vendorData)
setProductChartData(productData)
}
}, [data])
const CustomTooltip = ({ active, payload, label }: any) => {
if (active && payload && payload.length) {
return (
<div className="bg-white p-3 border border-gray-300 rounded-lg shadow-lg">
<p className="font-medium text-gray-900 mb-1">{payload[0].payload.fullName || payload[0].payload.name}</p>
<p className="text-gray-600">{Count: ${payload[0].value}
}</p>
</div>
)
}
return null
}
if (isLoading) { return ( <div className="bg-gray-50 min-h-screen p-6"> <div className="max-w-7xl mx-auto"> <div className="grid grid-cols-1 lg:grid-cols-2 gap-8"> {[1, 2].map((i) => ( <div key={i} className="bg-white rounded-lg border border-gray-200 p-6"> <div className="animate-pulse"> <div className="h-4 bg-gray-200 rounded w-1/4 mb-4"></div> <div className="h-80 bg-gray-200 rounded"></div> </div> </div> ))} </div> </div> </div> ) }
if (error) { return ( <div className="bg-gray-50 min-h-screen p-6 flex items-center justify-center"> <div className="bg-white border border-red-200 rounded-lg p-6 max-w-md text-center"> <p className="text-red-600">Error loading data. Please try again.</p> </div> </div> ) }
return ( <div className="bg-gray-50 min-h-screen p-6"> <div className="max-w-7xl mx-auto">
{/* Charts Grid */}
<div className="grid grid-cols-1 lg:grid-cols-2 gap-8">
{/* Vendors Chart */}
<div className="bg-white rounded-lg border border-gray-200 p-6">
<div className="mb-6">
<h2 className="text-lg font-medium text-gray-900 mb-1">Top 10 Vendors</h2>
<p className="text-sm text-gray-500">Distribution by count</p>
</div>
<ResponsiveContainer width="100%" height={400}>
<BarChart data={vendorChartData} margin={{ top: 20, right: 30, left: 20, bottom: 80 }}>
<CartesianGrid strokeDasharray="3 3" stroke="#f0f0f0" />
<XAxis
dataKey="name"
tick={{ fontSize: 12, fill: "#6b7280" }}
angle={0}
textAnchor="middle"
height={80}
interval={0}
axisLine={{ stroke: "#e5e7eb" }}
tickLine={{ stroke: "#e5e7eb" }}
/>
<YAxis
tick={{ fontSize: 12, fill: "#6b7280" }}
axisLine={{ stroke: "#e5e7eb" }}
tickLine={{ stroke: "#e5e7eb" }}
/>
<Tooltip content={<CustomTooltip />} />
<Bar dataKey="count" fill="#3b82f6" radius={[4, 4, 0, 0]} />
</BarChart>
</ResponsiveContainer>
</div>
{/* Products Chart */}
<div className="bg-white rounded-lg border border-gray-200 p-6">
<div className="mb-6">
<h2 className="text-lg font-medium text-gray-900 mb-1">Top 10 Products</h2>
<p className="text-sm text-gray-500">Distribution by count</p>
</div>
<ResponsiveContainer width="100%" height={400}>
<LineChart data={productChartData} margin={{ top: 20, right: 30, left: 20, bottom: 80 }}>
<CartesianGrid strokeDasharray="3 3" stroke="#f0f0f0" />
<XAxis
dataKey="name"
tick={{ fontSize: 12, fill: "#6b7280" }}
angle={0}
textAnchor="middle"
height={80}
interval={0}
axisLine={{ stroke: "#e5e7eb" }}
tickLine={{ stroke: "#e5e7eb" }}
/>
<YAxis
tick={{ fontSize: 12, fill: "#6b7280" }}
axisLine={{ stroke: "#e5e7eb" }}
tickLine={{ stroke: "#e5e7eb" }}
/>
<Tooltip content={<CustomTooltip />} />
<Line
type="monotone"
dataKey="count"
stroke="#10b981"
strokeWidth={3}
dot={{ fill: "#10b981", strokeWidth: 2, r: 5 }}
activeDot={{ r: 7, stroke: "#10b981", strokeWidth: 2, fill: "#ffffff" }}
/>
</LineChart>
</ResponsiveContainer>
</div>
</div>
</div>
</div>
) } show the x axis names inside the bar itself and for line show the names with colours as legends
I've modified your chart component with the following changes:
CustomBarLabel
component that renders vendor names in white text centered within each bartick={false}
to hide the bottom labels since they're now inside the barstick={false}
to clean up the bottom areaThe bar chart now clearly shows vendor names within each bar, making it easy to identify them at a glance. The line chart uses a color-coded legend system that makes it easy to associate each data point with its corresponding product name.
Here are several alternative ways to visualize your vendor and product data:
Here are several different ways to visualize your vendor and product data, each with unique advantages:
A treemap displays hierarchical data as nested rectangles, where the size of each rectangle represents the value.
Benefits:
This combination provides two distinct ways to visualize your data distribution.
Benefits:
This approach combines data cards with embedded mini-visualizations for each vendor/product.
Benefits:
A heatmap uses color intensity to represent data values, creating a visual "heat" pattern.
Benefits:
This combines the precision of tabular data with visual elements for quick insights.
Benefits:
For your specific vendor and product data, I would recommend either:
Each of these approaches provides a more modern and engaging way to visualize your data compared to standard bar and line charts.