1
- import { Card , DonutChart , Title , Subtitle } from '@tremor/react' ;
1
+ import { Card , Title , Subtitle } from '@tremor/react' ;
2
+ import type { Chart } from 'chart.js' ;
3
+ import { ChartTypeRegistry , TooltipItem } from 'chart.js' ;
4
+ import { ChartOptions } from 'chart.js' ;
2
5
import _map from 'lodash-es/map' ;
3
6
import _orderBy from 'lodash-es/orderBy' ;
7
+ import _sum from 'lodash-es/sum' ;
4
8
import _sumBy from 'lodash-es/sumBy' ;
9
+ import { Doughnut } from 'react-chartjs-2' ;
10
+ import { valueFormatter , getColor } from '@/components/analytics/helpers' ;
5
11
import { formatNumber } from '@/utils/js' ;
6
12
import ExportButton from '../buttons/ExportButton' ;
7
13
14
+ const centerTextPlugin = {
15
+ id : 'centerText' ,
16
+ beforeDraw : ( chart : Chart ) => {
17
+ const { width, height, ctx } = chart ;
18
+ ctx . restore ( ) ;
19
+
20
+ const fontSize = ( height / 150 ) . toFixed ( 2 ) ;
21
+ ctx . font = `${ fontSize } em sans-serif` ;
22
+ ctx . textBaseline = 'middle' ;
23
+
24
+ const total = _sum ( chart . data . datasets [ 0 ] . data ) ;
25
+
26
+ const text = total . toString ( ) ;
27
+ const textX = Math . round ( ( width - ctx . measureText ( text ) . width ) / 2 ) ;
28
+ const textY = height / 2 ;
29
+
30
+ ctx . fillText ( text , textX , textY ) ;
31
+ ctx . save ( ) ;
32
+ } ,
33
+ } ;
34
+
8
35
interface PieGraphItem {
9
36
label : string ;
10
37
value : number ;
@@ -31,34 +58,37 @@ export default function PieGraph({
31
58
const total = _sumBy ( items , ( item ) => item . value ) ;
32
59
const orderedItems = _orderBy ( items , [ 'value' ] , 'desc' ) ;
33
60
61
+ const data = {
62
+ labels : orderedItems . map ( ( v ) => v . label ) ,
63
+ datasets : [
64
+ {
65
+ data : orderedItems . map ( ( v ) => v . value ) ,
66
+ backgroundColor : orderedItems . map ( ( v , ind ) => getColor ( ind ) ) ,
67
+ hoverOffset : 10 ,
68
+ } ,
69
+ ] ,
70
+ } ;
71
+
72
+ const options : ChartOptions < 'doughnut' > = {
73
+ cutout : '70%' ,
74
+ plugins : {
75
+ legend : {
76
+ display : false ,
77
+ } ,
78
+ tooltip : {
79
+ callbacks : {
80
+ label : function ( context : TooltipItem < keyof ChartTypeRegistry > ) {
81
+ const value = valueFormatter ( Number ( context . raw as number ) ) ;
82
+ return value ;
83
+ } ,
84
+ } ,
85
+ } ,
86
+ } ,
87
+ } ;
88
+
34
89
return (
35
90
< div className = "w-full max-w-lg mx-auto" key = { key } >
36
- < DonutChart
37
- className = "mt-8"
38
- data = { orderedItems }
39
- category = "value"
40
- index = "label"
41
- valueFormatter = { formatNumber }
42
- showTooltip
43
- // See https://www.tremor.so/docs/layout/color-palette
44
- colors = { [
45
- 'cyan' ,
46
- 'blue' ,
47
- 'indigo' ,
48
- 'violet' ,
49
- 'fuchsia' ,
50
- 'rose' ,
51
- 'teal' ,
52
- 'lime' ,
53
- 'amber' ,
54
- 'zinc' ,
55
- 'yellow' ,
56
- 'sky' ,
57
- 'stone' ,
58
- 'orange' ,
59
- 'pink' ,
60
- ] }
61
- />
91
+ < Doughnut key = { key } data = { data } options = { options } plugins = { [ centerTextPlugin ] } />
62
92
< h4 className = "text-center font-semibold mt-5" > { key } </ h4 >
63
93
< ul className = "tremor-List-root w-full divide-y divide-tremor-border text-tremor-content dark:divide-dark-tremor-border dark:text-dark-tremor-content" >
64
94
{ orderedItems . map ( ( item ) => {
0 commit comments