Files
goodgo-platform/apps/web/components/charts/district-bar-chart.tsx
Ho Ngoc Hai 5848c2b386 perf(web): optimize bundle size — dynamic import Mapbox GL and code split Recharts
- Dynamic import ListingMap with next/dynamic (ssr: false) in /listings/[id] and /search pages
- Extract Recharts into lazy-loaded DistrictBarChart and PriceTrendChart components
- /listings/[id] first-load JS: 618KB → 149KB (-76%)
- /search first-load JS: 619KB → 150KB (-76%)
- Both pages now well under 300KB target

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-08 13:10:24 +07:00

61 lines
1.7 KiB
TypeScript

'use client';
import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
ResponsiveContainer,
} from 'recharts';
// eslint-disable-next-line @typescript-eslint/no-explicit-any
type TooltipFormatter = (value: any, name: any) => [string, string];
interface DistrictBarChartProps {
data: { district: string; price?: number; 'Gia/m2'?: number; listings: number }[];
height?: number;
dataKey?: string;
tooltipFormatter?: TooltipFormatter;
}
export function DistrictBarChart({
data,
height = 300,
dataKey = 'price',
tooltipFormatter,
}: DistrictBarChartProps) {
const defaultFormatter: TooltipFormatter = (value, name) => [
name === dataKey ? `${value} tr/m2` : String(value),
name === dataKey ? 'Gia' : 'Tin dang',
];
return (
<ResponsiveContainer width="100%" height={height}>
<BarChart data={data} margin={{ top: 5, right: 20, left: 0, bottom: 5 }}>
<CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
<XAxis
dataKey="district"
tick={{ fontSize: 11 }}
angle={-30}
textAnchor="end"
height={60}
className="fill-muted-foreground"
/>
<YAxis tick={{ fontSize: 12 }} className="fill-muted-foreground" />
<Tooltip
contentStyle={{
backgroundColor: 'hsl(var(--card))',
border: '1px solid hsl(var(--border))',
borderRadius: '0.5rem',
fontSize: '0.875rem',
}}
formatter={tooltipFormatter ?? defaultFormatter}
/>
<Bar dataKey={dataKey} fill="hsl(var(--primary))" radius={[4, 4, 0, 0]} />
</BarChart>
</ResponsiveContainer>
);
}