Added a general stats component

This commit is contained in:
2025-09-10 19:36:14 +02:00
parent 425bdda9c4
commit cdb500bac2
12 changed files with 369 additions and 468 deletions

View File

@@ -0,0 +1,31 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { ReactNode } from "react"
import CollapsedStats from "../_components/CollapsedStats"
export default function GeneralStats(
{ id, title, children, collapsedStats }: {
id: string
title: string
children: ReactNode
collapsedStats: Parameters<typeof CollapsedStats>[0]["stats"]
}
) {
return (
<AccordionItem value={id}>
<Card className="py-0">
<CardContent>
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer">
<h1 className="text-xl font-bold">{title}</h1>
<div className="flex gap-4">
<CollapsedStats stats={collapsedStats} />
</div>
</AccordionTrigger>
<AccordionContent>
{children}
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
)
}

View File

@@ -1,11 +1,9 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters" import { formatNumber } from "@/lib/formatters"
import { getBedwarsLevelForExp, getTotalBedwarsExpForLevel } from "@/lib/hypixel/bedwars/level" import { getBedwarsLevelForExp, getTotalBedwarsExpForLevel } from "@/lib/hypixel/bedwars/level"
import { devide, getProgress } from "@/lib/hypixel/general" import { devide, getProgress } from "@/lib/hypixel/general"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import { BedwarsLevel, BedwarsProgress } from "./components" import { BedwarsLevel, BedwarsProgress } from "./components"
import BedwarsGeneralStats from "./stats" import BedwarsGeneralStats from "./stats"
import BedwarsStatTable from "./table" import BedwarsStatTable from "./table"
@@ -27,51 +25,41 @@ export default function BedwarsStats({ stats }: { stats: NonNullStats["Bedwars"]
const ceilingXp = next - current const ceilingXp = next - current
return ( return (
<AccordionItem value="bedwars"> <GeneralStats
<Card className="py-0"> id="bedwars"
<CardContent> title="BedWars"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[
<h1 className="text-xl font-bold">BedWars</h1> {
<div className="flex gap-4"> title: <p>Level</p>,
<CollapsedStats stat: <BedwarsLevel xp={stats.Experience} />
stats={[ },
{ {
title: <p>Level</p>, title: <p>WS</p>,
stat: <BedwarsLevel xp={stats.Experience} /> stat: <p className="text-muted-foreground">{stats.winstreak ?? "?"}</p>
}, },
{ {
title: <p>WS</p>, title: <p>KD</p>,
stat: <p className="text-muted-foreground">{stats.winstreak ?? "?"}</p> stat: <p className="text-muted-foreground">{kd}</p>
}, },
{ {
title: <p>KD</p>, title: <p>FKD</p>,
stat: <p className="text-muted-foreground">{kd}</p> stat: <p className="text-muted-foreground">{fkd}</p>
}, },
{ {
title: <p>FKD</p>, title: <p>WL</p>,
stat: <p className="text-muted-foreground">{fkd}</p> stat: <p className="text-muted-foreground">{wl}</p>
}, },
{ {
title: <p>WL</p>, title: <p>BBL</p>,
stat: <p className="text-muted-foreground">{wl}</p> stat: <p className="text-muted-foreground">{bbl}</p>
}, }
{ ]}
title: <p>BBL</p>, >
stat: <p className="text-muted-foreground">{bbl}</p> <Separator className="my-4" />
} <BedwarsProgress level={level} percent={percent} currentXp={xpProgress} ceilingXp={ceilingXp} />
]} <BedwarsGeneralStats stats={stats} level={level} percent={percent} bbl={bbl} kd={kd} fkd={fkd} wl={wl} />
/> <Separator className="my-4" />
</div> <BedwarsStatTable stats={stats} />
</AccordionTrigger> </GeneralStats>
<AccordionContent>
<Separator className="my-4" />
<BedwarsProgress level={level} percent={percent} currentXp={xpProgress} ceilingXp={ceilingXp} />
<BedwarsGeneralStats stats={stats} level={level} percent={percent} bbl={bbl} kd={kd} fkd={fkd} wl={wl} />
<Separator className="my-4" />
<BedwarsStatTable stats={stats} />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,11 +1,9 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters" import { formatNumber } from "@/lib/formatters"
import { getBuildBattleRank } from "@/lib/hypixel/build-battle/general" import { getBuildBattleRank } from "@/lib/hypixel/build-battle/general"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import BuildBattleTitleProgress from "./progress" import BuildBattleTitleProgress from "./progress"
import BuildBattleGeneralStats from "./stats" import BuildBattleGeneralStats from "./stats"
import BuildBattleStatsTable from "./table" import BuildBattleStatsTable from "./table"
@@ -16,37 +14,27 @@ export default function BuildBattleStats({ stats }: { stats: NonNullStats["Build
const rank = getBuildBattleRank(stats.score) const rank = getBuildBattleRank(stats.score)
return ( return (
<AccordionItem value="build-battle"> <GeneralStats
<Card className="py-0"> id="build-battle"
<CardContent> title="Build Battle"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[
<h1 className="text-xl font-bold">Build Battle</h1> {
<div className="flex gap-4"> title: <p>Title</p>,
<CollapsedStats stat: <p className={cn(rank.bold && "font-bold", `text-mc-${rank.color}`)}>{rank.name}</p>
stats={[ },
{ {
title: <p>Title</p>, title: <p>Wins</p>,
stat: <p className={cn(rank.bold && "font-bold", `text-mc-${rank.color}`)}>{rank.name}</p> stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p>
}, }
{ ]}
title: <p>Wins</p>, >
stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p> <Separator className="my-4" />
} <BuildBattleTitleProgress score={stats.score} />
]} <Separator className="my-4" />
/> <BuildBattleGeneralStats stats={stats} />
</div> <Separator className="my-4" />
</AccordionTrigger> <BuildBattleStatsTable stats={stats} />
<AccordionContent> <Separator className="my-4" />
<Separator className="my-4" /> </GeneralStats>
<BuildBattleTitleProgress score={stats.score} />
<Separator className="my-4" />
<BuildBattleGeneralStats stats={stats} />
<Separator className="my-4" />
<BuildBattleStatsTable stats={stats} />
<Separator className="my-4" />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,11 +1,9 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters" import { formatNumber } from "@/lib/formatters"
import { getCopsAndCrimsScoreColor } from "@/lib/hypixel/copsandcrims/general" import { getCopsAndCrimsScoreColor } from "@/lib/hypixel/copsandcrims/general"
import { devide } from "@/lib/hypixel/general" import { devide } from "@/lib/hypixel/general"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import CopsAndCrimsGeneralStats from "./stats" import CopsAndCrimsGeneralStats from "./stats"
import CopsAndCrimsStatTable from "./table" import CopsAndCrimsStatTable from "./table"
import CopsAndCrimsWeaponStats from "./weapons" import CopsAndCrimsWeaponStats from "./weapons"
@@ -22,45 +20,35 @@ export default function CopsAndCrimsStats({ stats }: { stats: NonNullStats["Cops
const scoreColor = getCopsAndCrimsScoreColor(score) const scoreColor = getCopsAndCrimsScoreColor(score)
return ( return (
<AccordionItem value="cops-and-crims"> <GeneralStats
<Card className="py-0"> id="cops-and-crims"
<CardContent> title="Cops And Crims"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[
<h1 className="text-xl font-bold">Cops And Crims</h1> {
<div className="flex gap-4"> title: <p>Score</p>,
<CollapsedStats stat: <p className={`text-mc-${scoreColor}`}>{formatNumber(score)}</p>
stats={[ },
{ {
title: <p>Score</p>, title: <p>Kills</p>,
stat: <p className={`text-mc-${scoreColor}`}>{formatNumber(score)}</p> stat: <p className="text-muted-foreground">{formatNumber(kills)}</p>
}, },
{ {
title: <p>Kills</p>, title: <p>KD</p>,
stat: <p className="text-muted-foreground">{formatNumber(kills)}</p> stat: <p className="text-muted-foreground">{kd}</p>
}, },
{ {
title: <p>KD</p>, title: <p>Wins</p>,
stat: <p className="text-muted-foreground">{kd}</p> stat: <p className="text-muted-foreground">{formatNumber(wins)}</p>
}, }
{ ]}
title: <p>Wins</p>, >
stat: <p className="text-muted-foreground">{formatNumber(wins)}</p> <Separator className="my-4" />
} <CopsAndCrimsGeneralStats stats={stats} wins={wins} kills={kills} assits={assists} deaths={deaths} />
]} <Separator className="my-4" />
/> <CopsAndCrimsStatTable stats={stats} />
</div> <Separator className="my-4" />
</AccordionTrigger> <CopsAndCrimsWeaponStats stats={stats} />
<AccordionContent> <Separator className="my-4" />
<Separator className="my-4" /> </GeneralStats>
<CopsAndCrimsGeneralStats stats={stats} wins={wins} kills={kills} assits={assists} deaths={deaths} />
<Separator className="my-4" />
<CopsAndCrimsStatTable stats={stats} />
<Separator className="my-4" />
<CopsAndCrimsWeaponStats stats={stats} />
<Separator className="my-4" />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,11 +1,9 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters" import { formatNumber } from "@/lib/formatters"
import { getAllDuelsDivisions, getDuelsMostPlayed } from "@/lib/hypixel/duels/duels" import { getAllDuelsDivisions, getDuelsMostPlayed } from "@/lib/hypixel/duels/duels"
import { devide, romanize } from "@/lib/hypixel/general" import { devide, romanize } from "@/lib/hypixel/general"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import DuelsGeneralStats from "./stats" import DuelsGeneralStats from "./stats"
import DuelsStatsTable from "./table" import DuelsStatsTable from "./table"
@@ -18,63 +16,53 @@ export default function DuelsStats({ stats }: { stats: NonNullStats["Duels"] })
const mostPlayed = getDuelsMostPlayed(stats) const mostPlayed = getDuelsMostPlayed(stats)
return ( return (
<AccordionItem value="duels"> <GeneralStats
<Card className="py-0"> id="duels"
<CardContent> title="Duels"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[
<h1 className="text-xl font-bold">Duels</h1> {
<div className="flex gap-4"> title: <p>Division</p>,
<CollapsedStats stat: (
stats={[ <p>
{ {div !== null ?
title: <p>Division</p>, (
stat: ( <span className={`text-mc-${div.color}`}>
<p> {`${div.name} ${romanize(div.level)}`}
{div !== null ? </span>
( ) :
<span className={`text-mc-${div.color}`}> <span className="text-muted-foreground">-</span>}
{`${div.name} ${romanize(div.level)}`} </p>
</span> )
) : },
<span className="text-muted-foreground">-</span>}
</p>
)
},
{ {
title: <p>Wins</p>, title: <p>Wins</p>,
stat: ( stat: (
<p className="font-bold"> <p className="font-bold">
{mostPlayed !== null ? {mostPlayed !== null ?
( (
<span> <span>
{mostPlayed.name} {mostPlayed.name}
</span> </span>
) : ) :
<span className="text-muted-foreground">-</span>} <span className="text-muted-foreground">-</span>}
</p> </p>
) )
}, },
{ {
title: <p>Wins</p>, title: <p>Wins</p>,
stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p> stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p>
}, },
{ {
title: <p>WL</p>, title: <p>WL</p>,
stat: <p className="text-muted-foreground">{wl}</p> stat: <p className="text-muted-foreground">{wl}</p>
} }
]} ]}
/> >
</div> <Separator className="my-4" />
</AccordionTrigger> <DuelsGeneralStats stats={stats} div={div} kd={kd} wl={wl} />
<AccordionContent> <Separator className="my-4" />
<Separator className="my-4" /> <DuelsStatsTable stats={stats} />
<DuelsGeneralStats stats={stats} div={div} kd={kd} wl={wl} /> </GeneralStats>
<Separator className="my-4" />
<DuelsStatsTable stats={stats} />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,12 +1,10 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters" import { formatNumber } from "@/lib/formatters"
import { devide } from "@/lib/hypixel/general" import { devide } from "@/lib/hypixel/general"
import { getMegaWallsDifficultyColor, getMegawallsMostPlayed } from "@/lib/hypixel/megawalls/general" import { getMegaWallsDifficultyColor, getMegawallsMostPlayed } from "@/lib/hypixel/megawalls/general"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import MegaWallsGeneralStats from "./stats" import MegaWallsGeneralStats from "./stats"
import { MegaWallsClassesTable, MegaWallsModesTable } from "./table" import { MegaWallsClassesTable, MegaWallsModesTable } from "./table"
@@ -20,53 +18,43 @@ export default function MegaWallsStats({ stats }: { stats: NonNullStats["MegaWal
const difficultyColor = getMegaWallsDifficultyColor(mostPlayed !== null ? mostPlayed.difficulty : 1) const difficultyColor = getMegaWallsDifficultyColor(mostPlayed !== null ? mostPlayed.difficulty : 1)
return ( return (
<AccordionItem value="megawalls"> <GeneralStats
<Card className="py-0"> id="megawalls"
<CardContent> title="Mega Walls"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[
<h1 className="text-xl font-bold">Mega Walls</h1> {
<div className="flex gap-4"> title: <p>Main</p>,
<CollapsedStats stat: (
stats={[ <p className={cn(mostPlayed && `text-mc-${difficultyColor}`)}>
{ {mostPlayed !== null ? mostPlayed.name : "Unknown"}
title: <p>Main</p>, </p>
stat: ( )
<p className={cn(mostPlayed && `text-mc-${difficultyColor}`)}> },
{mostPlayed !== null ? mostPlayed.name : "Unknown"} {
</p> title: <p>KD</p>,
) stat: <p className="text-muted-foreground">{kd}</p>
}, },
{ {
title: <p>KD</p>, title: <p>FKD</p>,
stat: <p className="text-muted-foreground">{kd}</p> stat: <p className="text-muted-foreground">{fkd}</p>
}, },
{ {
title: <p>FKD</p>, title: <p>Wins</p>,
stat: <p className="text-muted-foreground">{fkd}</p> stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p>
}, },
{ {
title: <p>Wins</p>, title: <p>WL</p>,
stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p> stat: <p className="text-muted-foreground">{wl}</p>
}, }
{ ]}
title: <p>WL</p>, >
stat: <p className="text-muted-foreground">{wl}</p> <Separator className="my-4" />
} <MegaWallsGeneralStats stats={stats} />
]} <Separator className="my-4" />
/> <MegaWallsClassesTable stats={stats} />
</div> <Separator className="my-4" />
</AccordionTrigger> <MegaWallsModesTable stats={stats} />
<AccordionContent> <Separator className="my-4" />
<Separator className="my-4" /> </GeneralStats>
<MegaWallsGeneralStats stats={stats} />
<Separator className="my-4" />
<MegaWallsClassesTable stats={stats} />
<Separator className="my-4" />
<MegaWallsModesTable stats={stats} />
<Separator className="my-4" />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,9 +1,7 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters" import { formatNumber } from "@/lib/formatters"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import InfectionStats from "./infection" import InfectionStats from "./infection"
import MurderMysteryGeneralStats from "./stats" import MurderMysteryGeneralStats from "./stats"
import MurderMysteryStatTable from "./table" import MurderMysteryStatTable from "./table"
@@ -12,37 +10,27 @@ export default function MurderMysteryStats({ stats }: { stats: NonNullStats["Mur
if (!stats) return null if (!stats) return null
return ( return (
<AccordionItem value="murder-mystery"> <GeneralStats
<Card className="py-0"> id="murder-mystery"
<CardContent> title="Murder Mystery"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[
<h1 className="text-xl font-bold">Murder Mystery</h1> {
<div className="flex gap-4"> title: <p>Kills</p>,
<CollapsedStats stat: <p className="text-muted-foreground">{formatNumber(stats.kills)}</p>
stats={[ },
{ {
title: <p>Kills</p>, title: <p>Wins</p>,
stat: <p className="text-muted-foreground">{formatNumber(stats.kills)}</p> stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p>
}, }
{ ]}
title: <p>Wins</p>, >
stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p> <Separator className="my-4" />
} <MurderMysteryGeneralStats stats={stats} />
]} <Separator className="my-4" />
/> <InfectionStats stats={stats} />
</div> <Separator className="my-4" />
</AccordionTrigger> <MurderMysteryStatTable stats={stats} />
<AccordionContent> <Separator className="my-4" />
<Separator className="my-4" /> </GeneralStats>
<MurderMysteryGeneralStats stats={stats} />
<Separator className="my-4" />
<InfectionStats stats={stats} />
<Separator className="my-4" />
<MurderMysteryStatTable stats={stats} />
<Separator className="my-4" />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,11 +1,9 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters" import { formatNumber } from "@/lib/formatters"
import { devide } from "@/lib/hypixel/general" import { devide } from "@/lib/hypixel/general"
import { getPitPrestige } from "@/lib/hypixel/pit/general" import { getPitPrestige } from "@/lib/hypixel/pit/general"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import PitLevel from "./level" import PitLevel from "./level"
import PitProgress from "./progress" import PitProgress from "./progress"
import PitGeneralStats from "./stats" import PitGeneralStats from "./stats"
@@ -17,39 +15,29 @@ export default function PitStats({ stats }: { stats: NonNullStats["Pit"] }) {
const prestige = getPitPrestige(stats) const prestige = getPitPrestige(stats)
return ( return (
<AccordionItem value="pit"> <GeneralStats
<Card className="py-0"> id="pit"
<CardContent> title="Pit"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[
<h1 className="text-xl font-bold">Pit</h1> {
<div className="flex gap-4"> title: <p>Level</p>,
<CollapsedStats stat: <PitLevel xp={stats.profile.xp} prestige={prestige} />
stats={[ },
{ {
title: <p>Level</p>, title: <p>Kills</p>,
stat: <PitLevel xp={stats.profile.xp} prestige={prestige} /> stat: <p className="text-muted-foreground">{formatNumber(stats.kills)}</p>
}, },
{ {
title: <p>Kills</p>, title: <p>KD</p>,
stat: <p className="text-muted-foreground">{formatNumber(stats.kills)}</p> stat: <p className="text-muted-foreground">{kd}</p>
}, }
{ ]}
title: <p>KD</p>, >
stat: <p className="text-muted-foreground">{kd}</p> <Separator className="my-4" />
} <PitProgress prestige={prestige} xp={stats.profile.xp} />
]} <Separator className="my-4" />
/> <PitGeneralStats stats={stats} />
</div> <Separator className="my-4" />
</AccordionTrigger> </GeneralStats>
<AccordionContent>
<Separator className="my-4" />
<PitProgress prestige={prestige} xp={stats.profile.xp} />
<Separator className="my-4" />
<PitGeneralStats stats={stats} />
<Separator className="my-4" />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,11 +1,9 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters" import { formatNumber } from "@/lib/formatters"
import { devide, getProgress } from "@/lib/hypixel/general" import { devide, getProgress } from "@/lib/hypixel/general"
import { getSkywarsLevel, getSkywarsXpForLevel } from "@/lib/hypixel/skywars/level" import { getSkywarsLevel, getSkywarsXpForLevel } from "@/lib/hypixel/skywars/level"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import { AngelOfDeath, ShardProgress, SkywarsHeads, SkywarsLevel, SkywarsProgress } from "./components" import { AngelOfDeath, ShardProgress, SkywarsHeads, SkywarsLevel, SkywarsProgress } from "./components"
import SkyWarsGeneralStats from "./stats" import SkyWarsGeneralStats from "./stats"
import SkywarsStatTable from "./table" import SkywarsStatTable from "./table"
@@ -34,79 +32,69 @@ export default function SkyWarsStats(
const shardProgress = getProgress(0, stats.shard, 20000) const shardProgress = getProgress(0, stats.shard, 20000)
return ( return (
<AccordionItem value="skywars"> <GeneralStats
<Card className="py-0"> id="skywars"
<CardContent> title="SkyWars"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[
<h1 className="text-xl font-bold">SkyWars</h1> {
<div className="flex gap-4"> title: <p>Level</p>,
<CollapsedStats stat: <SkywarsLevel xp={stats.skywars_experience} icon={stats.selected_prestige_icon} />
stats={[ },
{ {
title: <p>Level</p>, title: <p>KD</p>,
stat: <SkywarsLevel xp={stats.skywars_experience} icon={stats.selected_prestige_icon} /> stat: <p className="text-muted-foreground">{kd}</p>
}, },
{ {
title: <p>KD</p>, title: <p>Wins</p>,
stat: <p className="text-muted-foreground">{kd}</p> stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p>
}, },
{ {
title: <p>Wins</p>, title: <p>WL</p>,
stat: <p className="text-muted-foreground">{formatNumber(stats.wins)}</p> stat: <p className="text-muted-foreground">{wl}</p>
}, }
{ ]}
title: <p>WL</p>, >
stat: <p className="text-muted-foreground">{wl}</p> <Separator className="my-4" />
} <SkywarsProgress level={Math.floor(level)} percent={levelProgress} currentXp={xpProgress} ceilingXp={ceilingXp} />
]} <SkyWarsGeneralStats stats={stats} level={level} />
/> <Separator className="my-4" />
</div> <SkywarsStatTable stats={stats} />
</AccordionTrigger> <Separator className="my-4" />
<AccordionContent> <div className="space-y-2">
<Separator className="my-4" /> <ShardProgress percent={shardProgress} shards={stats.shard} />
<SkywarsProgress level={Math.floor(level)} percent={levelProgress} currentXp={xpProgress} ceilingXp={ceilingXp} /> <AngelOfDeath
<SkyWarsGeneralStats stats={stats} level={level} /> shards={stats.shard}
<Separator className="my-4" /> lifetime_shards={achievements_skywars_opal_obsession * 20000 + stats.shard}
<SkywarsStatTable stats={stats} /> opals={stats.opals}
<Separator className="my-4" /> lifetime_opals={achievements_skywars_opal_obsession}
<div className="space-y-2"> />
<ShardProgress percent={shardProgress} shards={stats.shard} /> <SkywarsHeads
<AngelOfDeath heads={stats.heads}
shards={stats.shard} heads_special={{
lifetime_shards={achievements_skywars_opal_obsession * 20000 + stats.shard} heavenly: stats.heads_heavenly,
opals={stats.opals} divine: stats.heads_divine,
lifetime_opals={achievements_skywars_opal_obsession} decent: stats.heads_decent,
/> eww: stats.heads_eww,
<SkywarsHeads meh: stats.heads_meh,
heads={stats.heads} salty: stats.heads_salty,
heads_special={{ succulent: stats.heads_succulent,
heavenly: stats.heads_heavenly, sweet: stats.heads_sweet,
divine: stats.heads_divine, tasty: stats.heads_tasty,
decent: stats.heads_decent, yucky: stats.heads_yucky
eww: stats.heads_eww, }}
meh: stats.heads_meh, prestigeous={stats.head_collection === undefined
salty: stats.heads_salty, ? []
succulent: stats.heads_succulent, : stats.head_collection.prestigious.map(v => {
sweet: stats.heads_sweet, if (v.username === null) return null
tasty: stats.heads_tasty,
yucky: stats.heads_yucky
}}
prestigeous={stats.head_collection === undefined
? []
: stats.head_collection.prestigious.map(v => {
if (v.username === null) return null
return { return {
username: v.username, username: v.username,
timestamp: v.timestamp, timestamp: v.timestamp,
sacrifice: v.sacrifice sacrifice: v.sacrifice
} }
}).filter(v => v !== null)} }).filter(v => v !== null)}
/> />
</div> </div>
</AccordionContent> </GeneralStats>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,8 +1,6 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import TNTGamesGeneralStats from "./stats" import TNTGamesGeneralStats from "./stats"
import TNTWizardsStats from "./wizards" import TNTWizardsStats from "./wizards"
@@ -10,28 +8,18 @@ export default function TNTGamesStats({ stats }: { stats: NonNullStats["TNTGames
if (!stats) return null if (!stats) return null
return ( return (
<AccordionItem value="tnt-games"> <GeneralStats
<Card className="py-0"> id="tnt-games"
<CardContent> title="TNT Games"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[{
<h1 className="text-xl font-bold">TNT Games</h1> title: <p>Wins</p>,
<div className="flex gap-4"> stat: <p className="text-muted-foreground">{stats.wins}</p>
<CollapsedStats }]}
stats={[{ >
title: <p>Wins</p>, <Separator className="my-4" />
stat: <p className="text-muted-foreground">{stats.wins}</p> <TNTGamesGeneralStats stats={stats} />
}]} <Separator className="my-4" />
/> <TNTWizardsStats stats={stats} />
</div> </GeneralStats>
</AccordionTrigger>
<AccordionContent>
<Separator className="my-4" />
<TNTGamesGeneralStats stats={stats} />
<Separator className="my-4" />
<TNTWizardsStats stats={stats} />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,12 +1,10 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { formatNumber } from "@/lib/formatters" import { formatNumber } from "@/lib/formatters"
import { devide } from "@/lib/hypixel/general" import { devide } from "@/lib/hypixel/general"
import { getUHCStatsCombined } from "@/lib/hypixel/uhc/general" import { getUHCStatsCombined } from "@/lib/hypixel/uhc/general"
import { getUhcStarValue } from "@/lib/hypixel/uhc/level" import { getUhcStarValue } from "@/lib/hypixel/uhc/level"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
import UHCProgress from "./progress" import UHCProgress from "./progress"
import UHCGeneralStats from "./stats" import UHCGeneralStats from "./stats"
import UHCStatTable from "./table" import UHCStatTable from "./table"
@@ -19,40 +17,30 @@ export default function UHCStats({ stats }: { stats: NonNullStats["UHC"] }) {
const star = getUhcStarValue(stats.score) const star = getUhcStarValue(stats.score)
return ( return (
<AccordionItem value="uhc"> <GeneralStats
<Card className="py-0"> id="uhc"
<CardContent> title="UHC"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[
<h1 className="text-xl font-bold">UHC</h1> {
<div className="flex gap-4"> title: <p>Star</p>,
<CollapsedStats stat: <p className="text-mc-gold">{`[${star}✫]`}</p>
stats={[ },
{ {
title: <p>Star</p>, title: <p>KD</p>,
stat: <p className="text-mc-gold">{`[${star}✫]`}</p> stat: <p className="text-muted-foreground">{kd}</p>
}, },
{ {
title: <p>KD</p>, title: <p>Wins</p>,
stat: <p className="text-muted-foreground">{kd}</p> stat: <p className="text-muted-foreground">{formatNumber(combined.wins)}</p>
}, }
{ ]}
title: <p>Wins</p>, >
stat: <p className="text-muted-foreground">{formatNumber(combined.wins)}</p> <Separator className="my-4" />
} <UHCProgress score={stats.score} />
]} <Separator className="my-4" />
/> <UHCGeneralStats stats={stats} kills={combined.kills} deaths={combined.deaths} heads={combined.heads} wins={combined.wins} />
</div> <Separator className="my-4" />
</AccordionTrigger> <UHCStatTable stats={stats} />
<AccordionContent> </GeneralStats>
<Separator className="my-4" />
<UHCProgress score={stats.score} />
<Separator className="my-4" />
<UHCGeneralStats stats={stats} kills={combined.kills} deaths={combined.deaths} heads={combined.heads} wins={combined.wins} />
<Separator className="my-4" />
<UHCStatTable stats={stats} />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }

View File

@@ -1,27 +1,17 @@
import { AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion"
import { Card, CardContent } from "@/components/ui/card"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { NonNullStats } from "@/lib/schema/player" import { NonNullStats } from "@/lib/schema/player"
import CollapsedStats from "../../_components/CollapsedStats" import GeneralStats from "../GeneralStats"
export default function WoolGamesStats({ stats }: { stats: NonNullStats["WoolGames"] }) { export default function WoolGamesStats({ stats }: { stats: NonNullStats["WoolGames"] }) {
if (!stats) return null if (!stats) return null
return ( return (
<AccordionItem value="woolgames"> <GeneralStats
<Card className="py-0"> id="woolgames"
<CardContent> title="Wool Games"
<AccordionTrigger className="items-center py-2 hover:no-underline hover:cursor-pointer"> collapsedStats={[]}
<h1 className="text-xl font-bold">Wool Games</h1> >
<div className="flex gap-4"> <Separator className="my-4" />
<CollapsedStats stats={[]} /> </GeneralStats>
</div>
</AccordionTrigger>
<AccordionContent>
<Separator className="my-4" />
</AccordionContent>
</CardContent>
</Card>
</AccordionItem>
) )
} }