Added more to guild stats sidebar
This commit is contained in:
@@ -1,19 +1,102 @@
|
|||||||
|
import { GenericProgress } from "@/app/(stats)/player/[ign]/_components/generic-progress"
|
||||||
import { ReplaceLinks } from "@/components/link-replace"
|
import { ReplaceLinks } from "@/components/link-replace"
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||||
import { Separator } from "@/components/ui/separator"
|
import { Separator } from "@/components/ui/separator"
|
||||||
import { getColor } from "@/lib/colors"
|
import { getColor } from "@/lib/colors"
|
||||||
|
import { formatDate, formatNumber } from "@/lib/formatters"
|
||||||
|
import { getGame } from "@/lib/hypixel/general/status"
|
||||||
|
import { getGuildExp, getGuildLevel } from "@/lib/hypixel/guild/level"
|
||||||
import { Guild } from "@/lib/schema/guild"
|
import { Guild } from "@/lib/schema/guild"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
type SidebarProps = { guild: Guild["guild"] }
|
type SidebarProps = { guild: Guild["guild"] }
|
||||||
|
|
||||||
export default function Sidebar({ guild }: SidebarProps) {
|
export default function Sidebar({ guild }: SidebarProps) {
|
||||||
const tagColor = getColor(guild.tagColor, "text", "gray")
|
const textColor = getColor(guild.tagColor, "text", "gray")
|
||||||
|
const bgColor = getColor(guild.tagColor, "bg", "gray")
|
||||||
|
const level = getGuildLevel(guild.exp)
|
||||||
|
|
||||||
|
function LevelingProgress() {
|
||||||
|
const percent = (level - Math.floor(level)) * 100
|
||||||
|
const currentXp = getGuildExp(Math.floor(level))
|
||||||
|
const nextXp = getGuildExp(Math.floor(level) + 1)
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p className="font-bold">Leveling Progress</p>
|
||||||
|
<div className="flex gap-2 items-center mt-2">
|
||||||
|
<p className={textColor}>{Math.floor(level)}</p>
|
||||||
|
<GenericProgress
|
||||||
|
percent={percent}
|
||||||
|
tooltipId="guild-level-progress"
|
||||||
|
tooltipContent={`${formatNumber(guild.exp - currentXp)}/${formatNumber(nextXp - currentXp)} GEXP`}
|
||||||
|
className={bgColor}
|
||||||
|
/>
|
||||||
|
<p className={textColor}>{Math.floor(level) + 1}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function GeneralInfo() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">{"Level: "}</span>
|
||||||
|
<span>{formatNumber(level)}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">{"Created: "}</span>
|
||||||
|
<span>{formatDate(guild.created)}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">{"Legacy Rank: "}</span>
|
||||||
|
<span>{guild.legacyRanking !== undefined ? formatNumber(guild.legacyRanking) : "None"}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function Other() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">{"Members: "}</span>
|
||||||
|
<span>{guild.members.length}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">{"Publicly Listed: "}</span>
|
||||||
|
<span>{guild.publiclyListed === true ? "Yes" : "No"}</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">{"Publicly Joinable: "}</span>
|
||||||
|
<span>{guild.joinable === true ? "Yes" : "No"}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function PreferedGames() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>
|
||||||
|
<span className="font-bold">{"Preferred Games: "}</span>
|
||||||
|
{guild.preferredGames === undefined ? <span>No prefered games</span> : (
|
||||||
|
<span>
|
||||||
|
{guild.preferredGames.map(g => {
|
||||||
|
const game = getGame(g)
|
||||||
|
return game?.name || null
|
||||||
|
}).filter(g => g !== null).sort().join(", ")}
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card className="mx-auto w-full lg:mx-0 lg:w-1/4 max-w-120 md:max-w-3/10">
|
<Card className="mx-auto w-full lg:mx-0 lg:w-1/4 max-w-120 md:max-w-3/10">
|
||||||
<CardHeader className="flex justify-center">
|
<CardHeader className="flex justify-center">
|
||||||
<CardTitle className={cn("text-4xl", guild.tag && tagColor)}>
|
<CardTitle className={cn("text-4xl", guild.tag && textColor)}>
|
||||||
{guild.tag !== undefined ? `[${guild.tag}]` : "No Guild Tag"}
|
{guild.tag !== undefined ? `[${guild.tag}]` : "No Guild Tag"}
|
||||||
</CardTitle>
|
</CardTitle>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
@@ -22,6 +105,14 @@ export default function Sidebar({ guild }: SidebarProps) {
|
|||||||
<ReplaceLinks text={guild.description} /> :
|
<ReplaceLinks text={guild.description} /> :
|
||||||
<p>No guild description.</p>}
|
<p>No guild description.</p>}
|
||||||
<Separator className="my-4" />
|
<Separator className="my-4" />
|
||||||
|
<LevelingProgress />
|
||||||
|
<Separator className="my-4" />
|
||||||
|
<GeneralInfo />
|
||||||
|
<Separator className="my-4" />
|
||||||
|
<Other />
|
||||||
|
<Separator className="my-4" />
|
||||||
|
<PreferedGames />
|
||||||
|
<Separator className="my-4" />
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
)
|
)
|
||||||
|
|||||||
17
src/data/hypixel/guild.ts
Normal file
17
src/data/hypixel/guild.ts
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
export const EXP = [
|
||||||
|
100000,
|
||||||
|
150000,
|
||||||
|
250000,
|
||||||
|
500000,
|
||||||
|
750000,
|
||||||
|
1000000,
|
||||||
|
1250000,
|
||||||
|
1500000,
|
||||||
|
2000000,
|
||||||
|
2500000,
|
||||||
|
2500000,
|
||||||
|
2500000,
|
||||||
|
2500000,
|
||||||
|
2500000,
|
||||||
|
3000000
|
||||||
|
] as const
|
||||||
21
src/lib/hypixel/guild/level.ts
Normal file
21
src/lib/hypixel/guild/level.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import { EXP } from "@/data/hypixel/guild"
|
||||||
|
|
||||||
|
export function getGuildLevel(xp: number) {
|
||||||
|
let xpRemaining = xp
|
||||||
|
let level = 0
|
||||||
|
let xpToLevelUp = EXP[level]
|
||||||
|
while (xpRemaining >= xpToLevelUp) {
|
||||||
|
xpRemaining -= xpToLevelUp
|
||||||
|
level++
|
||||||
|
xpToLevelUp = EXP[level > 14 ? 14 : level]
|
||||||
|
}
|
||||||
|
return level + xpRemaining / xpToLevelUp
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getGuildExp(lvl: number) {
|
||||||
|
let xp = 0
|
||||||
|
for (let i = 0; i < lvl; i++) {
|
||||||
|
xp += EXP[i > 14 ? 14 : i]
|
||||||
|
}
|
||||||
|
return xp
|
||||||
|
}
|
||||||
@@ -6,6 +6,9 @@ export const guildSchema = z.object({
|
|||||||
name: z.string().min(1),
|
name: z.string().min(1),
|
||||||
tag: z.string().optional(),
|
tag: z.string().optional(),
|
||||||
tagColor: z.string().optional(),
|
tagColor: z.string().optional(),
|
||||||
|
exp: z.number().default(0),
|
||||||
|
created: z.number(),
|
||||||
|
legacyRanking: z.number().optional(),
|
||||||
members: z.array(z.object({
|
members: z.array(z.object({
|
||||||
uuid: z.string(),
|
uuid: z.string(),
|
||||||
rank: z.string(),
|
rank: z.string(),
|
||||||
@@ -20,7 +23,10 @@ export const guildSchema = z.object({
|
|||||||
created: z.number(),
|
created: z.number(),
|
||||||
priority: z.number()
|
priority: z.number()
|
||||||
})).optional(),
|
})).optional(),
|
||||||
description: z.string().optional()
|
description: z.string().optional(),
|
||||||
|
joinable: z.boolean().default(false),
|
||||||
|
publiclyListed: z.boolean().default(false),
|
||||||
|
preferredGames: z.array(z.string()).optional()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user