diff --git a/src/components/Leaderboard.tsx b/src/components/Leaderboard.tsx
index 0fa1228..812025d 100644
--- a/src/components/Leaderboard.tsx
+++ b/src/components/Leaderboard.tsx
@@ -2,6 +2,7 @@ import { useMemo } from 'react';
import {
Avatar,
Box,
+ Button,
Card,
Group,
Indicator,
@@ -10,6 +11,7 @@ import {
Text,
} from '@mantine/core';
import { Sparkline } from '@mantine/charts';
+import { IconTableExport } from '@tabler/icons-react';
import { useAppSelector } from '../redux/store';
import { selectAllRoundsFromGameId } from '../redux/round.selector';
@@ -25,11 +27,12 @@ interface Props {
function Leaderboard(props: Props) {
const { gameId } = props;
const rounds = useAppSelector((s) => selectAllRoundsFromGameId(s, gameId));
- const game = useAppSelector((s) => selectGameById(s, gameId));
- const { playerNames } = game;
- const playerHistory = useMemo(
+ const { playerNames, name: gameName } = useAppSelector((s) =>
+ selectGameById(s, gameId),
+ );
+ const playerBalanceHistory = useMemo(
() =>
- [...rounds.reverse()].reduce<{
+ [...rounds].reverse().reduce<{
[playerName: string]: number[];
}>(
(acc, cur) =>
@@ -48,16 +51,42 @@ function Leaderboard(props: Props) {
[rounds, playerNames],
);
+ const exportCSV = () => {
+ const headers = ['#', ...playerNames];
+ const rows = [...rounds]
+ .reverse()
+ .map((round, i) => [
+ `#${i + 1}`,
+ ...playerNames.map((player) => formatNumber(round.stats[player])),
+ ]);
+ const total = [
+ 'Total',
+ ...playerNames.map((player) => {
+ const history = playerBalanceHistory[player];
+ return formatNumber(history[history.length - 1]);
+ }),
+ ];
+ const table = [headers, ...rows, total];
+ const blobData = [table.map((r) => r.join(',')).join('\n')];
+ const blob = new Blob(blobData, { type: 'text/csv' });
+ const link = document.createElement('a');
+ link.href = URL.createObjectURL(blob);
+ link.download = `${gameName}.csv`;
+ document.body.appendChild(link);
+ link.click();
+ document.body.removeChild(link);
+ };
+
const dataList = useMemo(
() =>
- Object.keys(playerHistory).map((name) => {
- const history = playerHistory[name];
+ Object.keys(playerBalanceHistory).map((name) => {
+ const history = playerBalanceHistory[name];
return {
name,
stat: history[history.length - 1],
};
}),
- [playerHistory],
+ [playerBalanceHistory],
);
const list = useMemo(
@@ -102,45 +131,49 @@ function Leaderboard(props: Props) {
))}
-
- {list.map((x, i) => (
-
-
-
- {`#${i + 1}`}
-
-
-
- {x.name}
-
-
- {formatNumber(x.stat)}
-
-
-
-
-
-
- ))}
-
+
+ {list.map((x, i) => (
+
+
+
+ {`#${i + 1}`}
+
+
+
+ {x.name}
+
+
+ {formatNumber(x.stat)}
+
+
+
+
+
+
+ ))}
+
+ }
+ onClick={exportCSV}
+ >
+ Xuất CSV
+
+
) : (
{
return '';
};
-export const formatNumber = (n: number) => {
- if (n > 0) return `+${n}`;
- return n;
-};
+export const formatNumber = (n: number) => (n > 0 ? `+${n}` : `${n}`);
export const getSum = (list: number[]) => {
const sum = list.reduce((acc, cur) => acc + cur, 0);