Updated to nextjs v16
This commit is contained in:
@@ -17,97 +17,6 @@ export default function Sidebar({ guild }: SidebarProps) {
|
||||
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>
|
||||
<SidebarItem title="Leveling Progress">
|
||||
<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>
|
||||
</SidebarItem>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function GeneralInfo() {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="Level: " value={formatNumber(level)} />
|
||||
<BasicSidebarItem title="Created: " value={formatDate(guild.created)} />
|
||||
<BasicSidebarItem title="Legacy Rank: " value={guild.legacyRanking !== undefined ? formatNumber(guild.legacyRanking) : "None"} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Other() {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="Members: " value={guild.members.length} />
|
||||
<BasicSidebarItem title="Publicly Listed: " value={guild.publiclyListed === true ? "Yes" : "No"} />
|
||||
<BasicSidebarItem title="Publicly Joinable: " value={guild.joinable === true ? "Yes" : "No"} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function PreferedGames() {
|
||||
return (
|
||||
<div>
|
||||
<SidebarItem title="Preferred Games: ">
|
||||
{guild.preferredGames === undefined ?
|
||||
<span className="text-muted-foreground">No prefered games</span> :
|
||||
(
|
||||
<span className="text-muted-foreground">
|
||||
{guild.preferredGames.map(g => {
|
||||
const game = getGame(g)
|
||||
return game?.name || null
|
||||
}).filter(g => g !== null).sort().join(", ")}
|
||||
</span>
|
||||
)}
|
||||
</SidebarItem>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Achievements() {
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold">Achievements</h2>
|
||||
<BasicSidebarItem title="Experience Kings: " value={formatNumber(guild.achievements.EXPERIENCE_KINGS)} />
|
||||
<BasicSidebarItem title="Winners: " value={formatNumber(guild.achievements.WINNERS)} />
|
||||
<BasicSidebarItem title="Online Players: " value={formatNumber(guild.achievements.ONLINE_PLAYERS)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function GameExperience() {
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold">Experience</h2>
|
||||
{guild.guildExpByGameType === undefined ? <p>No EXP in any games</p> : (
|
||||
<div>
|
||||
{Object.entries(guild.guildExpByGameType).map(g => {
|
||||
const game = getGame(g[0])
|
||||
if (!game) return null
|
||||
return { name: game.name, val: g[1] }
|
||||
}).filter(g => g !== null).sort().map((v, i) => {
|
||||
return <BasicSidebarItem key={i} title={`${v.name}: `} value={formatNumber(v.val)} />
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<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">
|
||||
@@ -120,19 +29,110 @@ export default function Sidebar({ guild }: SidebarProps) {
|
||||
<ReplaceLinks text={guild.description} /> :
|
||||
<p>No guild description.</p>}
|
||||
<Separator className="my-4" />
|
||||
<LevelingProgress />
|
||||
<LevelingProgress guild={guild} level={level} textColor={textColor} bgColor={bgColor} />
|
||||
<Separator className="my-4" />
|
||||
<GeneralInfo />
|
||||
<GeneralInfo guild={guild} level={level} />
|
||||
<Separator className="my-4" />
|
||||
<Other />
|
||||
<Other guild={guild} />
|
||||
<Separator className="my-4" />
|
||||
<PreferedGames />
|
||||
<PreferedGames guild={guild} />
|
||||
<Separator className="my-4" />
|
||||
<Achievements />
|
||||
<Achievements guild={guild} />
|
||||
<Separator className="my-4" />
|
||||
<GameExperience />
|
||||
<GameExperience guild={guild} />
|
||||
<Separator className="my-4" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
function LevelingProgress({ guild, level, textColor, bgColor }: { guild: Guild["guild"], level: number, textColor: string, bgColor: string }) {
|
||||
const percent = (level - Math.floor(level)) * 100
|
||||
const currentXp = getGuildExp(Math.floor(level))
|
||||
const nextXp = getGuildExp(Math.floor(level) + 1)
|
||||
return (
|
||||
<div>
|
||||
<SidebarItem title="Leveling Progress">
|
||||
<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>
|
||||
</SidebarItem>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function GeneralInfo({ guild, level }: { guild: Guild["guild"], level: number }) {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="Level: " value={formatNumber(level)} />
|
||||
<BasicSidebarItem title="Created: " value={formatDate(guild.created)} />
|
||||
<BasicSidebarItem title="Legacy Rank: " value={guild.legacyRanking !== undefined ? formatNumber(guild.legacyRanking) : "None"} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Other({ guild }: { guild: Guild["guild"] }) {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="Members: " value={guild.members.length} />
|
||||
<BasicSidebarItem title="Publicly Listed: " value={guild.publiclyListed === true ? "Yes" : "No"} />
|
||||
<BasicSidebarItem title="Publicly Joinable: " value={guild.joinable === true ? "Yes" : "No"} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function PreferedGames({ guild }: { guild: Guild["guild"] }) {
|
||||
return (
|
||||
<div>
|
||||
<SidebarItem title="Preferred Games: ">
|
||||
{guild.preferredGames === undefined ?
|
||||
<span className="text-muted-foreground">No prefered games</span> :
|
||||
(
|
||||
<span className="text-muted-foreground">
|
||||
{guild.preferredGames.map(g => {
|
||||
const game = getGame(g)
|
||||
return game?.name || null
|
||||
}).filter(g => g !== null).sort().join(", ")}
|
||||
</span>
|
||||
)}
|
||||
</SidebarItem>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Achievements({ guild }: { guild: Guild["guild"] }) {
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold">Achievements</h2>
|
||||
<BasicSidebarItem title="Experience Kings: " value={formatNumber(guild.achievements.EXPERIENCE_KINGS)} />
|
||||
<BasicSidebarItem title="Winners: " value={formatNumber(guild.achievements.WINNERS)} />
|
||||
<BasicSidebarItem title="Online Players: " value={formatNumber(guild.achievements.ONLINE_PLAYERS)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function GameExperience({ guild }: { guild: Guild["guild"] }) {
|
||||
return (
|
||||
<div>
|
||||
<h2 className="text-xl font-bold">Experience</h2>
|
||||
{guild.guildExpByGameType === undefined ? <p>No EXP in any games</p> : (
|
||||
<div>
|
||||
{Object.entries(guild.guildExpByGameType).map(g => {
|
||||
const game = getGame(g[0])
|
||||
if (!game) return null
|
||||
return { name: game.name, val: g[1] }
|
||||
}).filter(g => g !== null).sort().map((v, i) => {
|
||||
return <BasicSidebarItem key={i} title={`${v.name}: `} value={formatNumber(v.val)} />
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { CSS } from "@dnd-kit/utilities"
|
||||
import Cookies from "js-cookie"
|
||||
import { GripVertical } from "lucide-react"
|
||||
import { usePathname } from "next/navigation"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
import { useEffect, useEffectEvent, useRef, useState } from "react"
|
||||
|
||||
import { useRouter } from "next/navigation"
|
||||
import ArcadeStats from "./_stats/arcade/arcade"
|
||||
@@ -149,11 +149,18 @@ export function PlayerStats(
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const client = useEffectEvent(() => {
|
||||
setIsClient(true)
|
||||
})
|
||||
const statsOrderFromCookie = useEffectEvent(() => {
|
||||
if (layout && layout.length > 0) {
|
||||
setStatsOrder(layout)
|
||||
}
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
client()
|
||||
statsOrderFromCookie()
|
||||
const cookie = Cookies.get(COOKIE_VALUES.statsOrder)
|
||||
if (cookie) {
|
||||
Cookies.set(COOKIE_VALUES.statsOrder, cookie, cookieOpts.current)
|
||||
|
||||
@@ -30,226 +30,228 @@ export default function Sidebar({ level, ign, player, guild, rank, specialRank,
|
||||
const levelMultiplierVal = levelMultiplier.value
|
||||
const levelMultiplierText = levelMultiplier.level === true ? `(Level ${level.toString().split(".")[0]})` : `(${levelMultiplier.name})`
|
||||
|
||||
function General() {
|
||||
return (
|
||||
<div className="flex justify-between px-8">
|
||||
<div className="text-center">
|
||||
<p>Hypixel level</p>
|
||||
<p>{formatNumber(level)}</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<p>Karma</p>
|
||||
<p className="text-mc-light-purple">{formatNumber(player.karma)}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Coins() {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="Coin multiplier: " value={`x${levelMultiplierVal} ${levelMultiplierText}`} />
|
||||
<SidebarItem title="Total coins: ">
|
||||
<span className="text-mc-gold">
|
||||
{formatNumber(getTotalCoins(player.stats))}
|
||||
</span>
|
||||
</SidebarItem>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Other() {
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
<span>
|
||||
<Link href={`/achievements/${ign}`} className="font-bold underline">
|
||||
Achievement Points
|
||||
</Link>
|
||||
</span>
|
||||
<span className="font-bold">{": "}</span>
|
||||
<span>{formatNumber(player.achievementPoints ?? 0)}</span>
|
||||
</p>
|
||||
<p>
|
||||
<span>
|
||||
<Link href={`/quests/${ign}`} className="font-bold underline">
|
||||
Quests Completed
|
||||
</Link>
|
||||
</span>
|
||||
<span className="font-bold">{": "}</span>
|
||||
<span>{formatNumber(getTotalQuests(player.quests))}</span>
|
||||
</p>
|
||||
<BasicSidebarItem title="Challenges Completed: " value={formatNumber(getTotalChallenges(player.challenges))} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DailyRewards() {
|
||||
return (
|
||||
<div>
|
||||
<SidebarItem title="Today's Reward: ">
|
||||
<span
|
||||
className={`${rewardClaimed(player.lastClaimedReward) === true ? "font-bold text-mc-green" : undefined}`}
|
||||
>
|
||||
{rewardClaimed(player.lastClaimedReward) ? "Claimed" : "Unclaimed"}
|
||||
</span>
|
||||
</SidebarItem>
|
||||
<BasicSidebarItem title="Rewards Claimed: " value={player.totalRewards ?? 0} />
|
||||
<BasicSidebarItem title="Reward Streak: " value={player.rewardStreak ?? 0} />
|
||||
<BasicSidebarItem title="Top Reward Streak: " value={player.rewardHighScore ?? 0} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Gifting() {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="Gifts Given: " value={player.giftingMeta?.giftsGiven ?? 0} />
|
||||
<BasicSidebarItem title="Ranks Given: " value={player.giftingMeta?.ranksGiven ?? 0} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Logins() {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="First Login: " value={formatDate(player.firstLogin ?? 0)} />
|
||||
<BasicSidebarItem title="Last Login: " value={formatDate(player.lastLogin ?? 0)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function SkyblockButton() {
|
||||
return (
|
||||
<Button asChild variant="outline">
|
||||
<Link href={`https://sky.shiiyu.moe/stats/${player.displayname}`}>
|
||||
View SkyBlock Stats
|
||||
</Link>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
function GuildInfo() {
|
||||
if (!guild) return null
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-8">
|
||||
<div>
|
||||
<Link href={`/guild/${ign}`}>
|
||||
<h1 className="text-xl font-bold underline">Guild</h1>
|
||||
</Link>
|
||||
<SidebarItem title="Name: ">
|
||||
<span className={getColor(guild.tagColor, "text", "gray")}>{guild.name}</span>
|
||||
</SidebarItem>
|
||||
<BasicSidebarItem title="Members: " value={guild.members.length} />
|
||||
</div>
|
||||
<div>
|
||||
<SidebarItem title="Rank: ">
|
||||
<span>{`${getGuildMember(guild, player.uuid)?.rank} `}</span>
|
||||
<span className={getColor(guild.tagColor, "text", "gray")}>
|
||||
{getGuildRankTag(guild, player.uuid)}
|
||||
</span>
|
||||
</SidebarItem>
|
||||
<BasicSidebarItem title="Daily GEXP: " value={formatNumber(getMemberGEXP(guild, player.uuid, 0) ?? 0)} />
|
||||
<BasicSidebarItem title="Weekly GEXP: " value={formatNumber(getMemberWeeklyGEXP(guild, player.uuid) ?? 0)} />
|
||||
<BasicSidebarItem title="Joined: " value={formatDate(getGuildMember(guild, player.uuid)?.joined ?? 0)} />
|
||||
</div>
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function OnlineStatus() {
|
||||
if (!session?.online) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-xl font-bold">Online Status</h2>
|
||||
<BasicSidebarItem title="Status: " value="Offline" />
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const noMapGameTypes = ["BUILD_BATTLE", "HOUSING", "REPLAY"]
|
||||
const noMapArcadeModes = [
|
||||
"DAYONE",
|
||||
"DEFENDER",
|
||||
"DRAGONWARS2",
|
||||
"DROPPER",
|
||||
"SOCCER",
|
||||
"STARWARS",
|
||||
"SIMON_SAYS",
|
||||
"PARTY",
|
||||
"DRAW_THEIR_THING",
|
||||
"PIXEL_PARTY",
|
||||
"THROW_OUT"
|
||||
]
|
||||
|
||||
const showMode = !(session.gameType === "REPLAY")
|
||||
const showMap = session.map !== undefined &&
|
||||
session.gameType !== undefined &&
|
||||
!noMapGameTypes.includes(session.gameType) &&
|
||||
session.mode !== undefined &&
|
||||
!(session.gameType === "ARCADE" && noMapArcadeModes.includes(session.mode))
|
||||
const mode = session.mode === "LOBBY" ? "Lobby" : getGameMode(session.gameType, session.mode)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-xl font-bold">Online Status</h2>
|
||||
<div>
|
||||
{session.gameType && <BasicSidebarItem title="Game: " value={getGame(session.gameType)?.name || "Unknown"} />}
|
||||
{showMode && <BasicSidebarItem title="Mode: " value={mode || "Unknown"} />}
|
||||
{showMap && <BasicSidebarItem title="Map: " value={session.map || "Unknown"} />}
|
||||
</div>
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function SoicalLinks() {
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<h1 className="text-xl font-bold underline">Social Links</h1>
|
||||
<div className="flex gap-2">
|
||||
<SocialIcons
|
||||
discord={player?.socialMedia?.links?.DISCORD}
|
||||
twitch={player?.socialMedia?.links?.TWITCH}
|
||||
youtube={player?.socialMedia?.links?.YOUTUBE}
|
||||
twitter={player?.socialMedia?.links?.TWITTER}
|
||||
hypixel={player?.socialMedia?.links?.HYPIXEL}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="mx-auto w-full lg:mx-0 lg:w-1/4 max-w-120 md:max-w-3/10">
|
||||
<CardContent>
|
||||
<General />
|
||||
<General level={level} player={player} />
|
||||
<Separator className="my-4" />
|
||||
<Coins />
|
||||
<Coins levelMultiplierVal={levelMultiplierVal} levelMultiplierText={levelMultiplierText} player={player} />
|
||||
<Separator className="my-4" />
|
||||
<Other />
|
||||
<Other ign={ign} player={player} />
|
||||
<Separator className="my-4" />
|
||||
<DailyRewards />
|
||||
<DailyRewards player={player} />
|
||||
<Separator className="my-4" />
|
||||
<Gifting />
|
||||
<Gifting player={player} />
|
||||
<Separator className="my-4" />
|
||||
<Logins />
|
||||
<Logins player={player} />
|
||||
<Separator className="my-4" />
|
||||
<SkyblockButton />
|
||||
<SkyblockButton player={player} />
|
||||
<Separator className="my-4" />
|
||||
<GuildInfo />
|
||||
<OnlineStatus />
|
||||
<SoicalLinks />
|
||||
<GuildInfo player={player} guild={guild} ign={ign} />
|
||||
<OnlineStatus session={session} />
|
||||
<SoicalLinks {...player.socialMedia?.links} />
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
function General({ level, player }: { level: number, player: Player["player"] }) {
|
||||
return (
|
||||
<div className="flex justify-between px-8">
|
||||
<div className="text-center">
|
||||
<p>Hypixel level</p>
|
||||
<p>{formatNumber(level)}</p>
|
||||
</div>
|
||||
<div className="text-center">
|
||||
<p>Karma</p>
|
||||
<p className="text-mc-light-purple">{formatNumber(player.karma)}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Coins(
|
||||
{ levelMultiplierVal, levelMultiplierText, player }: { levelMultiplierVal: number, levelMultiplierText: string, player: Player["player"] }
|
||||
) {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="Coin multiplier: " value={`x${levelMultiplierVal} ${levelMultiplierText}`} />
|
||||
<SidebarItem title="Total coins: ">
|
||||
<span className="text-mc-gold">
|
||||
{formatNumber(getTotalCoins(player.stats))}
|
||||
</span>
|
||||
</SidebarItem>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Other({ ign, player }: { ign: string, player: Player["player"] }) {
|
||||
return (
|
||||
<div>
|
||||
<p>
|
||||
<span>
|
||||
<Link href={`/achievements/${ign}`} className="font-bold underline">
|
||||
Achievement Points
|
||||
</Link>
|
||||
</span>
|
||||
<span className="font-bold">{": "}</span>
|
||||
<span>{formatNumber(player.achievementPoints ?? 0)}</span>
|
||||
</p>
|
||||
<p>
|
||||
<span>
|
||||
<Link href={`/quests/${ign}`} className="font-bold underline">
|
||||
Quests Completed
|
||||
</Link>
|
||||
</span>
|
||||
<span className="font-bold">{": "}</span>
|
||||
<span>{formatNumber(getTotalQuests(player.quests))}</span>
|
||||
</p>
|
||||
<BasicSidebarItem title="Challenges Completed: " value={formatNumber(getTotalChallenges(player.challenges))} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function DailyRewards({ player }: { player: Player["player"] }) {
|
||||
return (
|
||||
<div>
|
||||
<SidebarItem title="Today's Reward: ">
|
||||
<span
|
||||
className={`${rewardClaimed(player.lastClaimedReward) === true ? "font-bold text-mc-green" : undefined}`}
|
||||
>
|
||||
{rewardClaimed(player.lastClaimedReward) ? "Claimed" : "Unclaimed"}
|
||||
</span>
|
||||
</SidebarItem>
|
||||
<BasicSidebarItem title="Rewards Claimed: " value={player.totalRewards ?? 0} />
|
||||
<BasicSidebarItem title="Reward Streak: " value={player.rewardStreak ?? 0} />
|
||||
<BasicSidebarItem title="Top Reward Streak: " value={player.rewardHighScore ?? 0} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Gifting({ player }: { player: Player["player"] }) {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="Gifts Given: " value={player.giftingMeta?.giftsGiven ?? 0} />
|
||||
<BasicSidebarItem title="Ranks Given: " value={player.giftingMeta?.ranksGiven ?? 0} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Logins({ player }: { player: Player["player"] }) {
|
||||
return (
|
||||
<div>
|
||||
<BasicSidebarItem title="First Login: " value={formatDate(player.firstLogin ?? 0)} />
|
||||
<BasicSidebarItem title="Last Login: " value={formatDate(player.lastLogin ?? 0)} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function SkyblockButton({ player }: { player: Player["player"] }) {
|
||||
return (
|
||||
<Button asChild variant="outline">
|
||||
<Link href={`https://sky.shiiyu.moe/stats/${player.displayname}`}>
|
||||
View SkyBlock Stats
|
||||
</Link>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
function GuildInfo({ guild, ign, player }: { guild: Guild["guild"] | undefined, ign: string, player: Player["player"] }) {
|
||||
if (!guild) return null
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-8">
|
||||
<div>
|
||||
<Link href={`/guild/${ign}`}>
|
||||
<h1 className="text-xl font-bold underline">Guild</h1>
|
||||
</Link>
|
||||
<SidebarItem title="Name: ">
|
||||
<span className={getColor(guild.tagColor, "text", "gray")}>{guild.name}</span>
|
||||
</SidebarItem>
|
||||
<BasicSidebarItem title="Members: " value={guild.members.length} />
|
||||
</div>
|
||||
<div>
|
||||
<SidebarItem title="Rank: ">
|
||||
<span>{`${getGuildMember(guild, player.uuid)?.rank} `}</span>
|
||||
<span className={getColor(guild.tagColor, "text", "gray")}>
|
||||
{getGuildRankTag(guild, player.uuid)}
|
||||
</span>
|
||||
</SidebarItem>
|
||||
<BasicSidebarItem title="Daily GEXP: " value={formatNumber(getMemberGEXP(guild, player.uuid, 0) ?? 0)} />
|
||||
<BasicSidebarItem title="Weekly GEXP: " value={formatNumber(getMemberWeeklyGEXP(guild, player.uuid) ?? 0)} />
|
||||
<BasicSidebarItem title="Joined: " value={formatDate(getGuildMember(guild, player.uuid)?.joined ?? 0)} />
|
||||
</div>
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function OnlineStatus({ session }: { session: Session["session"] | null }) {
|
||||
if (!session?.online) {
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-xl font-bold">Online Status</h2>
|
||||
<BasicSidebarItem title="Status: " value="Offline" />
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const noMapGameTypes = ["BUILD_BATTLE", "HOUSING", "REPLAY"]
|
||||
const noMapArcadeModes = [
|
||||
"DAYONE",
|
||||
"DEFENDER",
|
||||
"DRAGONWARS2",
|
||||
"DROPPER",
|
||||
"SOCCER",
|
||||
"STARWARS",
|
||||
"SIMON_SAYS",
|
||||
"PARTY",
|
||||
"DRAW_THEIR_THING",
|
||||
"PIXEL_PARTY",
|
||||
"THROW_OUT"
|
||||
]
|
||||
|
||||
const showMode = !(session.gameType === "REPLAY")
|
||||
const showMap = session.map !== undefined &&
|
||||
session.gameType !== undefined &&
|
||||
!noMapGameTypes.includes(session.gameType) &&
|
||||
session.mode !== undefined &&
|
||||
!(session.gameType === "ARCADE" && noMapArcadeModes.includes(session.mode))
|
||||
const mode = session.mode === "LOBBY" ? "Lobby" : getGameMode(session.gameType, session.mode)
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col gap-2">
|
||||
<h2 className="text-xl font-bold">Online Status</h2>
|
||||
<div>
|
||||
{session.gameType && <BasicSidebarItem title="Game: " value={getGame(session.gameType)?.name || "Unknown"} />}
|
||||
{showMode && <BasicSidebarItem title="Mode: " value={mode || "Unknown"} />}
|
||||
{showMap && <BasicSidebarItem title="Map: " value={session.map || "Unknown"} />}
|
||||
</div>
|
||||
</div>
|
||||
<Separator className="my-4" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
function SoicalLinks(links: { DISCORD?: string, TWITCH?: string, YOUTUBE?: string, TWITTER?: string, HYPIXEL?: string }) {
|
||||
return (
|
||||
<div className="flex flex-col gap-2">
|
||||
<h1 className="text-xl font-bold underline">Social Links</h1>
|
||||
<div className="flex gap-2">
|
||||
<SocialIcons
|
||||
discord={links?.DISCORD}
|
||||
twitch={links?.TWITCH}
|
||||
youtube={links?.YOUTUBE}
|
||||
twitter={links?.TWITTER}
|
||||
hypixel={links?.HYPIXEL}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -117,33 +117,35 @@ export function SkywarsLevel({ xp, icon }: { xp: number, icon: string | undefine
|
||||
)
|
||||
}
|
||||
|
||||
function MapSkywarsPrestigeColors() {
|
||||
if (typeof pres.colormap_2 === "string") {
|
||||
return <span className={`text-mc-${pres.colormap_2}`}>{val}</span>
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{val.split("").map((c, i) => {
|
||||
if (level.toString().length === 2) {
|
||||
return <span className={`text-mc-${pres.colormap_2[i]}`} key={i}>{c}</span>
|
||||
} else {
|
||||
return <span className={`text-mc-${pres.colormap_3[i]}`} key={i}>{c}</span>
|
||||
}
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<p>
|
||||
<span className={`text-mc-${pres.leftBracket}`}>[</span>
|
||||
<MapSkywarsPrestigeColors />
|
||||
<MapSkywarsPrestigeColors level={level} val={val} colormap_2={pres.colormap_2} colormap_3={pres.colormap_3} />
|
||||
<span className={`text-mc-${pres.rightBracket}`}>]</span>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
|
||||
function MapSkywarsPrestigeColors(
|
||||
{ colormap_2, colormap_3, level, val }: { colormap_2: string | string[], colormap_3: string | string[], level: number, val: string }
|
||||
) {
|
||||
if (typeof colormap_2 === "string") {
|
||||
return <span className={`text-mc-${colormap_2}`}>{val}</span>
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{val.split("").map((c, i) => {
|
||||
if (level.toString().length === 2) {
|
||||
return <span className={`text-mc-${colormap_2[i]}`} key={i}>{c}</span>
|
||||
} else {
|
||||
return <span className={`text-mc-${colormap_3[i]}`} key={i}>{c}</span>
|
||||
}
|
||||
})}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export function SkywarsProgress({ level, percent, currentXp, ceilingXp }: { level: number, percent: number, currentXp: number, ceilingXp: number }) {
|
||||
return (
|
||||
<div className="flex items-center mb-10">
|
||||
|
||||
@@ -16,9 +16,9 @@ export const metadata: Metadata = {
|
||||
|
||||
export default function RootLayout({ children }: LayoutProps<"/">) {
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning className={geist.className}>
|
||||
<html lang="en" data-scroll-behavior="smooth" suppressHydrationWarning className={geist.className}>
|
||||
<head>
|
||||
{/* eslint-disable-next-line @next/next/no-sync-scripts */}
|
||||
{ }
|
||||
{/* {process.env.NODE_ENV === "development" && <script src="https://unpkg.com/react-scan/dist/auto.global.js" />} */}
|
||||
</head>
|
||||
<body className="antialiased">
|
||||
|
||||
@@ -4,7 +4,7 @@ import { cn } from "@/lib/utils"
|
||||
import { Monitor, Moon, Sun } from "lucide-react"
|
||||
import { motion } from "motion/react"
|
||||
import { useTheme } from "next-themes"
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
import { useCallback, useEffect, useEffectEvent, useState } from "react"
|
||||
|
||||
const themes = [
|
||||
{
|
||||
@@ -40,8 +40,12 @@ export function ThemeSwitcher({ className, vertical = false }: ThemeSwitcherProp
|
||||
[setTheme]
|
||||
)
|
||||
|
||||
useEffect(() => {
|
||||
const mount = useEffectEvent(() => {
|
||||
setMounted(true)
|
||||
})
|
||||
|
||||
useEffect(() => {
|
||||
mount()
|
||||
}, [])
|
||||
|
||||
if (!mounted) {
|
||||
|
||||
@@ -200,7 +200,7 @@ export const PRESTIGES = [
|
||||
colormap_2: ["red", "gold", "yellow"],
|
||||
colormap_3: ["light-purple", "red", "gold", "yellow"]
|
||||
}
|
||||
] as const
|
||||
]
|
||||
|
||||
export const ICONS = {
|
||||
default: "\u22c6", // ⋆
|
||||
|
||||
@@ -37,7 +37,7 @@ export function getSkywarsPrestige(level: number) {
|
||||
const floored = floorLevel(level, 10)
|
||||
|
||||
if (level > PRESTIGES.at(-1)!.level) {
|
||||
PRESTIGES.at(-1)!
|
||||
return PRESTIGES.at(-1)!
|
||||
}
|
||||
|
||||
return PRESTIGES.find(p => p.level === floored)!
|
||||
|
||||
Reference in New Issue
Block a user