This commit is contained in:
parent
17c40edc3a
commit
e8d864e531
@ -5,6 +5,7 @@ import Card from "../card";
|
||||
import CountryFlag from "../country-flag";
|
||||
import { Avatar, AvatarImage } from "../ui/avatar";
|
||||
import ClaimProfile from "./claim-profile";
|
||||
import PlayerStats from "./player-stats";
|
||||
|
||||
const playerData = [
|
||||
{
|
||||
@ -40,33 +41,38 @@ type Props = {
|
||||
export default function PlayerHeader({ player }: Props) {
|
||||
return (
|
||||
<Card>
|
||||
<div className="flex gap-3 flex-col items-center text-center sm:flex-row sm:items-start sm:text-start relative select-none">
|
||||
<div className="flex gap-3 flex-col items-center text-center lg:flex-row lg:items-start lg:text-start relative select-none">
|
||||
<Avatar className="w-32 h-32 pointer-events-none">
|
||||
<AvatarImage fetchPriority="high" src={player.profilePicture} />
|
||||
</Avatar>
|
||||
<div>
|
||||
<p className="font-bold text-2xl">{player.name}</p>
|
||||
<div className="flex flex-col">
|
||||
<div>
|
||||
{player.inactive && <p className="text-gray-400">Inactive Account</p>}
|
||||
{player.banned && <p className="text-red-500">Banned Account</p>}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
{playerData.map((subName, index) => {
|
||||
// Check if the player is inactive or banned and if the data should be shown
|
||||
if (!subName.showWhenInactiveOrBanned && (player.inactive || player.banned)) {
|
||||
return null;
|
||||
}
|
||||
<div className="w-full flex gap-2 flex-col justify-center items-center lg:justify-start lg:items-start">
|
||||
<div>
|
||||
<p className="font-bold text-2xl">{player.name}</p>
|
||||
<div className="flex flex-col">
|
||||
<div>
|
||||
{player.inactive && <p className="text-gray-400">Inactive Account</p>}
|
||||
{player.banned && <p className="text-red-500">Banned Account</p>}
|
||||
</div>
|
||||
<div className="flex gap-2">
|
||||
{playerData.map((subName, index) => {
|
||||
// Check if the player is inactive or banned and if the data should be shown
|
||||
if (!subName.showWhenInactiveOrBanned && (player.inactive || player.banned)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<div key={index} className="flex gap-1 items-center">
|
||||
{subName.icon && subName.icon(player)}
|
||||
{subName.render && subName.render(player)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
return (
|
||||
<div key={index} className="flex gap-1 items-center">
|
||||
{subName.icon && subName.icon(player)}
|
||||
{subName.render && subName.render(player)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<PlayerStats player={player} />
|
||||
|
||||
<div className="absolute top-0 right-0">
|
||||
<ClaimProfile playerId={player.id} />
|
||||
</div>
|
||||
|
@ -97,7 +97,7 @@ export default function PlayerRankChart({ player }: Props) {
|
||||
lineTension: 0.5,
|
||||
data: playerRankHistory,
|
||||
label: "Rank",
|
||||
borderColor: "#c084fc",
|
||||
borderColor: "#a147fa",
|
||||
fill: false,
|
||||
color: "#fff",
|
||||
},
|
||||
|
71
src/components/player/player-stats.tsx
Normal file
71
src/components/player/player-stats.tsx
Normal file
@ -0,0 +1,71 @@
|
||||
import ScoreSaberPlayer from "@/common/data-fetcher/types/scoresaber/scoresaber-player";
|
||||
import { formatNumberWithCommas } from "@/common/number-utils";
|
||||
import StatValue from "@/components/stat-value";
|
||||
import { ClassValue } from "clsx";
|
||||
|
||||
type Badge = {
|
||||
name: string;
|
||||
color?: ClassValue;
|
||||
create: (player: ScoreSaberPlayer) => string | React.ReactNode | undefined;
|
||||
};
|
||||
|
||||
const badges: Badge[] = [
|
||||
{
|
||||
name: "Ranked Play Count",
|
||||
color: "bg-pp",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
return formatNumberWithCommas(player.scoreStats.rankedPlayCount);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Total Ranked Score",
|
||||
color: "bg-pp",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
return formatNumberWithCommas(player.scoreStats.totalRankedScore);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Average Ranked Accuracy",
|
||||
color: "bg-pp",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
return player.scoreStats.averageRankedAccuracy.toFixed(2) + "%";
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Total Play Count",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
return formatNumberWithCommas(player.scoreStats.totalPlayCount);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Total Score",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
return formatNumberWithCommas(player.scoreStats.totalScore);
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Total Replays Watched",
|
||||
create: (player: ScoreSaberPlayer) => {
|
||||
return formatNumberWithCommas(player.scoreStats.replaysWatched);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
type Props = {
|
||||
player: ScoreSaberPlayer;
|
||||
};
|
||||
|
||||
export default function PlayerStats({ player }: Props) {
|
||||
return (
|
||||
<div className={`flex flex-wrap gap-2 w-full justify-center lg:justify-start`}>
|
||||
{badges.map((badge, index) => {
|
||||
const toRender = badge.create(player);
|
||||
if (toRender === undefined) {
|
||||
return <div key={index} />;
|
||||
}
|
||||
|
||||
return <StatValue key={index} color={badge.color} name={badge.name} value={toRender} />;
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
}
|
@ -1,18 +1,30 @@
|
||||
import clsx, { ClassValue } from "clsx";
|
||||
|
||||
type Props = {
|
||||
/**
|
||||
* The stat name.
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* The background color of the stat.
|
||||
*/
|
||||
color?: ClassValue;
|
||||
|
||||
/**
|
||||
* The value of the stat.
|
||||
*/
|
||||
value: React.ReactNode;
|
||||
};
|
||||
|
||||
export default function StatValue({ name, value }: Props) {
|
||||
export default function StatValue({ name, color, value }: Props) {
|
||||
return (
|
||||
<div className="flex min-w-16 gap-2 bg-accent h-[28px] p-1 items-center justify-center rounded-md text-sm">
|
||||
<div
|
||||
className={clsx(
|
||||
"flex min-w-16 gap-2 h-[28px] p-1 items-center justify-center rounded-md text-sm",
|
||||
color ? color : "bg-accent"
|
||||
)}
|
||||
>
|
||||
{name && (
|
||||
<>
|
||||
<p>{name}</p>
|
||||
|
@ -10,7 +10,7 @@ const config: Config = {
|
||||
theme: {
|
||||
extend: {
|
||||
colors: {
|
||||
pp: "#c084fc",
|
||||
pp: "#a147fa",
|
||||
background: "hsl(var(--background))",
|
||||
foreground: "hsl(var(--foreground))",
|
||||
card: {
|
||||
|
Reference in New Issue
Block a user