mirror of
https://github.com/ershisan99/www.git
synced 2025-12-17 21:09:22 +00:00
fix table styles
This commit is contained in:
@@ -9,7 +9,6 @@ export default async function PlayerPage({
|
|||||||
}: {
|
}: {
|
||||||
params: Promise<{ id: string }>
|
params: Promise<{ id: string }>
|
||||||
}) {
|
}) {
|
||||||
const session = await auth()
|
|
||||||
const { id } = await params
|
const { id } = await params
|
||||||
if (id) {
|
if (id) {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
|
|||||||
@@ -5,14 +5,13 @@ import {
|
|||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipProvider,
|
TooltipProvider,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from '@/components/ui/tooltip'
|
} from '@/components/ui/mobile-tooltip'
|
||||||
import type React from 'react'
|
import type React from 'react'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
|
||||||
import { GamesTable } from '@/app/players/[id]/_components/games-table'
|
import { GamesTable } from '@/app/players/[id]/_components/games-table'
|
||||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
||||||
import { Badge } from '@/components/ui/badge'
|
import { Badge } from '@/components/ui/badge'
|
||||||
import { Card, CardContent, CardHeader } from '@/components/ui/card'
|
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
@@ -78,7 +77,6 @@ export function UserInfo() {
|
|||||||
channel_id: RANKED_CHANNEL,
|
channel_id: RANKED_CHANNEL,
|
||||||
user_id: id,
|
user_id: id,
|
||||||
})
|
})
|
||||||
console.log({ vanillaUserRank, rankedUserRank })
|
|
||||||
|
|
||||||
// Filter games by leaderboard if needed
|
// Filter games by leaderboard if needed
|
||||||
const filteredGamesByLeaderboard =
|
const filteredGamesByLeaderboard =
|
||||||
@@ -142,304 +140,298 @@ export function UserInfo() {
|
|||||||
.at(0)
|
.at(0)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='min-h-screen bg-gradient-to-b from-gray-50 to-gray-100 dark:from-zinc-900 dark:to-zinc-950'>
|
<div className='flex flex-1 flex-col overflow-hidden'>
|
||||||
<div className='container mx-auto'>
|
<div className='mx-auto flex w-[calc(100%-1rem)] max-w-fd-container flex-1 flex-col'>
|
||||||
<Card className='overflow-hidden border-none bg-white py-0 shadow-lg dark:bg-zinc-900'>
|
<div className='py-8'>
|
||||||
<CardHeader className='border-gray-200 border-b bg-white p-6 dark:border-zinc-800 dark:bg-zinc-900'>
|
<div className='flex flex-col items-center gap-6 md:flex-row'>
|
||||||
<div className='flex flex-col items-center gap-6 md:flex-row'>
|
<div className='relative'>
|
||||||
<div className='relative'>
|
<Avatar className='size-24'>
|
||||||
<Avatar className='h-24 w-24 border-4 border-gray-100 shadow-md dark:border-zinc-800'>
|
<AvatarImage
|
||||||
<AvatarImage
|
src={profileData.avatar}
|
||||||
src={profileData.avatar}
|
alt={profileData.username}
|
||||||
alt={profileData.username}
|
/>
|
||||||
/>
|
<AvatarFallback className='bg-violet-50 font-bold text-2xl text-violet-600 dark:bg-violet-900/30 dark:text-violet-300'>
|
||||||
<AvatarFallback className='bg-violet-50 font-bold text-2xl text-violet-600 dark:bg-violet-900/30 dark:text-violet-300'>
|
{profileData.username.slice(0, 2).toUpperCase()}
|
||||||
{profileData.username.slice(0, 2).toUpperCase()}
|
</AvatarFallback>
|
||||||
</AvatarFallback>
|
</Avatar>
|
||||||
</Avatar>
|
</div>
|
||||||
|
|
||||||
|
<div className='text-center md:text-left'>
|
||||||
|
<div className={'flex items-start gap-2'}>
|
||||||
|
<h1 className='font-bold text-3xl text-gray-900 dark:text-white'>
|
||||||
|
{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>
|
</div>
|
||||||
|
|
||||||
<div className='text-center md:text-left'>
|
<p className='text-gray-500 text-sm dark:text-zinc-400'>
|
||||||
<div className={'flex items-start gap-2'}>
|
{firstGame ? (
|
||||||
<h1 className='font-bold text-3xl text-gray-900 dark:text-white'>
|
<>First game: {dateFormatter.format(firstGame.gameTime)}</>
|
||||||
{profileData.username}
|
) : (
|
||||||
</h1>
|
<>No games played yet</>
|
||||||
<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'>
|
|
||||||
{firstGame ? (
|
|
||||||
<>First game: {dateFormatter.format(firstGame.gameTime)}</>
|
|
||||||
) : (
|
|
||||||
<>No games played yet</>
|
|
||||||
)}
|
|
||||||
</p>
|
|
||||||
<div className='mt-2 flex flex-wrap items-center justify-center gap-2 md:justify-start'>
|
|
||||||
{!!rankedLeaderboard && (
|
|
||||||
<Badge
|
|
||||||
variant='outline'
|
|
||||||
className='border-gray-200 bg-gray-50 dark:border-zinc-700 dark:bg-zinc-800'
|
|
||||||
>
|
|
||||||
<Trophy className='mr-1 h-3 w-3 text-violet-500' />
|
|
||||||
<span className='text-gray-700 dark:text-zinc-300'>
|
|
||||||
Ranked Queue:{' '}
|
|
||||||
{isNonNullish(rankedUserRank?.rank)
|
|
||||||
? `#${rankedUserRank.rank}`
|
|
||||||
: 'N/A'}
|
|
||||||
</span>
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
{!!vanillaLeaderboard && (
|
|
||||||
<Badge
|
|
||||||
variant='outline'
|
|
||||||
className='border-gray-200 bg-gray-50 dark:border-zinc-700 dark:bg-zinc-800'
|
|
||||||
>
|
|
||||||
<Trophy className='mr-1 h-3 w-3 text-violet-500' />
|
|
||||||
<span className='text-gray-700 dark:text-zinc-300'>
|
|
||||||
Vanilla Queue:{' '}
|
|
||||||
{isNonNullish(vanillaUserRank?.rank)
|
|
||||||
? `#${vanillaUserRank.rank}`
|
|
||||||
: 'N/A'}
|
|
||||||
</span>
|
|
||||||
</Badge>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
'grid w-full flex-grow grid-cols-2 divide-gray-100 md:w-auto md:grid-cols-3 md:divide-y-0 dark:divide-zinc-800',
|
|
||||||
isNonNullish(rankedUserRank?.mmr) && 'lg:grid-cols-4',
|
|
||||||
isNonNullish(vanillaUserRank?.mmr) && 'lg:grid-cols-4',
|
|
||||||
isNonNullish(rankedUserRank?.mmr) &&
|
|
||||||
isNonNullish(vanillaUserRank?.mmr) &&
|
|
||||||
'lg:grid-cols-5'
|
|
||||||
)}
|
)}
|
||||||
>
|
</p>
|
||||||
<StatsCard
|
<div className='mt-2 flex flex-wrap items-center justify-center gap-2 md:justify-start'>
|
||||||
title='Games'
|
{!!rankedLeaderboard && (
|
||||||
value={profileData.games}
|
<Badge
|
||||||
icon={<BarChart3 className='h-5 w-5 text-violet-500' />}
|
variant='outline'
|
||||||
description='Total matches'
|
className='border-gray-200 bg-gray-50 dark:border-zinc-700 dark:bg-zinc-800'
|
||||||
/>
|
>
|
||||||
<StatsCard
|
<Trophy className='mr-1 h-3 w-3 text-violet-500' />
|
||||||
title='Wins'
|
<span className='text-gray-700 dark:text-zinc-300'>
|
||||||
value={profileData.wins}
|
Ranked Queue:{' '}
|
||||||
icon={<ArrowUpCircle className='h-5 w-5 text-emerald-500' />}
|
{isNonNullish(rankedUserRank?.rank)
|
||||||
description={`${profileData.winRate}% win rate`}
|
? `#${rankedUserRank.rank}`
|
||||||
accentColor='text-emerald-500'
|
: 'N/A'}
|
||||||
/>
|
</span>
|
||||||
<StatsCard
|
</Badge>
|
||||||
title='Losses'
|
|
||||||
value={profileData.losses}
|
|
||||||
icon={<ArrowDownCircle className='h-5 w-5 text-rose-500' />}
|
|
||||||
description={`${profileData.lossRate}% loss rate`}
|
|
||||||
accentColor='text-rose-500'
|
|
||||||
/>
|
|
||||||
{isNonNullish(rankedUserRank?.mmr) && (
|
|
||||||
<StatsCard
|
|
||||||
title='Ranked MMR'
|
|
||||||
value={Math.round(rankedUserRank.mmr)}
|
|
||||||
description={
|
|
||||||
lastRankedGame ? (
|
|
||||||
<span
|
|
||||||
className={cn(
|
|
||||||
'flex items-center',
|
|
||||||
lastRankedGame.mmrChange === 0
|
|
||||||
? 'text-zink-800 dark:text-zink-200'
|
|
||||||
: lastRankedGame.mmrChange > 0
|
|
||||||
? 'text-emerald-500'
|
|
||||||
: 'text-rose-500'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{lastRankedGame.mmrChange === 0 ? (
|
|
||||||
'Tied'
|
|
||||||
) : lastRankedGame.mmrChange > 0 ? (
|
|
||||||
<ChevronUp className='h-3 w-3' />
|
|
||||||
) : (
|
|
||||||
<ChevronDown className='h-3 w-3' />
|
|
||||||
)}
|
|
||||||
{lastRankedGame.mmrChange !== 0
|
|
||||||
? numberFormatter.format(
|
|
||||||
Math.trunc(lastRankedGame.mmrChange)
|
|
||||||
)
|
|
||||||
: null}{' '}
|
|
||||||
last match
|
|
||||||
</span>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
icon={
|
|
||||||
<ShieldHalf className='h-5 w-5 text-zink-800 dark:text-zink-200' />
|
|
||||||
}
|
|
||||||
accentColor='text-zink-800 dark:text-zink-200'
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
{isNonNullish(vanillaUserRank?.mmr) && (
|
{!!vanillaLeaderboard && (
|
||||||
<StatsCard
|
<Badge
|
||||||
title='Vanilla MMR'
|
variant='outline'
|
||||||
value={Math.round(vanillaUserRank.mmr)}
|
className='border-gray-200 bg-gray-50 dark:border-zinc-700 dark:bg-zinc-800'
|
||||||
icon={
|
>
|
||||||
<IceCreamCone className='h-5 w-5 text-zink-800 dark:text-zink-200' />
|
<Trophy className='mr-1 h-3 w-3 text-violet-500' />
|
||||||
}
|
<span className='text-gray-700 dark:text-zinc-300'>
|
||||||
accentColor='text-zink-800 dark:text-zink-200'
|
Vanilla Queue:{' '}
|
||||||
description={
|
{isNonNullish(vanillaUserRank?.rank)
|
||||||
lastVanillaGame ? (
|
? `#${vanillaUserRank.rank}`
|
||||||
<span
|
: 'N/A'}
|
||||||
className={cn(
|
</span>
|
||||||
'flex items-center',
|
</Badge>
|
||||||
lastVanillaGame.mmrChange === 0
|
|
||||||
? 'text-zink-800 dark:text-zink-200'
|
|
||||||
: lastVanillaGame.mmrChange > 0
|
|
||||||
? 'text-emerald-500'
|
|
||||||
: 'text-rose-500'
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{lastVanillaGame.mmrChange === 0 ? (
|
|
||||||
'Tied'
|
|
||||||
) : lastVanillaGame.mmrChange > 0 ? (
|
|
||||||
<ChevronUp className='h-3 w-3' />
|
|
||||||
) : (
|
|
||||||
<ChevronDown className='h-3 w-3' />
|
|
||||||
)}
|
|
||||||
{lastVanillaGame.mmrChange !== 0
|
|
||||||
? numberFormatter.format(
|
|
||||||
Math.trunc(lastVanillaGame.mmrChange)
|
|
||||||
)
|
|
||||||
: null}{' '}
|
|
||||||
last match
|
|
||||||
</span>
|
|
||||||
) : null
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
<div
|
||||||
|
className={cn(
|
||||||
|
'grid w-full flex-grow grid-cols-2 divide-gray-100 md:w-auto md:grid-cols-3 md:divide-y-0 dark:divide-zinc-800',
|
||||||
|
isNonNullish(rankedUserRank?.mmr) && 'lg:grid-cols-4',
|
||||||
|
isNonNullish(vanillaUserRank?.mmr) && 'lg:grid-cols-4',
|
||||||
|
isNonNullish(rankedUserRank?.mmr) &&
|
||||||
|
isNonNullish(vanillaUserRank?.mmr) &&
|
||||||
|
'lg:grid-cols-5'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<StatsCard
|
||||||
|
title='Games'
|
||||||
|
value={profileData.games}
|
||||||
|
icon={<BarChart3 className='h-5 w-5 text-violet-500' />}
|
||||||
|
description='Total matches'
|
||||||
|
/>
|
||||||
|
<StatsCard
|
||||||
|
title='Wins'
|
||||||
|
value={profileData.wins}
|
||||||
|
icon={<ArrowUpCircle className='h-5 w-5 text-emerald-500' />}
|
||||||
|
description={`${profileData.winRate}% win rate`}
|
||||||
|
accentColor='text-emerald-500'
|
||||||
|
/>
|
||||||
|
<StatsCard
|
||||||
|
title='Losses'
|
||||||
|
value={profileData.losses}
|
||||||
|
icon={<ArrowDownCircle className='h-5 w-5 text-rose-500' />}
|
||||||
|
description={`${profileData.lossRate}% loss rate`}
|
||||||
|
accentColor='text-rose-500'
|
||||||
|
/>
|
||||||
|
{isNonNullish(rankedUserRank?.mmr) && (
|
||||||
|
<StatsCard
|
||||||
|
title='Ranked MMR'
|
||||||
|
value={Math.round(rankedUserRank.mmr)}
|
||||||
|
description={
|
||||||
|
lastRankedGame ? (
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
'flex items-center',
|
||||||
|
lastRankedGame.mmrChange === 0
|
||||||
|
? 'text-zink-800 dark:text-zink-200'
|
||||||
|
: lastRankedGame.mmrChange > 0
|
||||||
|
? 'text-emerald-500'
|
||||||
|
: 'text-rose-500'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{lastRankedGame.mmrChange === 0 ? (
|
||||||
|
'Tied'
|
||||||
|
) : lastRankedGame.mmrChange > 0 ? (
|
||||||
|
<ChevronUp className='h-3 w-3' />
|
||||||
|
) : (
|
||||||
|
<ChevronDown className='h-3 w-3' />
|
||||||
|
)}
|
||||||
|
{lastRankedGame.mmrChange !== 0
|
||||||
|
? numberFormatter.format(
|
||||||
|
Math.trunc(lastRankedGame.mmrChange)
|
||||||
|
)
|
||||||
|
: null}{' '}
|
||||||
|
last match
|
||||||
|
</span>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
icon={
|
||||||
|
<ShieldHalf className='h-5 w-5 text-zink-800 dark:text-zink-200' />
|
||||||
|
}
|
||||||
|
accentColor='text-zink-800 dark:text-zink-200'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{isNonNullish(vanillaUserRank?.mmr) && (
|
||||||
|
<StatsCard
|
||||||
|
title='Vanilla MMR'
|
||||||
|
value={Math.round(vanillaUserRank.mmr)}
|
||||||
|
icon={
|
||||||
|
<IceCreamCone className='h-5 w-5 text-zink-800 dark:text-zink-200' />
|
||||||
|
}
|
||||||
|
accentColor='text-zink-800 dark:text-zink-200'
|
||||||
|
description={
|
||||||
|
lastVanillaGame ? (
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
'flex items-center',
|
||||||
|
lastVanillaGame.mmrChange === 0
|
||||||
|
? 'text-zink-800 dark:text-zink-200'
|
||||||
|
: lastVanillaGame.mmrChange > 0
|
||||||
|
? 'text-emerald-500'
|
||||||
|
: 'text-rose-500'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{lastVanillaGame.mmrChange === 0 ? (
|
||||||
|
'Tied'
|
||||||
|
) : lastVanillaGame.mmrChange > 0 ? (
|
||||||
|
<ChevronUp className='h-3 w-3' />
|
||||||
|
) : (
|
||||||
|
<ChevronDown className='h-3 w-3' />
|
||||||
|
)}
|
||||||
|
{lastVanillaGame.mmrChange !== 0
|
||||||
|
? numberFormatter.format(
|
||||||
|
Math.trunc(lastVanillaGame.mmrChange)
|
||||||
|
)
|
||||||
|
: null}{' '}
|
||||||
|
last match
|
||||||
|
</span>
|
||||||
|
) : null
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<CardContent className='p-0'>
|
<Tabs defaultValue='matches' className='p-6'>
|
||||||
<Tabs defaultValue='matches' className='p-6'>
|
<div className='mb-6 flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center'>
|
||||||
<div className='mb-6 flex flex-col items-start justify-between gap-4 sm:flex-row sm:items-center'>
|
<TabsList className='bg-gray-100 dark:bg-zinc-800'>
|
||||||
<TabsList className='bg-gray-100 dark:bg-zinc-800'>
|
<TabsTrigger value='matches'>Match History</TabsTrigger>
|
||||||
<TabsTrigger value='matches'>Match History</TabsTrigger>
|
<TabsTrigger value='stats'>Statistics</TabsTrigger>
|
||||||
<TabsTrigger value='stats'>Statistics</TabsTrigger>
|
<TabsTrigger value='achievements'>Achievements</TabsTrigger>
|
||||||
<TabsTrigger value='achievements'>Achievements</TabsTrigger>
|
</TabsList>
|
||||||
</TabsList>
|
|
||||||
|
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
<div className='mr-2 flex items-center gap-2'>
|
<div className='mr-2 flex items-center gap-2'>
|
||||||
<Trophy className='h-4 w-4 text-gray-400 dark:text-zinc-400' />
|
<Trophy className='h-4 w-4 text-gray-400 dark:text-zinc-400' />
|
||||||
<Select
|
<Select
|
||||||
value={leaderboardFilter}
|
value={leaderboardFilter}
|
||||||
onValueChange={setLeaderboardFilter}
|
onValueChange={setLeaderboardFilter}
|
||||||
>
|
>
|
||||||
<SelectTrigger className='h-9 w-[150px]'>
|
<SelectTrigger className='h-9 w-[150px]'>
|
||||||
<SelectValue placeholder='Leaderboard' />
|
<SelectValue placeholder='Leaderboard' />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
<SelectItem value='all'>All Leaderboards</SelectItem>
|
<SelectItem value='all'>All Leaderboards</SelectItem>
|
||||||
<SelectItem value='ranked'>Ranked</SelectItem>
|
<SelectItem value='ranked'>Ranked</SelectItem>
|
||||||
<SelectItem value='vanilla'>Vanilla</SelectItem>
|
<SelectItem value='vanilla'>Vanilla</SelectItem>
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
|
||||||
|
|
||||||
<Filter className='h-4 w-4 text-gray-400 dark:text-zinc-400' />
|
|
||||||
<Select value={filter} onValueChange={setFilter}>
|
|
||||||
<SelectTrigger className='h-9 w-[120px]'>
|
|
||||||
<SelectValue placeholder='Filter' />
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
<SelectItem value='all'>All Games</SelectItem>
|
|
||||||
<SelectItem value='wins'>Wins</SelectItem>
|
|
||||||
<SelectItem value='losses'>Losses</SelectItem>
|
|
||||||
<SelectItem value='ties'>Ties</SelectItem>
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TabsContent value='matches' className='m-0'>
|
<Filter className='h-4 w-4 text-gray-400 dark:text-zinc-400' />
|
||||||
<div className='overflow-hidden rounded-lg border'>
|
<Select value={filter} onValueChange={setFilter}>
|
||||||
<div className='overflow-x-auto'>
|
<SelectTrigger className='h-9 w-[120px]'>
|
||||||
<GamesTable games={filteredGames} />
|
<SelectValue placeholder='Filter' />
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
<SelectItem value='all'>All Games</SelectItem>
|
||||||
|
<SelectItem value='wins'>Wins</SelectItem>
|
||||||
|
<SelectItem value='losses'>Losses</SelectItem>
|
||||||
|
<SelectItem value='ties'>Ties</SelectItem>
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<TabsContent value='matches' className='m-0'>
|
||||||
|
<div className='overflow-hidden rounded-lg border'>
|
||||||
|
<div className='overflow-x-auto'>
|
||||||
|
<GamesTable games={filteredGames} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
|
<TabsContent value='stats' className='m-0'>
|
||||||
|
<div className='grid grid-cols-1 gap-6 md:grid-cols-2'>
|
||||||
|
{(rankedLeaderboard || lastRankedGame) && (
|
||||||
|
<LeaderboardStatsCard
|
||||||
|
title='Ranked Queue Stats'
|
||||||
|
rank={rankedUserRank?.rank}
|
||||||
|
mmr={
|
||||||
|
lastRankedGame
|
||||||
|
? Math.trunc(
|
||||||
|
lastRankedGame.playerMmr + lastRankedGame.mmrChange
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
icon={<Trophy className='h-5 w-5 text-violet-500' />}
|
||||||
|
accentColor='text-violet-500'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{(vanillaLeaderboard || lastVanillaGame) && (
|
||||||
|
<LeaderboardStatsCard
|
||||||
|
title='Vanilla Queue Stats'
|
||||||
|
rank={vanillaUserRank?.rank}
|
||||||
|
mmr={
|
||||||
|
lastVanillaGame
|
||||||
|
? Math.trunc(
|
||||||
|
lastVanillaGame.playerMmr + lastVanillaGame.mmrChange
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
icon={<Star className='h-5 w-5 text-amber-500' />}
|
||||||
|
accentColor='text-amber-500'
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{!rankedLeaderboard &&
|
||||||
|
!vanillaLeaderboard &&
|
||||||
|
!lastRankedGame &&
|
||||||
|
!lastVanillaGame && (
|
||||||
|
<div className='col-span-2 flex h-40 items-center justify-center rounded-lg border bg-gray-50 dark:bg-zinc-800/50'>
|
||||||
|
<p className='text-gray-500 dark:text-zinc-400'>
|
||||||
|
No leaderboard data available
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)}
|
||||||
</TabsContent>
|
</div>
|
||||||
|
</TabsContent>
|
||||||
|
|
||||||
<TabsContent value='stats' className='m-0'>
|
<TabsContent value='achievements' className='m-0'>
|
||||||
<div className='grid grid-cols-1 gap-6 md:grid-cols-2'>
|
<div className='flex h-40 items-center justify-center rounded-lg border bg-gray-50 dark:bg-zinc-800/50'>
|
||||||
{(rankedLeaderboard || lastRankedGame) && (
|
<p className='text-gray-500 dark:text-zinc-400'>
|
||||||
<LeaderboardStatsCard
|
Achievements coming soon
|
||||||
title='Ranked Queue Stats'
|
</p>
|
||||||
rank={rankedUserRank?.rank}
|
</div>
|
||||||
mmr={
|
</TabsContent>
|
||||||
lastRankedGame
|
</Tabs>
|
||||||
? Math.trunc(
|
|
||||||
lastRankedGame.playerMmr +
|
|
||||||
lastRankedGame.mmrChange
|
|
||||||
)
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
icon={<Trophy className='h-5 w-5 text-violet-500' />}
|
|
||||||
accentColor='text-violet-500'
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{(vanillaLeaderboard || lastVanillaGame) && (
|
|
||||||
<LeaderboardStatsCard
|
|
||||||
title='Vanilla Queue Stats'
|
|
||||||
rank={vanillaUserRank?.rank}
|
|
||||||
mmr={
|
|
||||||
lastVanillaGame
|
|
||||||
? Math.trunc(
|
|
||||||
lastVanillaGame.playerMmr +
|
|
||||||
lastVanillaGame.mmrChange
|
|
||||||
)
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
icon={<Star className='h-5 w-5 text-amber-500' />}
|
|
||||||
accentColor='text-amber-500'
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{!rankedLeaderboard &&
|
|
||||||
!vanillaLeaderboard &&
|
|
||||||
!lastRankedGame &&
|
|
||||||
!lastVanillaGame && (
|
|
||||||
<div className='col-span-2 flex h-40 items-center justify-center rounded-lg border bg-gray-50 dark:bg-zinc-800/50'>
|
|
||||||
<p className='text-gray-500 dark:text-zinc-400'>
|
|
||||||
No leaderboard data available
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
|
||||||
|
|
||||||
<TabsContent value='achievements' className='m-0'>
|
|
||||||
<div className='flex h-40 items-center justify-center rounded-lg border bg-gray-50 dark:bg-zinc-800/50'>
|
|
||||||
<p className='text-gray-500 dark:text-zinc-400'>
|
|
||||||
Achievements coming soon
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
|
||||||
</Tabs>
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ export function LeaderboardPage() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='flex flex-1 flex-col overflow-hidden'>
|
<div className='flex flex-1 flex-col overflow-hidden'>
|
||||||
<div className=' mx-auto flex w-[calc(100%-1rem)] max-w-fd-container flex-1 flex-col'>
|
<div className='mx-auto flex w-[calc(100%-1rem)] max-w-fd-container flex-1 flex-col'>
|
||||||
<div className='flex flex-1 flex-col overflow-hidden border-none'>
|
<div className='flex flex-1 flex-col overflow-hidden border-none'>
|
||||||
<Tabs
|
<Tabs
|
||||||
defaultValue={leaderboardType}
|
defaultValue={leaderboardType}
|
||||||
@@ -273,7 +273,7 @@ function RawLeaderboardTable({
|
|||||||
<div
|
<div
|
||||||
ref={tableContainerRef}
|
ref={tableContainerRef}
|
||||||
className='flex-1 overflow-auto overflow-x-auto'
|
className='flex-1 overflow-auto overflow-x-auto'
|
||||||
style={{ maxHeight: 'calc(100vh - 300px)' }}
|
style={{ maxHeight: 'calc(100vh - 200px)' }}
|
||||||
>
|
>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHeader className='sticky top-0 z-10 bg-white dark:bg-zinc-900'>
|
<TableHeader className='sticky top-0 z-10 bg-white dark:bg-zinc-900'>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import type { ReactNode } from 'react'
|
|||||||
import { source } from '../../../lib/source'
|
import { source } from '../../../lib/source'
|
||||||
|
|
||||||
export default function Layout({ children }: { children: ReactNode }) {
|
export default function Layout({ children }: { children: ReactNode }) {
|
||||||
console.log(baseOptions)
|
|
||||||
return (
|
return (
|
||||||
<DocsLayout {...baseOptions} tree={source.pageTree}>
|
<DocsLayout {...baseOptions} tree={source.pageTree}>
|
||||||
{children}
|
{children}
|
||||||
|
|||||||
71
src/components/ui/mobile-tooltip.tsx
Normal file
71
src/components/ui/mobile-tooltip.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
'use client'
|
||||||
|
|
||||||
|
import type {
|
||||||
|
PopoverContentProps,
|
||||||
|
PopoverProps,
|
||||||
|
PopoverTriggerProps,
|
||||||
|
} from '@radix-ui/react-popover'
|
||||||
|
import type {
|
||||||
|
TooltipContentProps,
|
||||||
|
TooltipProps,
|
||||||
|
TooltipProviderProps,
|
||||||
|
TooltipTriggerProps,
|
||||||
|
} from '@radix-ui/react-tooltip'
|
||||||
|
import { createContext, useContext, useEffect, useState } from 'react'
|
||||||
|
import { Popover, PopoverContent, PopoverTrigger } from './popover'
|
||||||
|
import {
|
||||||
|
Tooltip as OriginalTooltip,
|
||||||
|
TooltipContent as OriginalTooltipContent,
|
||||||
|
TooltipProvider as OriginalTooltipProvider,
|
||||||
|
TooltipTrigger as OriginalTooltipTrigger,
|
||||||
|
} from './tooltip'
|
||||||
|
|
||||||
|
const TouchContext = createContext<boolean | undefined>(undefined)
|
||||||
|
const useTouch = () => useContext(TouchContext)
|
||||||
|
|
||||||
|
export const TooltipProvider = ({
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: TooltipProviderProps) => {
|
||||||
|
const [isTouch, setTouch] = useState<boolean | undefined>(undefined)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setTouch(window.matchMedia('(pointer: coarse)').matches)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TouchContext.Provider value={isTouch}>
|
||||||
|
<OriginalTooltipProvider {...props}>{children}</OriginalTooltipProvider>
|
||||||
|
</TouchContext.Provider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const Tooltip = (props: TooltipProps & PopoverProps) => {
|
||||||
|
const isTouch = useTouch()
|
||||||
|
|
||||||
|
return isTouch ? <Popover {...props} /> : <OriginalTooltip {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TooltipTrigger = (
|
||||||
|
props: TooltipTriggerProps & PopoverTriggerProps
|
||||||
|
) => {
|
||||||
|
const isTouch = useTouch()
|
||||||
|
|
||||||
|
return isTouch ? (
|
||||||
|
<PopoverTrigger {...props} />
|
||||||
|
) : (
|
||||||
|
<OriginalTooltipTrigger {...props} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TooltipContent = (
|
||||||
|
props: TooltipContentProps & PopoverContentProps
|
||||||
|
) => {
|
||||||
|
const isTouch = useTouch()
|
||||||
|
|
||||||
|
return isTouch ? (
|
||||||
|
<PopoverContent {...props} />
|
||||||
|
) : (
|
||||||
|
<OriginalTooltipContent {...props} />
|
||||||
|
)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user