made the player page look much nicer
All checks were successful
Deploy Website / docker (ubuntu-latest) (push) Successful in 2m23s
All checks were successful
Deploy Website / docker (ubuntu-latest) (push) Successful in 2m23s
This commit is contained in:
parent
f156b7f582
commit
1c2214a659
@ -21,7 +21,7 @@ export function HandAccuracyBadge({ score, hand }: HandAccuracyProps) {
|
||||
const formattedHand = capitalizeFirstLetter(hand);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<div className="flex gap-1 items-center justify-center">
|
||||
<Tooltip
|
||||
display={
|
||||
<>
|
||||
|
@ -1,9 +1,7 @@
|
||||
import { formatNumberWithCommas } from "@ssr/common/utils/number-utils";
|
||||
import { PauseIcon } from "@heroicons/react/24/solid";
|
||||
import { ScoreBadgeProps } from "@/components/score/badges/badge-props";
|
||||
import { ScoreMissesTooltip } from "@/components/score/score-misses-tooltip";
|
||||
import { Misses } from "@ssr/common/model/additional-score-data/misses";
|
||||
import Tooltip from "@/components/tooltip";
|
||||
|
||||
type ScoreMissesBadgeProps = ScoreBadgeProps & {
|
||||
/**
|
||||
@ -34,69 +32,82 @@ export default function ScoreMissesAndPausesBadge({ score, hideXMark }: ScoreMis
|
||||
return (
|
||||
<div className="flex flex-col justify-center items-center w-full">
|
||||
<div className="flex items-center gap-1">
|
||||
<ScoreMissesTooltip
|
||||
missedNotes={score.missedNotes}
|
||||
badCuts={score.badCuts}
|
||||
bombCuts={misses?.bombCuts}
|
||||
wallsHit={misses?.wallsHit}
|
||||
fullCombo={score.fullCombo}
|
||||
>
|
||||
<div className="flex items-center">
|
||||
<div className="flex items-center gap-1">
|
||||
<ScoreMissesTooltip
|
||||
missedNotes={score.missedNotes}
|
||||
badCuts={score.badCuts}
|
||||
bombCuts={misses?.bombCuts}
|
||||
wallsHit={misses?.wallsHit}
|
||||
fullCombo={score.fullCombo}
|
||||
>
|
||||
<p>
|
||||
{score.fullCombo ? <span className="text-green-400">FC</span> : formatNumberWithCommas(score.misses)}
|
||||
{!hideXMark && !score.fullCombo && <span>x</span>}
|
||||
</p>
|
||||
</div>
|
||||
</ScoreMissesTooltip>
|
||||
{additionalData && !!pauses && pauses > 0 && (
|
||||
<>
|
||||
<p>|</p>
|
||||
<Tooltip
|
||||
display={
|
||||
<p>
|
||||
{pauses}x Pause{pauses > 1 ? "s" : ""}
|
||||
</p>
|
||||
}
|
||||
</ScoreMissesTooltip>
|
||||
{additionalData && previousScoreMisses && scoreImprovement && misses && isMissImprovement && (
|
||||
<ScoreMissesTooltip
|
||||
missedNotes={previousScoreMisses.missedNotes}
|
||||
badCuts={previousScoreMisses.badCuts}
|
||||
bombCuts={previousScoreMisses.bombCuts}
|
||||
wallsHit={previousScoreMisses.wallsHit}
|
||||
fullCombo={previousScoreFc}
|
||||
>
|
||||
<div className="flex gap-1 items-center">
|
||||
<p>{pauses && pauses}</p>
|
||||
<PauseIcon className="w-4 h-4" />
|
||||
<div className="text-xs flex flex-row gap-1">
|
||||
<p>(vs {previousScoreFc ? "FC" : formatNumberWithCommas(previousScoreMisses.misses)}x)</p>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{additionalData && previousScoreMisses && scoreImprovement && misses && isMissImprovement && (
|
||||
<div className="flex gap-2 items-center justify-center">
|
||||
<ScoreMissesTooltip
|
||||
missedNotes={previousScoreMisses.missedNotes}
|
||||
badCuts={previousScoreMisses.badCuts}
|
||||
bombCuts={previousScoreMisses.bombCuts}
|
||||
wallsHit={previousScoreMisses.wallsHit}
|
||||
fullCombo={previousScoreFc}
|
||||
>
|
||||
<div className="flex gap-1 items-center text-xs">
|
||||
{previousScoreFc ? (
|
||||
<p className="text-green-400">FC</p>
|
||||
) : (
|
||||
formatNumberWithCommas(previousScoreMisses.misses)
|
||||
)}
|
||||
</div>
|
||||
</ScoreMissesTooltip>
|
||||
<p>-></p>
|
||||
<ScoreMissesTooltip
|
||||
missedNotes={misses.missedNotes}
|
||||
badCuts={misses.badCuts}
|
||||
bombCuts={misses.bombCuts}
|
||||
wallsHit={misses.wallsHit}
|
||||
fullCombo={additionalData.fullCombo}
|
||||
>
|
||||
<div className="flex gap-1 items-center text-xs">
|
||||
{additionalData.fullCombo ? <p className="text-green-400">FC</p> : formatNumberWithCommas(misses.misses)}
|
||||
</div>
|
||||
</ScoreMissesTooltip>
|
||||
</ScoreMissesTooltip>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{/*{additionalData && !!pauses && pauses > 0 && (*/}
|
||||
{/* <>*/}
|
||||
{/* <p>|</p>*/}
|
||||
{/* <Tooltip*/}
|
||||
{/* display={*/}
|
||||
{/* <p>*/}
|
||||
{/* {pauses}x Pause{pauses > 1 ? "s" : ""}*/}
|
||||
{/* </p>*/}
|
||||
{/* }*/}
|
||||
{/* >*/}
|
||||
{/* <div className="flex gap-1 items-center">*/}
|
||||
{/* <p>{pauses && pauses}</p>*/}
|
||||
{/* <PauseIcon className="w-4 h-4" />*/}
|
||||
{/* </div>*/}
|
||||
{/* </Tooltip>*/}
|
||||
{/* </>*/}
|
||||
{/*)}*/}
|
||||
</div>
|
||||
{/*{additionalData && previousScoreMisses && scoreImprovement && misses && isMissImprovement && (*/}
|
||||
{/* <div className="flex gap-2 items-center justify-center">*/}
|
||||
{/* <ScoreMissesTooltip*/}
|
||||
{/* missedNotes={previousScoreMisses.missedNotes}*/}
|
||||
{/* badCuts={previousScoreMisses.badCuts}*/}
|
||||
{/* bombCuts={previousScoreMisses.bombCuts}*/}
|
||||
{/* wallsHit={previousScoreMisses.wallsHit}*/}
|
||||
{/* fullCombo={previousScoreFc}*/}
|
||||
{/* >*/}
|
||||
{/* <div className="flex gap-1 items-center text-xs">*/}
|
||||
{/* {previousScoreFc ? (*/}
|
||||
{/* <p className="text-green-400">FC</p>*/}
|
||||
{/* ) : (*/}
|
||||
{/* formatNumberWithCommas(previousScoreMisses.misses)*/}
|
||||
{/* )}*/}
|
||||
{/* </div>*/}
|
||||
{/* </ScoreMissesTooltip>*/}
|
||||
{/* <p>-></p>*/}
|
||||
{/* <ScoreMissesTooltip*/}
|
||||
{/* missedNotes={misses.missedNotes}*/}
|
||||
{/* badCuts={misses.badCuts}*/}
|
||||
{/* bombCuts={misses.bombCuts}*/}
|
||||
{/* wallsHit={misses.wallsHit}*/}
|
||||
{/* fullCombo={additionalData.fullCombo}*/}
|
||||
{/* >*/}
|
||||
{/* <div className="flex gap-1 items-center text-xs">*/}
|
||||
{/* {additionalData.fullCombo ? <p className="text-green-400">FC</p> : formatNumberWithCommas(misses.misses)}*/}
|
||||
{/* </div>*/}
|
||||
{/* </ScoreMissesTooltip>*/}
|
||||
{/* </div>*/}
|
||||
{/*)}*/}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
import StatValue from "@/components/stat-value";
|
||||
import { ScoreSaberScore } from "@ssr/common/model/score/impl/scoresaber-score";
|
||||
import ScoreSaberLeaderboard from "@ssr/common/model/leaderboard/impl/scoresaber-leaderboard";
|
||||
import clsx from "clsx";
|
||||
|
||||
/**
|
||||
* A badge to display in the score stats.
|
||||
@ -27,6 +27,19 @@ export function ScoreBadges({ badges, score, leaderboard }: ScoreBadgeProps) {
|
||||
if (toRender === undefined) {
|
||||
return <div key={index} />;
|
||||
}
|
||||
return <StatValue key={index} color={color} value={toRender} />;
|
||||
return (
|
||||
<div
|
||||
key={index}
|
||||
className={clsx(
|
||||
"flex h-fit p-1 items-center justify-center rounded-md text-sm cursor-default",
|
||||
color ? color : "bg-accent"
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: (!color?.includes("bg") && color) || undefined,
|
||||
}}
|
||||
>
|
||||
{toRender}
|
||||
</div>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ export default function ScoreSongInfo({ leaderboard, beatSaverMap }: Props) {
|
||||
>
|
||||
{leaderboard.songName} {leaderboard.songSubName}
|
||||
</Link>
|
||||
<div className="flex flex-col text-sm">
|
||||
<div className="flex flex-row text-sm gap-2">
|
||||
<p className="text-gray-400">{leaderboard.songAuthorName}</p>
|
||||
<FallbackLink
|
||||
href={mappersProfile}
|
||||
|
@ -72,8 +72,10 @@ type Props = {
|
||||
|
||||
export default function ScoreStats({ score, leaderboard }: Props) {
|
||||
return (
|
||||
<div className={`grid grid-cols-3 grid-rows-2 gap-1 ml-0 lg:ml-2 `}>
|
||||
<ScoreBadges badges={badges} score={score} leaderboard={leaderboard} />
|
||||
<div className="flex flex-col justify-center h-full">
|
||||
<div className={`grid grid-cols-3 gap-1 ml-0 lg:ml-2 justify-center`}>
|
||||
<ScoreBadges badges={badges} score={score} leaderboard={leaderboard} />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -120,12 +120,12 @@ export default function Score({ leaderboard, beatSaverMap, score, settings, high
|
||||
};
|
||||
|
||||
const gridColsClass = settings?.noScoreButtons
|
||||
? "grid-cols-[20px 1fr_1fr] lg:grid-cols-[0.5fr_4fr_300px]" // Fewer columns if no buttons
|
||||
: "grid-cols-[20px 1fr_1fr] lg:grid-cols-[0.5fr_4fr_1fr_300px]"; // Original with buttons
|
||||
? "grid-cols-[20px 1fr_1fr] lg:grid-cols-[0.5fr_4fr_350px]" // Fewer columns if no buttons
|
||||
: "grid-cols-[20px 1fr_1fr] lg:grid-cols-[0.5fr_4fr_1fr_350px]"; // Original with buttons
|
||||
|
||||
return (
|
||||
<div className="pb-2 pt-2">
|
||||
<div className={`grid w-full gap-2 lg:gap-0 ${gridColsClass}`}>
|
||||
<div className="pb-2 pt-2 w-full h-full">
|
||||
<div className={`grid w-full h-full gap-2 lg:gap-0 ${gridColsClass}`}>
|
||||
<ScoreRankInfo score={score} leaderboard={leaderboard} />
|
||||
<ScoreSongInfo leaderboard={leaderboard} beatSaverMap={beatSaverMap} />
|
||||
{!settings?.noScoreButtons && (
|
||||
|
@ -16,18 +16,24 @@ type Props = {
|
||||
*/
|
||||
color?: string;
|
||||
|
||||
/**
|
||||
* The additional classes for the stat.
|
||||
*/
|
||||
className?: string;
|
||||
|
||||
/**
|
||||
* The value of the stat.
|
||||
*/
|
||||
value: React.ReactNode;
|
||||
};
|
||||
|
||||
export default function StatValue({ name, icon, color, value }: Props) {
|
||||
export default function StatValue({ name, icon, color, className, value }: Props) {
|
||||
return (
|
||||
<div
|
||||
className={clsx(
|
||||
"flex min-w-16 gap-2 h-full p-1 items-center justify-center rounded-md text-sm cursor-default",
|
||||
color ? color : "bg-accent"
|
||||
color ? color : "bg-accent",
|
||||
className
|
||||
)}
|
||||
style={{
|
||||
backgroundColor: (!color?.includes("bg") && color) || undefined,
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
import { Tooltip as ShadCnTooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip";
|
||||
import { useState } from "react";
|
||||
import { cn } from "@/common/utils";
|
||||
import { clsx } from "clsx";
|
||||
|
||||
type Props = {
|
||||
/**
|
||||
@ -36,16 +36,15 @@ export default function Tooltip({ children, display, asChild = true, side = "top
|
||||
|
||||
return (
|
||||
<ShadCnTooltip open={open}>
|
||||
<TooltipTrigger className={className} asChild={asChild}>
|
||||
<div
|
||||
className={cn("cursor-default", className)}
|
||||
onMouseEnter={() => setOpen(true)}
|
||||
onMouseLeave={() => setOpen(false)}
|
||||
onTouchStart={() => setOpen(!open)}
|
||||
onTouchEnd={() => setOpen(!open)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
<TooltipTrigger
|
||||
className={clsx("cursor-default", className)}
|
||||
asChild={asChild}
|
||||
onMouseEnter={() => setOpen(true)}
|
||||
onMouseLeave={() => setOpen(false)}
|
||||
onTouchStart={() => setOpen(!open)}
|
||||
onTouchEnd={() => setOpen(!open)}
|
||||
>
|
||||
{children}
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="max-w-[350px]" side={side}>
|
||||
{display}
|
||||
|
Reference in New Issue
Block a user