import { groupBy } from 'es-toolkit'; import { TrendingUpIcon } from 'lucide-react'; import { Area, AreaChart, Bar, BarChart, CartesianGrid, PolarAngleAxis, PolarGrid, Radar, RadarChart, XAxis, YAxis, } from 'recharts'; import type { Post } from '@/entities/post'; import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from '@/shared/ui/card'; import { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig, } from '@/shared/ui/chart'; type PostChartsProps = { /** 현재 필터(검색·작성자)가 적용된 목록 — 차트도 표와 같은 데이터를 본다. */ posts: Post[]; }; type AuthorStat = { userId: number; author: string; count: number; avgBody: number; avgTitle: number; }; const avgOf = (items: Post[], pick: (post: Post) => number) => Math.round(items.reduce((sum, post) => sum + pick(post), 0) / items.length); const toAuthorStats = (posts: Post[]): AuthorStat[] => { const byAuthor = groupBy(posts, (post) => post.userId); return Object.entries(byAuthor) .map(([userId, items]) => ({ userId: Number(userId), author: `작성자 ${userId}`, count: items.length, avgBody: avgOf(items, (post) => post.body.length), avgTitle: avgOf(items, (post) => post.title.length), })) .sort((a, b) => a.userId - b.userId); }; const toIdBuckets = (posts: Post[]) => { return Array.from({ length: 10 }, (_, index) => { const start = index * 10 + 1; const items = posts.filter( (post) => post.id >= start && post.id <= start + 9 ); return { range: `${start}~${start + 9}`, avgBody: items.length === 0 ? 0 : avgOf(items, (post) => post.body.length), }; }); }; const bodyConfig = { avgBody: { label: '평균 본문 길이', color: 'var(--chart-1)' }, } satisfies ChartConfig; const titleConfig = { avgTitle: { label: '평균 제목 길이', color: 'var(--chart-2)' }, } satisfies ChartConfig; export const PostCharts = ({ posts }: PostChartsProps) => { const stats = toAuthorStats(posts); return (