Skip to content

Commit

Permalink
Merge branch 'dev' into feat/devtools
Browse files Browse the repository at this point in the history
  • Loading branch information
jaybuidl committed Oct 14, 2024
2 parents d2a8904 + 3d5ce0e commit a534252
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 93 deletions.
115 changes: 115 additions & 0 deletions web/src/pages/Home/CourtOverview/BarChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import React, { useCallback } from "react";
import styled, { useTheme } from "styled-components";
import {
Chart as ChartJS,
BarElement,
Tooltip,
CategoryScale,
LinearScale,
PointElement,
LineElement,
TimeScale,
ChartOptions,
} from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
import { Bar } from "react-chartjs-2";
import "chartjs-adapter-moment";

ChartJS.register(CategoryScale, LinearScale, PointElement, LineElement, TimeScale, Tooltip);
const formatter = new Intl.NumberFormat("en", { notation: "compact" });

const BarContainer = styled.div`
height: 220px;
margin-top: 16px;
`;

ChartJS.register(BarElement);

export interface IBarChartData {
labels: string[];
data: number[];
total: number;
}

interface IBarChartProps {
chartData: IBarChartData;
}

const BarChart: React.FC<IBarChartProps> = ({ chartData }) => {
const theme = useTheme();
const getPercentValue = useCallback(
(value: number) => `${Math.floor((value * 100) / chartData.total)} %`,
[chartData]
);

const formatPNKValue = useCallback((value: number) => formatter.format(value), []);

const tickSize = 5; // suggested, if that many labels can't fit, chart will use even labels

const options: ChartOptions<"bar"> = {
responsive: true,
maintainAspectRatio: false,
scales: {
x: {
grid: { display: false },
ticks: {
color: theme.secondaryText,
},
},
y: {
grid: { color: theme.stroke, borderDash: [4, 4] },
ticks: {
color: theme.secondaryText,
stepSize: (chartData.total * tickSize) / 100,
callback: (value) => getPercentValue(value),
},
max: chartData.total,
},
},
plugins: {
datalabels: {
anchor: "end",
align: "top",
offset: -4,
color: theme.primaryText,
font: {
weight: "bold",
},
formatter: formatPNKValue,
},
tooltip: {
backgroundColor: theme.whiteBackground,
titleColor: theme.primaryText,
borderColor: theme.stroke,
borderWidth: 1,
displayColors: false,
callbacks: {
label: (context) => getPercentValue(context.parsed.y),
labelTextColor: () => theme.primaryText,
},
},
},
};

return (
<BarContainer>
<Bar
data={{
labels: chartData.labels,
datasets: [
{
data: chartData.data,
backgroundColor: theme.secondaryPurple,
hoverBackgroundColor: theme.primaryBlue,
maxBarThickness: 60,
},
],
}}
options={options}
plugins={[ChartDataLabels]}
/>
</BarContainer>
);
};

export default BarChart;
95 changes: 7 additions & 88 deletions web/src/pages/Home/CourtOverview/CasesByCourtsChart.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
import React, { useCallback } from "react";
import styled, { useTheme } from "styled-components";

import { Chart as ChartJS, BarElement } from "chart.js";
import ChartDataLabels from "chartjs-plugin-datalabels";
import { Bar } from "react-chartjs-2";
import "chartjs-adapter-moment";

const BarContainer = styled.div`
height: 220px;
margin-top: 16px;
`;

ChartJS.register(BarElement);
import React from "react";
import BarChart, { IBarChartData } from "./BarChart";

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

Expand All @@ -20,82 +8,13 @@ interface ICasesByCourtsChart {
}

const CasesByCourtsChart: React.FC<ICasesByCourtsChart> = ({ data }) => {
const theme = useTheme();
const getPercentValue = useCallback((value: number) => `${Math.floor((value * 100) / data.totalCases)} %`, [data]);
const tickSize = 5; // this is suggested, if that many labels can't fit, chart will use even labels

const options = {
responsive: true,
maintainAspectRatio: false,
tooltips: {
position: "nearest",
},
scales: {
x: {
grid: { display: false },
ticks: {
color: theme.secondaryText,
},
},
y: {
grid: { color: theme.stroke, borderDash: [4, 4] },
ticks: {
color: theme.secondaryText,
stepSize: (data.totalCases * tickSize) / 100,
callback: (value) => getPercentValue(value),
},
max: data.totalCases,
},
},
plugins: {
datalabels: {
anchor: "end",
align: "top",
offset: -4,
color: theme.primaryText,
font: {
weight: "bold",
},
},
tooltip: {
backgroundColor: theme.whiteBackground,
titleColor: theme.primaryText,
borderColor: theme.stroke,
borderWidth: 1,
displayColors: false,
callbacks: {
label: (context) => getPercentValue(context.parsed.y),
labelTextColor: () => theme.primaryText,
},
},
},
const chartData: IBarChartData = {
labels: data.labels,
data: data.cases,
total: data.totalCases,
};

return (
<BarContainer>
{
// eslint-disable-next-line
// @ts-ignore
<Bar
{...{
data: {
labels: data.labels,
datasets: [
{
data: data.cases,
backgroundColor: theme.secondaryPurple,
hoverBackgroundColor: theme.primaryBlue,
maxBarThickness: 60,
},
],
},
options,
}}
plugins={[ChartDataLabels]}
/>
}
</BarContainer>
);
return <BarChart chartData={chartData} />;
};

export default CasesByCourtsChart;
25 changes: 22 additions & 3 deletions web/src/pages/Home/CourtOverview/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { responsiveSize } from "styles/responsiveSize";

import { StyledSkeleton } from "components/StyledSkeleton";

import StakedPNKByCourtsChart, { StakedPNKByCourtsChartData } from "./StakedPNKByCourtsChart";
import CasesByCourtsChart, { CasesByCourtsChartData } from "./CasesByCourtsChart";
import TimeSeriesChart from "./TimeSeriesChart";

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

const CHART_OPTIONS = [
{ text: "Staked PNK", value: "stakedPNK" },
{ text: "Staked PNK per court", value: "stakedPNKPerCourt" },
{ text: "Cases", value: "cases" },
{ text: "Cases per court", value: "casesPerCourt" },
];
Expand Down Expand Up @@ -81,18 +83,35 @@ const Chart: React.FC = () => {
{ labels: [], cases: [], totalCases: 0 }
);

const processedStakedPNKData = courtsChartData?.reduce(
(accData: StakedPNKByCourtsChartData, current) => {
return {
labels: [...accData.labels, current.name ?? ""],
stakes: [...accData.stakes, parseFloat(formatUnits(current.stake, 18))],
totalStake: accData.totalStake + parseFloat(formatUnits(current.stake, 18)),
};
},
{ labels: [], stakes: [], totalStake: 0 }
);

const ChartComponent = useMemo(() => {
switch (chartOption) {
case "casesPerCourt":
return processedCourtsData ? (
<CasesByCourtsChart data={processedCourtsData} />
) : (
<StyledSkeleton height={233} />
<StyledSkeleton height={234} />
);
case "stakedPNKPerCourt":
return processedStakedPNKData ? (
<StakedPNKByCourtsChart data={processedStakedPNKData} />
) : (
<StyledSkeleton height={234} />
);
default:
return processedData ? <TimeSeriesChart data={processedData} /> : <StyledSkeleton height={233} />;
return processedData ? <TimeSeriesChart data={processedData} /> : <StyledSkeleton height={234} />;
}
}, [processedCourtsData, processedData, chartOption]);
}, [processedCourtsData, processedStakedPNKData, processedData, chartOption]);

return (
<Container>
Expand Down
5 changes: 3 additions & 2 deletions web/src/pages/Home/CourtOverview/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import React from "react";
import styled from "styled-components";

import { responsiveSize } from "styles/responsiveSize";

import { useNavigate } from "react-router-dom";

import { Button } from "@kleros/ui-components-library";

import Bookmark from "svgs/icons/bookmark.svg";

import { responsiveSize } from "styles/responsiveSize";

const StyledHeader = styled.div`
display: flex;
flex-wrap: wrap;
justify-content: space-between;
gap: 0 12px;
margin-bottom: ${responsiveSize(16, 0)};
`;

const StyledH1 = styled.h1`
Expand Down
20 changes: 20 additions & 0 deletions web/src/pages/Home/CourtOverview/StakedPNKByCourtsChart.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from "react";
import BarChart, { IBarChartData } from "./BarChart";

export type StakedPNKByCourtsChartData = { labels: string[]; stakes: number[]; totalStake: number };

interface IStakedPNKByCourtsChart {
data: StakedPNKByCourtsChartData;
}

const StakedPNKByCourtsChart: React.FC<IStakedPNKByCourtsChart> = ({ data }) => {
const chartData: IBarChartData = {
labels: data.labels,
data: data.stakes,
total: data.totalStake,
};

return <BarChart chartData={chartData} />;
};

export default StakedPNKByCourtsChart;

0 comments on commit a534252

Please sign in to comment.