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)} + + + + + + + ))} + + + ) : ( { 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);