gitscope
← marzneshin / v0.6.2 / dashboard/src/components/charts/pie/index.tsx
https://dev.kronoz.win/r/marzneshin.git
dashboard/src/components/charts/pie/index.tsx · TypeScript
Blame Raw
 1import { FC, useState } from 'react';
 2import { Pie } from '@visx/shape';
 3import { Group } from '@visx/group';
 4import { Text } from '@visx/text';
 5
 6export type PieChartDataRecord = {
 7    symbol: string,
 8    amount: number,
 9    color: string
10};
11
12export interface PieChartProps {
13    data: PieChartDataRecord[];
14    width: number;
15    height: number;
16    total: number;
17    label: string;
18}
19
20export const PieChart: FC<PieChartProps> = ({ data, width, height, total, label }) => {
21    const half = width / 2;
22    const [active, setActive] = useState<PieChartDataRecord | null>(null);
23
24    return (
25        <svg width={width} height={height}>
26            <Group top={half} left={half}>
27                <Pie
28                    data={data}
29                    pieValue={(data) => data.amount}
30                    outerRadius={half}
31                    innerRadius={({ data }) => (active && (active.symbol === data.symbol) ? half - 14 : half - 8)}
32                    padAngle={0.01}
33                >
34                    {pie => {
35                        return pie.arcs.map(arc => {
36                            return (
37                                <g
38                                    key={arc.data.symbol}
39                                    onMouseEnter={() => setActive(arc.data)}
40                                    onMouseLeave={() => setActive(null)}
41                                >
42                                    <path d={pie.path(arc) ?? ''} className={arc.data.color}></path>
43                                </g>
44                            )
45                        })
46                    }}
47                </Pie>
48                <Text
49                    textAnchor="middle"
50                    fontSize={30}
51                    dy={-10}
52                    className='fill-primary'
53                >
54                    {active ? active.amount : total}
55                </Text>
56                <Text
57                    textAnchor="middle"
58                    fontSize={15}
59                    dy={10}
60                    className='fill-muted-foreground'
61                >
62                    {label}
63                </Text>
64            </Group>
65        </svg>
66    );
67};