'use client' import { Badge } from '@/components/ui/badge' import { Button } from '@/components/ui/button' import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table' import { cn } from '@/lib/utils' import type { SelectGames } from '@/server/db/types' import { type SortingState, createColumnHelper, flexRender, getCoreRowModel, getSortedRowModel, useReactTable, } from '@tanstack/react-table' import { ArrowDownCircle, ArrowUp, ArrowUpCircle, MinusCircle, } from 'lucide-react' import { useSession } from 'next-auth/react' import { useFormatter } from 'next-intl' import Link from 'next/link' import { useMemo, useState } from 'react' const numberFormatter = new Intl.NumberFormat('en-US', { signDisplay: 'exceptZero', }) const columnHelper = createColumnHelper() function getTranscript(gameNumber: number) { return fetch( `https://api.neatqueue.com/api/transcript/1226193436521267223/${gameNumber}` ).then((res) => res.json()) } function openTranscript(gameNumber: number): void { getTranscript(gameNumber) .then((html: string) => { const newWindow = window.open('', '_blank') if (newWindow) { newWindow.document.write(html) newWindow.document.close() } else { console.error( 'Failed to open new window - popup blocker may be enabled' ) } }) .catch((err) => { console.error('Failed to load transcript:', err) }) } const useColumns = () => { const format = useFormatter() const session = useSession() const isAdmin = session.data?.user.role === 'admin' return useMemo( () => [ columnHelper.accessor('opponentName', { meta: { className: 'pl-4' }, header: 'Opponent', cell: (info) => ( {info.getValue()} ), }), columnHelper.accessor('gameType', { header: 'Game Type', cell: (info) => { const gameType = info.getValue() return ( {info.getValue()} ) }, }), columnHelper.accessor('opponentMmr', { header: 'Opponent MMR', meta: { className: 'justify-end' }, cell: (info) => ( {Math.trunc(info.getValue())} ), }), columnHelper.accessor('playerMmr', { header: 'MMR', meta: { className: 'justify-end' }, cell: (info) => ( {Math.trunc(info.getValue())} ), }), columnHelper.accessor('mmrChange', { header: 'Result', meta: { className: 'justify-end' }, cell: (info) => { const mmrChange = info.getValue() return ( 0 ? 'text-emerald-500' : 'text-rose-500' )} > {numberFormatter.format(Math.trunc(mmrChange))} {mmrChange === 0 ? ( ) : mmrChange > 0 ? ( ) : ( )} ) }, }), columnHelper.accessor('gameTime', { header: 'Date', meta: { className: 'justify-end' }, cell: (info) => ( {format.dateTime(info.getValue(), { year: 'numeric', month: '2-digit', day: '2-digit', })} ), }), columnHelper.accessor('gameTime', { header: 'Time', meta: { className: 'justify-end pr-4' }, cell: (info) => ( {format.dateTime(info.getValue(), { hour: '2-digit', minute: '2-digit', })} ), id: 'time', }), ...(isAdmin ? [ columnHelper.accessor('gameNum', { header: 'Transcript', meta: { className: 'pr-0' }, cell: (info) => ( ), id: 'transcript', }), ] : []), ], [isAdmin] ) } export function GamesTable({ games }: { games: SelectGames[] }) { const [sorting, setSorting] = useState([]) const columns = useColumns() const table = useReactTable({ data: games, columns, state: { sorting, }, onSortingChange: setSorting, getCoreRowModel: getCoreRowModel(), getSortedRowModel: getSortedRowModel(), getRowId: (originalRow) => originalRow.gameNum.toString(), }) return (
{table.getHeaderGroups().map((headerGroup) => ( {headerGroup.headers.map((header) => { const sortDirection = header.column.getIsSorted() return ( ) })} ))} {table.getRowModel().rows.map((row) => ( {row.getVisibleCells().map((cell) => ( {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} ))}
) }