use server name where possible and add a list of aliases

This commit is contained in:
2025-04-04 16:10:42 +02:00
parent fca13e9395
commit 24d39a4132
3 changed files with 46 additions and 112 deletions

View File

@@ -1,97 +0,0 @@
'use client'
import {
Table,
TableBody,
TableCaption,
TableCell,
TableHead,
TableHeader,
TableRow,
} from '@/components/ui/table'
import { cn } from '@/lib/utils'
import { api } from '@/trpc/react'
import { useFormatter } from 'next-intl'
import { useParams } from 'next/navigation'
export function PlayerGames() {
const { id } = useParams()
if (!id || typeof id !== 'string') {
return null
}
const [games] = api.history.user_games.useSuspenseQuery({ user_id: id })
const format = useFormatter()
return (
<Table>
<TableCaption>User's latest games</TableCaption>
<TableHeader>
<TableRow>
<TableHead className='w-[100px]'>Game type</TableHead>
<TableHead>Opponent</TableHead>
<TableHead className='text-right'>Opponent MMR</TableHead>
<TableHead className='text-right'>MMR</TableHead>
<TableHead className='text-right'>Result</TableHead>
<TableHead>Date</TableHead>
<TableHead className='text-right'>Time</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{games.map((game) => {
return (
<TableRow key={game.gameId}>
<TableCell className='font-medium'>{game.gameType}</TableCell>
<TableCell>{game.opponentName}</TableCell>
<TableCell className='text-right font-mono'>
{Math.trunc(game.opponentMmr)}
</TableCell>
<TableCell className='text-right font-mono'>
{Math.trunc(game.playerMmr)}
</TableCell>
<GameResultCell result={game.result} mmrChange={game.mmrChange} />
<TableCell className='text-right font-mono'>
<time dateTime={game.gameTime.toISOString()}>
{format.dateTime(game.gameTime, {
year: 'numeric',
month: '2-digit',
day: '2-digit',
})}
</time>
</TableCell>
<TableCell className='text-right font-mono'>
{format.dateTime(game.gameTime, {
hour: '2-digit',
minute: '2-digit',
})}
</TableCell>
</TableRow>
)
})}
</TableBody>
</Table>
)
}
const numberFormatter = new Intl.NumberFormat('en-US', {
signDisplay: 'exceptZero',
})
function GameResultCell({
result,
mmrChange,
}: { result: string; mmrChange: number }) {
return (
<TableCell
className={cn(
'text-right',
'font-mono',
result === 'win' && 'text-green-600',
result === 'loss' && 'text-red-500',
result === 'tie' && 'text-yellow-500'
)}
>
{numberFormatter.format(Math.trunc(mmrChange))}
</TableCell>
)
}

View File

@@ -1,5 +1,11 @@
'use client' 'use client'
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '@/components/ui/tooltip'
import type React from 'react' import type React from 'react'
import { useState } from 'react' import { useState } from 'react'
@@ -26,6 +32,7 @@ import {
ChevronUp, ChevronUp,
Filter, Filter,
IceCreamCone, IceCreamCone,
InfoIcon,
MinusCircle, MinusCircle,
ShieldHalf, ShieldHalf,
Star, Star,
@@ -104,8 +111,13 @@ export function UserInfo() {
} }
} }
const aliases = [...new Set(games.map((g) => g.playerName))]
console.log(aliases)
const lastGame = games.at(0)
const currentName = lastGame?.playerName ?? discord_user.username
const profileData = { const profileData = {
username: discord_user.username, username: currentName,
avatar: discord_user.avatar_url, avatar: discord_user.avatar_url,
games: games_played, games: games_played,
wins, wins,
@@ -114,7 +126,6 @@ export function UserInfo() {
winRate: games_played > 0 ? Math.round((wins / games_played) * 100) : 0, winRate: games_played > 0 ? Math.round((wins / games_played) * 100) : 0,
} }
const lastGame = games.at(0)
const firstGame = games.at(-1) const firstGame = games.at(-1)
// Get last games for each leaderboard // Get last games for each leaderboard
@@ -144,9 +155,29 @@ export function UserInfo() {
</div> </div>
<div className='text-center md:text-left'> <div className='text-center md:text-left'>
<h1 className='font-bold text-3xl text-gray-900 dark:text-white'> <div className={'flex items-start gap-2'}>
{profileData.username} <h1 className='font-bold text-3xl text-gray-900 dark:text-white'>
</h1> {profileData.username}
</h1>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<InfoIcon className={'size-4'} />
</TooltipTrigger>
<TooltipContent align={'center'} sideOffset={5}>
<div>
<p>Also known as:</p>
<ul className={'list-disc pl-4'}>
{aliases.map((alias) => (
<li key={alias}>{alias}</li>
))}
</ul>
</div>
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
<p className='text-gray-500 text-sm dark:text-zinc-400'> <p className='text-gray-500 text-sm dark:text-zinc-400'>
{firstGame ? ( {firstGame ? (
<>First game: {dateFormatter.format(firstGame.gameTime)}</> <>First game: {dateFormatter.format(firstGame.gameTime)}</>

View File

@@ -1,9 +1,9 @@
"use client" 'use client'
import * as React from "react" import * as TooltipPrimitive from '@radix-ui/react-tooltip'
import * as TooltipPrimitive from "@radix-ui/react-tooltip" import type * as React from 'react'
import { cn } from "@/lib/utils" import { cn } from '@/lib/utils'
function TooltipProvider({ function TooltipProvider({
delayDuration = 0, delayDuration = 0,
@@ -11,7 +11,7 @@ function TooltipProvider({
}: React.ComponentProps<typeof TooltipPrimitive.Provider>) { }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return ( return (
<TooltipPrimitive.Provider <TooltipPrimitive.Provider
data-slot="tooltip-provider" data-slot='tooltip-provider'
delayDuration={delayDuration} delayDuration={delayDuration}
{...props} {...props}
/> />
@@ -23,7 +23,7 @@ function Tooltip({
}: React.ComponentProps<typeof TooltipPrimitive.Root>) { }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
return ( return (
<TooltipProvider> <TooltipProvider>
<TooltipPrimitive.Root data-slot="tooltip" {...props} /> <TooltipPrimitive.Root data-slot='tooltip' {...props} />
</TooltipProvider> </TooltipProvider>
) )
} }
@@ -31,7 +31,7 @@ function Tooltip({
function TooltipTrigger({ function TooltipTrigger({
...props ...props
}: React.ComponentProps<typeof TooltipPrimitive.Trigger>) { }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} /> return <TooltipPrimitive.Trigger data-slot='tooltip-trigger' {...props} />
} }
function TooltipContent({ function TooltipContent({
@@ -43,16 +43,16 @@ function TooltipContent({
return ( return (
<TooltipPrimitive.Portal> <TooltipPrimitive.Portal>
<TooltipPrimitive.Content <TooltipPrimitive.Content
data-slot="tooltip-content" data-slot='tooltip-content'
sideOffset={sideOffset} sideOffset={sideOffset}
className={cn( className={cn(
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance", 'fade-in-0 zoom-in-95 data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) animate-in text-balance rounded-md bg-primary px-3 py-1.5 text-primary-foreground text-xs data-[state=closed]:animate-out',
className className
)} )}
{...props} {...props}
> >
{children} {children}
<TooltipPrimitive.Arrow className="bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" /> <TooltipPrimitive.Arrow className='z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-primary fill-primary' />
</TooltipPrimitive.Content> </TooltipPrimitive.Content>
</TooltipPrimitive.Portal> </TooltipPrimitive.Portal>
) )