Skip to content

Commit 395c8d8

Browse files
committed
feat: add staked pnk per court chart, slightly modify skeleton size, abstract barchart
1 parent 1f37740 commit 395c8d8

File tree

4 files changed

+150
-91
lines changed

4 files changed

+150
-91
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
import React, { useCallback } from "react";
2+
import styled, { useTheme } from "styled-components";
3+
import { Chart as ChartJS, BarElement } from "chart.js";
4+
import ChartDataLabels from "chartjs-plugin-datalabels";
5+
import { Bar } from "react-chartjs-2";
6+
import "chartjs-adapter-moment";
7+
8+
const BarContainer = styled.div`
9+
height: 220px;
10+
margin-top: 16px;
11+
`;
12+
13+
ChartJS.register(BarElement);
14+
15+
export interface IBarChartData {
16+
labels: string[];
17+
data: number[];
18+
total: number;
19+
}
20+
21+
interface IBarChartProps {
22+
chartData: IBarChartData;
23+
}
24+
25+
const BarChart: React.FC<IBarChartProps> = ({ chartData }) => {
26+
const theme = useTheme();
27+
const getPercentValue = useCallback(
28+
(value: number) => `${Math.floor((value * 100) / chartData.total)} %`,
29+
[chartData]
30+
);
31+
const tickSize = 5; // suggested, if that many labels can't fit, chart will use even labels
32+
33+
const options = {
34+
responsive: true,
35+
maintainAspectRatio: false,
36+
tooltips: {
37+
position: "nearest",
38+
},
39+
scales: {
40+
x: {
41+
grid: { display: false },
42+
ticks: {
43+
color: theme.secondaryText,
44+
},
45+
},
46+
y: {
47+
grid: { color: theme.stroke, borderDash: [4, 4] },
48+
ticks: {
49+
color: theme.secondaryText,
50+
stepSize: (chartData.total * tickSize) / 100,
51+
callback: (value) => getPercentValue(value),
52+
},
53+
max: chartData.total,
54+
},
55+
},
56+
plugins: {
57+
datalabels: {
58+
anchor: "end",
59+
align: "top",
60+
offset: -4,
61+
color: theme.primaryText,
62+
font: {
63+
weight: "bold",
64+
},
65+
},
66+
tooltip: {
67+
backgroundColor: theme.whiteBackground,
68+
titleColor: theme.primaryText,
69+
borderColor: theme.stroke,
70+
borderWidth: 1,
71+
displayColors: false,
72+
callbacks: {
73+
label: (context) => getPercentValue(context.parsed.y),
74+
labelTextColor: () => theme.primaryText,
75+
},
76+
},
77+
},
78+
};
79+
80+
return (
81+
<BarContainer>
82+
<Bar
83+
data={{
84+
labels: chartData.labels,
85+
datasets: [
86+
{
87+
data: chartData.data,
88+
backgroundColor: theme.secondaryPurple,
89+
hoverBackgroundColor: theme.primaryBlue,
90+
maxBarThickness: 60,
91+
},
92+
],
93+
}}
94+
options={options}
95+
plugins={[ChartDataLabels]}
96+
/>
97+
</BarContainer>
98+
);
99+
};
100+
101+
export default BarChart;
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,5 @@
1-
import React, { useCallback } from "react";
2-
import styled, { useTheme } from "styled-components";
3-
4-
import { Chart as ChartJS, BarElement } from "chart.js";
5-
import ChartDataLabels from "chartjs-plugin-datalabels";
6-
import { Bar } from "react-chartjs-2";
7-
import "chartjs-adapter-moment";
8-
9-
const BarContainer = styled.div`
10-
height: 220px;
11-
margin-top: 16px;
12-
`;
13-
14-
ChartJS.register(BarElement);
1+
import React from "react";
2+
import BarChart, { IBarChartData } from "./BarChart";
153

164
export type CasesByCourtsChartData = { labels: string[]; cases: number[]; totalCases: number };
175

@@ -20,82 +8,13 @@ interface ICasesByCourtsChart {
208
}
219

2210
const CasesByCourtsChart: React.FC<ICasesByCourtsChart> = ({ data }) => {
23-
const theme = useTheme();
24-
const getPercentValue = useCallback((value: number) => `${Math.floor((value * 100) / data.totalCases)} %`, [data]);
25-
const tickSize = 5; // this is suggested, if that many labels can't fit, chart will use even labels
26-
27-
const options = {
28-
responsive: true,
29-
maintainAspectRatio: false,
30-
tooltips: {
31-
position: "nearest",
32-
},
33-
scales: {
34-
x: {
35-
grid: { display: false },
36-
ticks: {
37-
color: theme.secondaryText,
38-
},
39-
},
40-
y: {
41-
grid: { color: theme.stroke, borderDash: [4, 4] },
42-
ticks: {
43-
color: theme.secondaryText,
44-
stepSize: (data.totalCases * tickSize) / 100,
45-
callback: (value) => getPercentValue(value),
46-
},
47-
max: data.totalCases,
48-
},
49-
},
50-
plugins: {
51-
datalabels: {
52-
anchor: "end",
53-
align: "top",
54-
offset: -4,
55-
color: theme.primaryText,
56-
font: {
57-
weight: "bold",
58-
},
59-
},
60-
tooltip: {
61-
backgroundColor: theme.whiteBackground,
62-
titleColor: theme.primaryText,
63-
borderColor: theme.stroke,
64-
borderWidth: 1,
65-
displayColors: false,
66-
callbacks: {
67-
label: (context) => getPercentValue(context.parsed.y),
68-
labelTextColor: () => theme.primaryText,
69-
},
70-
},
71-
},
11+
const chartData: IBarChartData = {
12+
labels: data.labels,
13+
data: data.cases,
14+
total: data.totalCases,
7215
};
7316

74-
return (
75-
<BarContainer>
76-
{
77-
// eslint-disable-next-line
78-
// @ts-ignore
79-
<Bar
80-
{...{
81-
data: {
82-
labels: data.labels,
83-
datasets: [
84-
{
85-
data: data.cases,
86-
backgroundColor: theme.secondaryPurple,
87-
hoverBackgroundColor: theme.primaryBlue,
88-
maxBarThickness: 60,
89-
},
90-
],
91-
},
92-
options,
93-
}}
94-
plugins={[ChartDataLabels]}
95-
/>
96-
}
97-
</BarContainer>
98-
);
17+
return <BarChart chartData={chartData} />;
9918
};
10019

10120
export default CasesByCourtsChart;

web/src/pages/Home/CourtOverview/Chart.tsx

+22-3
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { responsiveSize } from "styles/responsiveSize";
1212

1313
import { StyledSkeleton } from "components/StyledSkeleton";
1414

15+
import StakedPNKByCourtsChart, { StakedPNKByCourtsChartData } from "./StakedPNKByCourtsChart";
1516
import CasesByCourtsChart, { CasesByCourtsChartData } from "./CasesByCourtsChart";
1617
import TimeSeriesChart from "./TimeSeriesChart";
1718

@@ -28,6 +29,7 @@ const StyledDropdown = styled(DropdownSelect)`
2829

2930
const CHART_OPTIONS = [
3031
{ text: "Staked PNK", value: "stakedPNK" },
32+
{ text: "Staked PNK per court", value: "stakedPNKPerCourt" },
3133
{ text: "Cases", value: "cases" },
3234
{ text: "Cases per court", value: "casesPerCourt" },
3335
];
@@ -81,18 +83,35 @@ const Chart: React.FC = () => {
8183
{ labels: [], cases: [], totalCases: 0 }
8284
);
8385

86+
const processedStakedPNKData = courtsChartData?.reduce(
87+
(accData: StakedPNKByCourtsChartData, current) => {
88+
return {
89+
labels: [...accData.labels, current.name ?? ""],
90+
stakes: [...accData.stakes, parseFloat(formatUnits(current.stake, 18))],
91+
totalStake: accData.totalStake + parseFloat(formatUnits(current.stake, 18)),
92+
};
93+
},
94+
{ labels: [], stakes: [], totalStake: 0 }
95+
);
96+
8497
const ChartComponent = useMemo(() => {
8598
switch (chartOption) {
8699
case "casesPerCourt":
87100
return processedCourtsData ? (
88101
<CasesByCourtsChart data={processedCourtsData} />
89102
) : (
90-
<StyledSkeleton height={233} />
103+
<StyledSkeleton height={234} />
104+
);
105+
case "stakedPNKPerCourt":
106+
return processedStakedPNKData ? (
107+
<StakedPNKByCourtsChart data={processedStakedPNKData} />
108+
) : (
109+
<StyledSkeleton height={234} />
91110
);
92111
default:
93-
return processedData ? <TimeSeriesChart data={processedData} /> : <StyledSkeleton height={233} />;
112+
return processedData ? <TimeSeriesChart data={processedData} /> : <StyledSkeleton height={234} />;
94113
}
95-
}, [processedCourtsData, processedData, chartOption]);
114+
}, [processedCourtsData, processedStakedPNKData, processedData, chartOption]);
96115

97116
return (
98117
<Container>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from "react";
2+
import BarChart, { IBarChartData } from "./BarChart";
3+
4+
export type StakedPNKByCourtsChartData = { labels: string[]; stakes: number[]; totalStake: number };
5+
6+
interface IStakedPNKByCourtsChart {
7+
data: StakedPNKByCourtsChartData;
8+
}
9+
10+
const StakedPNKByCourtsChart: React.FC<IStakedPNKByCourtsChart> = ({ data }) => {
11+
const chartData: IBarChartData = {
12+
labels: data.labels,
13+
data: data.stakes,
14+
total: data.totalStake,
15+
};
16+
17+
return <BarChart chartData={chartData} />;
18+
};
19+
20+
export default StakedPNKByCourtsChart;

0 commit comments

Comments
 (0)