This commit is contained in:
parent
cdf9942924
commit
a15f8f46f9
@ -4,6 +4,7 @@
|
|||||||
import { CategoryScale, Chart, Legend, LinearScale, LineElement, PointElement, Title, Tooltip } from "chart.js";
|
import { CategoryScale, Chart, Legend, LinearScale, LineElement, PointElement, Title, Tooltip } from "chart.js";
|
||||||
import { Line } from "react-chartjs-2";
|
import { Line } from "react-chartjs-2";
|
||||||
import { useIsMobile } from "@/hooks/use-is-mobile";
|
import { useIsMobile } from "@/hooks/use-is-mobile";
|
||||||
|
import { formatDateMinimal, getDaysAgoDate, parseDate } from "@ssr/common/utils/time-utils";
|
||||||
|
|
||||||
Chart.register(LinearScale, CategoryScale, PointElement, LineElement, Title, Tooltip, Legend);
|
Chart.register(LinearScale, CategoryScale, PointElement, LineElement, Title, Tooltip, Legend);
|
||||||
|
|
||||||
@ -17,6 +18,9 @@ export type Axis = {
|
|||||||
title?: { display: boolean; text: string; color?: string };
|
title?: { display: boolean; text: string; color?: string };
|
||||||
ticks?: {
|
ticks?: {
|
||||||
stepSize?: number;
|
stepSize?: number;
|
||||||
|
callback?: (value: number, index: number, values: any) => string;
|
||||||
|
font?: (context: any) => { weight: string; color?: string } | undefined;
|
||||||
|
color?: (context: any) => string | undefined;
|
||||||
};
|
};
|
||||||
reverse?: boolean;
|
reverse?: boolean;
|
||||||
};
|
};
|
||||||
@ -42,12 +46,13 @@ export type DatasetConfig = {
|
|||||||
hideOnMobile?: boolean;
|
hideOnMobile?: boolean;
|
||||||
displayName: string;
|
displayName: string;
|
||||||
position: AxisPosition;
|
position: AxisPosition;
|
||||||
|
precision?: number; // Added precision option here
|
||||||
};
|
};
|
||||||
labelFormatter: (value: number) => string;
|
labelFormatter: (value: number) => string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ChartProps = {
|
export type ChartProps = {
|
||||||
labels: string[];
|
labels: Date[];
|
||||||
datasetConfig: DatasetConfig[];
|
datasetConfig: DatasetConfig[];
|
||||||
histories: Record<string, (number | null)[]>;
|
histories: Record<string, (number | null)[]>;
|
||||||
};
|
};
|
||||||
@ -57,14 +62,21 @@ const generateAxis = (
|
|||||||
reverse: boolean,
|
reverse: boolean,
|
||||||
display: boolean,
|
display: boolean,
|
||||||
position: AxisPosition,
|
position: AxisPosition,
|
||||||
displayName: string
|
displayName: string,
|
||||||
|
precision: number | undefined // Adding precision parameter
|
||||||
): Axis => ({
|
): Axis => ({
|
||||||
id,
|
id,
|
||||||
position,
|
position,
|
||||||
display,
|
display,
|
||||||
grid: { drawOnChartArea: id === "y", color: id === "y" ? "#252525" : "" },
|
grid: { drawOnChartArea: id === "y", color: id === "y" ? "#252525" : "" },
|
||||||
title: { display: true, text: displayName, color: "#ffffff" },
|
title: { display: true, text: displayName, color: "#ffffff" },
|
||||||
ticks: { stepSize: 10 },
|
ticks: {
|
||||||
|
stepSize: 10,
|
||||||
|
callback: (value: number) => {
|
||||||
|
// Apply precision if specified, otherwise default to no decimal places
|
||||||
|
return precision !== undefined ? value.toFixed(precision) : value.toString();
|
||||||
|
},
|
||||||
|
},
|
||||||
reverse,
|
reverse,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -85,6 +97,22 @@ export default function GenericChart({ labels, datasetConfig, histories }: Chart
|
|||||||
x: {
|
x: {
|
||||||
grid: { color: "#252525" },
|
grid: { color: "#252525" },
|
||||||
reverse: false,
|
reverse: false,
|
||||||
|
ticks: {
|
||||||
|
font: (context: any) => {
|
||||||
|
// Make the first of the month bold
|
||||||
|
if (parseDate(context.tick.label).getDate() === 1) {
|
||||||
|
return {
|
||||||
|
weight: "bold",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
color: (context: any) => {
|
||||||
|
if (parseDate(context.tick.label).getDate() === 1) {
|
||||||
|
return "#ffffff";
|
||||||
|
}
|
||||||
|
return "#717171";
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,7 +126,8 @@ export default function GenericChart({ labels, datasetConfig, histories }: Chart
|
|||||||
config.axisConfig.reverse,
|
config.axisConfig.reverse,
|
||||||
isMobile && config.axisConfig.hideOnMobile ? false : config.axisConfig.display,
|
isMobile && config.axisConfig.hideOnMobile ? false : config.axisConfig.display,
|
||||||
config.axisConfig.position,
|
config.axisConfig.position,
|
||||||
config.axisConfig.displayName
|
config.axisConfig.displayName,
|
||||||
|
config.axisConfig.precision // Pass precision from config to generateAxis
|
||||||
);
|
);
|
||||||
|
|
||||||
return generateDataset(config.title, historyArray, config.color, config.axisId);
|
return generateDataset(config.title, historyArray, config.color, config.axisId);
|
||||||
@ -118,6 +147,22 @@ export default function GenericChart({ labels, datasetConfig, histories }: Chart
|
|||||||
legend: { position: "top", labels: { color: "white" } },
|
legend: { position: "top", labels: { color: "white" } },
|
||||||
tooltip: {
|
tooltip: {
|
||||||
callbacks: {
|
callbacks: {
|
||||||
|
title(context: any) {
|
||||||
|
const date = labels[context[0].dataIndex];
|
||||||
|
const currentDate = new Date();
|
||||||
|
const differenceInTime = currentDate.getTime() - new Date(date).getTime();
|
||||||
|
const differenceInDays = Math.ceil(differenceInTime / (1000 * 3600 * 24)) - 1;
|
||||||
|
let formattedDate: string;
|
||||||
|
if (differenceInDays === 0) {
|
||||||
|
formattedDate = "Today";
|
||||||
|
} else if (differenceInDays === 1) {
|
||||||
|
formattedDate = "Yesterday";
|
||||||
|
} else {
|
||||||
|
formattedDate = formatDateMinimal(date);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${formattedDate} ${differenceInDays > 0 ? `(${differenceInDays} day${differenceInDays > 1 ? "s" : ""} ago)` : ""}`;
|
||||||
|
},
|
||||||
label(context: any) {
|
label(context: any) {
|
||||||
const value = Number(context.parsed.y);
|
const value = Number(context.parsed.y);
|
||||||
const config = datasetConfig.find(cfg => cfg.title === context.dataset.label);
|
const config = datasetConfig.find(cfg => cfg.title === context.dataset.label);
|
||||||
@ -128,7 +173,18 @@ export default function GenericChart({ labels, datasetConfig, histories }: Chart
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const data = { labels, datasets };
|
const formattedLabels = labels.map(date => {
|
||||||
|
if (formatDateMinimal(getDaysAgoDate(0)) === formatDateMinimal(date)) {
|
||||||
|
return "Now";
|
||||||
|
}
|
||||||
|
if (formatDateMinimal(getDaysAgoDate(1)) === formatDateMinimal(date)) {
|
||||||
|
return "Yesterday";
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatDateMinimal(date);
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = { labels: formattedLabels, datasets };
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="block h-[360px] w-full relative">
|
<div className="block h-[360px] w-full relative">
|
||||||
|
@ -18,20 +18,6 @@ type Props = {
|
|||||||
datasetConfig: DatasetConfig[];
|
datasetConfig: DatasetConfig[];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set up the labels
|
|
||||||
const labels: string[] = [];
|
|
||||||
const historyDays = 50;
|
|
||||||
for (let day = 0; day < historyDays; day++) {
|
|
||||||
if (day == 0) {
|
|
||||||
labels.push("Now");
|
|
||||||
} else if (day == 1) {
|
|
||||||
labels.push("Yesterday");
|
|
||||||
} else {
|
|
||||||
labels.push(`${day + 1} days ago`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
labels.reverse();
|
|
||||||
|
|
||||||
export default function GenericPlayerChart({ player, datasetConfig }: Props) {
|
export default function GenericPlayerChart({ player, datasetConfig }: Props) {
|
||||||
// Check if player statistics are available
|
// Check if player statistics are available
|
||||||
if (!player.statisticHistory || Object.keys(player.statisticHistory).length === 0) {
|
if (!player.statisticHistory || Object.keys(player.statisticHistory).length === 0) {
|
||||||
@ -48,6 +34,9 @@ export default function GenericPlayerChart({ player, datasetConfig }: Props) {
|
|||||||
histories[config.field] = [];
|
histories[config.field] = [];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const labels: Date[] = [];
|
||||||
|
const historyDays = 50;
|
||||||
|
|
||||||
// Sort the statistic entries by date
|
// Sort the statistic entries by date
|
||||||
const statisticEntries = Object.entries(player.statisticHistory).sort(
|
const statisticEntries = Object.entries(player.statisticHistory).sort(
|
||||||
([a], [b]) => parseDate(a).getTime() - parseDate(b).getTime()
|
([a], [b]) => parseDate(a).getTime() - parseDate(b).getTime()
|
||||||
@ -85,6 +74,7 @@ export default function GenericPlayerChart({ player, datasetConfig }: Props) {
|
|||||||
histories[config.field].push(null);
|
histories[config.field].push(null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
labels.push(targetDate);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the chart with collected data
|
// Render the chart with collected data
|
||||||
|
@ -20,7 +20,7 @@ const datasetConfig: DatasetConfig[] = [
|
|||||||
axisConfig: {
|
axisConfig: {
|
||||||
reverse: true,
|
reverse: true,
|
||||||
display: true,
|
display: true,
|
||||||
displayName: "Global Rank",
|
displayName: "Rank",
|
||||||
position: "left",
|
position: "left",
|
||||||
},
|
},
|
||||||
labelFormatter: (value: number) => `Rank #${formatNumberWithCommas(value)}`,
|
labelFormatter: (value: number) => `Rank #${formatNumberWithCommas(value)}`,
|
||||||
@ -49,6 +49,7 @@ const datasetConfig: DatasetConfig[] = [
|
|||||||
hideOnMobile: true,
|
hideOnMobile: true,
|
||||||
displayName: "PP",
|
displayName: "PP",
|
||||||
position: "right",
|
position: "right",
|
||||||
|
precision: 1,
|
||||||
},
|
},
|
||||||
labelFormatter: (value: number) => `PP ${formatNumberWithCommas(value)}pp`,
|
labelFormatter: (value: number) => `PP ${formatNumberWithCommas(value)}pp`,
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user