chuni: add max combo
This commit is contained in:
parent
fa1257ec72
commit
d69d3a2a87
@ -23,6 +23,7 @@ export const getMusic = async (musicId?: number) => {
|
|||||||
)
|
)
|
||||||
.select(({ fn }) => [...CHUNI_MUSIC_PROPERTIES,
|
.select(({ fn }) => [...CHUNI_MUSIC_PROPERTIES,
|
||||||
'score.isFullCombo', 'score.isAllJustice', 'score.isSuccess', 'score.scoreRank', 'score.scoreMax',
|
'score.isFullCombo', 'score.isAllJustice', 'score.isSuccess', 'score.scoreRank', 'score.scoreMax',
|
||||||
|
'score.maxComboCount',
|
||||||
fn<boolean>('NOT ISNULL', ['favorite.favId']).as('favorite'),
|
fn<boolean>('NOT ISNULL', ['favorite.favId']).as('favorite'),
|
||||||
chuniRating()])
|
chuniRating()])
|
||||||
.where(({ selectFrom, eb, and, or }) => and([
|
.where(({ selectFrom, eb, and, or }) => and([
|
||||||
|
@ -68,6 +68,9 @@ export const ChuniMusicPlaylog = ({ music, playlog }: ChuniMusicPlaylogProps) =>
|
|||||||
{data.scoreMax ? <div className="ml-2 text-center flex-grow sm:flex-grow-0">
|
{data.scoreMax ? <div className="ml-2 text-center flex-grow sm:flex-grow-0">
|
||||||
<span className="font-semibold">High Score: </span>{data.scoreMax.toLocaleString()}
|
<span className="font-semibold">High Score: </span>{data.scoreMax.toLocaleString()}
|
||||||
</div> : null}
|
</div> : null}
|
||||||
|
{data.maxComboCount ? <div className="ml-2 text-center flex-grow sm:flex-grow-0">
|
||||||
|
<span className="font-semibold">Max Combo: </span>{data.maxComboCount.toLocaleString()}
|
||||||
|
</div> : null}
|
||||||
</div>
|
</div>
|
||||||
{badges.length ? <div className={`flex-grow lg:flex-grow-0 ml-auto mr-auto sm:ml-0 lg:ml-auto lg:mr-0 mt-2 flex gap-0.5 flex-wrap justify-center sm:justify-start ${data.playlog.length ? 'cursor-pointer' : ''}`} onClick={toggleExpanded}>
|
{badges.length ? <div className={`flex-grow lg:flex-grow-0 ml-auto mr-auto sm:ml-0 lg:ml-auto lg:mr-0 mt-2 flex gap-0.5 flex-wrap justify-center sm:justify-start ${data.playlog.length ? 'cursor-pointer' : ''}`} onClick={toggleExpanded}>
|
||||||
{badges}
|
{badges}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
import { getPlaylog } from '@/actions/chuni/playlog';
|
import { getPlaylog } from '@/actions/chuni/playlog';
|
||||||
import { getJacketUrl } from '@/helpers/assets';
|
import { getJacketUrl } from '@/helpers/assets';
|
||||||
import Link from 'next/link';
|
import Link from 'next/link';
|
||||||
import { ChuniRating } from '@/components/chuni/rating';
|
import { ChuniRating } from '@/components/chuni/rating';
|
||||||
import { ChuniScoreBadge, ChuniLampSuccessBadge, getVariantFromRank, ChuniLampComboBadge } from '@/components/chuni/score-badge';
|
import { ChuniLampComboBadge, ChuniLampSuccessBadge, ChuniScoreBadge, getVariantFromRank } from '@/components/chuni/score-badge';
|
||||||
import { ChuniLevelBadge } from '@/components/chuni/level-badge';
|
import { ChuniLevelBadge } from '@/components/chuni/level-badge';
|
||||||
import { ChuniDifficultyContainer } from '@/components/chuni/difficulty-container';
|
import { ChuniDifficultyContainer } from '@/components/chuni/difficulty-container';
|
||||||
import { formatJst } from '@/helpers/format-jst';
|
import { formatJst } from '@/helpers/format-jst';
|
||||||
import { Ticker } from '@/components/ticker';
|
import { Ticker, TickerHoverProvider } from '@/components/ticker';
|
||||||
|
|
||||||
export type ChuniPlaylogCardProps = {
|
export type ChuniPlaylogCardProps = {
|
||||||
playlog: Awaited<ReturnType<typeof getPlaylog>>['data'][number],
|
playlog: Awaited<ReturnType<typeof getPlaylog>>['data'][number],
|
||||||
@ -23,48 +25,56 @@ const getChangeColor = (val: number) => {
|
|||||||
if (val === 0) return 'text-gray-500';
|
if (val === 0) return 'text-gray-500';
|
||||||
if (val < 0) return 'text-red-500';
|
if (val < 0) return 'text-red-500';
|
||||||
return 'text-blue-500';
|
return 'text-blue-500';
|
||||||
}
|
};
|
||||||
|
|
||||||
export const ChuniPlaylogCard = ({ playlog, className }: ChuniPlaylogCardProps) => {
|
export const ChuniPlaylogCard = ({ playlog, className }: ChuniPlaylogCardProps) => {
|
||||||
return (<div className={`rounded-md bg-content1 relative flex flex-col p-2 pt-1 border border-black/25 ${className ?? ''}`}>
|
return (<TickerHoverProvider>{setHover => <div onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
|
||||||
|
className={`rounded-md bg-content1 relative flex flex-col p-2 pt-1 border border-black/25 ${className ?? ''}`}>
|
||||||
<div className="flex">
|
<div className="flex">
|
||||||
<div className="flex-shrink-0 mr-2 mt-auto">
|
<div className="flex-shrink-0 mr-2 mt-auto">
|
||||||
<ChuniDifficultyContainer difficulty={playlog.chartId ?? 0} className="w-28 aspect-square relative p-1">
|
<ChuniDifficultyContainer difficulty={playlog.chartId ?? 0} className="w-28 aspect-square relative p-1">
|
||||||
<ChuniLevelBadge className="absolute -bottom-1.5 -right-1.5 w-12" music={playlog} />
|
<ChuniLevelBadge className="absolute -bottom-1.5 -right-1.5 w-12" music={playlog}/>
|
||||||
<img className="aspect-square w-full rounded overflow-hidden" src={getJacketUrl(`chuni/jacket/${playlog.jacketPath}`)}
|
<img className="aspect-square w-full rounded overflow-hidden"
|
||||||
alt={playlog.title ?? ''} />
|
src={getJacketUrl(`chuni/jacket/${playlog.jacketPath}`)}
|
||||||
|
alt={playlog.title ?? ''}/>
|
||||||
</ChuniDifficultyContainer>
|
</ChuniDifficultyContainer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-col leading-tight overflow-hidden text-nowrap w-full">
|
<div className="flex flex-col leading-tight overflow-hidden text-nowrap w-full">
|
||||||
<div className="text-xs text-right -mb-0.5 w-full">{ formatJst(playlog.userPlayDate!) }</div>
|
<div className="text-xs text-right -mb-0.5 w-full">{formatJst(playlog.userPlayDate!)}</div>
|
||||||
<Link href={`/chuni/music/${playlog.songId}`} lang="ja" className="hover:text-secondary transition mb-2 font-semibold">
|
<Link href={`/chuni/music/${playlog.songId}`} lang="ja"
|
||||||
<Ticker hoverOnly noDelay><span className="underline">{ playlog.title }</span></Ticker>
|
className="hover:text-secondary transition mb-1 font-semibold">
|
||||||
|
<Ticker hoverOnly noDelay><span className="underline">{playlog.title}</span></Ticker>
|
||||||
</Link>
|
</Link>
|
||||||
<Ticker className="text-sm mb-2">{ playlog.artist }</Ticker>
|
<Ticker hoverOnly noDelay className="text-sm mb-1">{playlog.artist}</Ticker>
|
||||||
<span lang="ja" className="text-sm mb-2">{ playlog.genre }</span>
|
<span lang="ja" className="text-sm">{playlog.genre}</span>
|
||||||
<div className="text-sm flex items-center">
|
<div className="text-sm flex items-center">
|
||||||
Rating: <ChuniRating className="text-medium" rating={+playlog.rating * 100} />
|
Rating: <ChuniRating className="text-medium" rating={+playlog.rating * 100}/>
|
||||||
<span className={`text-xs ${getChangeColor(playlog.playerRatingChange)}`}> (
|
<span className={`text-xs ${getChangeColor(playlog.playerRatingChange)}`}> (
|
||||||
{getChangeSign(playlog.playerRatingChange)}
|
{getChangeSign(playlog.playerRatingChange)}
|
||||||
{(playlog.playerRatingChange / 100).toFixed(2)}
|
{(playlog.playerRatingChange / 100).toFixed(2)}
|
||||||
)</span>
|
)</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="text-xs">
|
||||||
|
Max Combo: {playlog.maxCombo?.toLocaleString()}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="h-5 lg:h-[1.125rem] xl:h-6 2xl:h-[1.125rem] 4xl:h-6 5xl:h-[1.125rem] my-auto flex gap-0.5 overflow-hidden">
|
<div
|
||||||
|
className="h-5 lg:h-[1.125rem] xl:h-6 2xl:h-[1.125rem] 4xl:h-6 5xl:h-[1.125rem] my-auto flex gap-0.5 overflow-hidden">
|
||||||
<ChuniScoreBadge variant={getVariantFromRank(playlog.rank ?? 0)} className="h-full">
|
<ChuniScoreBadge variant={getVariantFromRank(playlog.rank ?? 0)} className="h-full">
|
||||||
{playlog.score?.toLocaleString()}
|
{playlog.score?.toLocaleString()}
|
||||||
</ChuniScoreBadge>
|
</ChuniScoreBadge>
|
||||||
{!!playlog.isClear && <ChuniLampSuccessBadge success={1} />}
|
{!!playlog.isClear && <ChuniLampSuccessBadge success={1}/>}
|
||||||
<ChuniLampComboBadge {...playlog} />
|
<ChuniLampComboBadge {...playlog} />
|
||||||
{!!playlog.isNewRecord && <ChuniScoreBadge variant="gold" fontSize="sm">NEW RECORD</ChuniScoreBadge>}
|
{!!playlog.isNewRecord && <ChuniScoreBadge variant="gold" fontSize="sm">NEW RECORD</ChuniScoreBadge>}
|
||||||
</div>
|
</div>
|
||||||
<div className="flex flex-wrap text-xs justify-around drop-shadow-sm">
|
<div className="flex flex-wrap text-xs justify-around drop-shadow-sm">
|
||||||
<div className="mr-0.5 text-chuni-justice-critical">Justice Critical: { playlog.judgeHeaven }</div>
|
<div className="mr-0.5 text-chuni-justice-critical">Justice Critical: {playlog.judgeHeaven}</div>
|
||||||
<div className="mr-0.5 text-chuni-justice">Justice: { playlog.judgeCritical }</div>
|
<div className="mr-0.5 text-chuni-justice">Justice: {playlog.judgeCritical}</div>
|
||||||
<div className="mr-0.5 text-chuni-attack">Attack: { playlog.judgeAttack }</div>
|
<div className="mr-0.5 text-chuni-attack">Attack: {playlog.judgeAttack}</div>
|
||||||
<div className="mr-0.5 text-chuni-miss">Miss: { playlog.judgeGuilty }</div>
|
<div className="mr-0.5 text-chuni-miss">Miss: {playlog.judgeGuilty}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>);
|
</div>}
|
||||||
|
</TickerHoverProvider>);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user