chuni: show chart credits and note counts on music detail
This commit is contained in:
parent
9f126d84b1
commit
8a864c2cf7
@ -19,7 +19,8 @@ type ChuniMusicPlaylogProps = {
|
|||||||
export const ChuniMusicPlaylog = ({ music, playlog }: ChuniMusicPlaylogProps) => {
|
export const ChuniMusicPlaylog = ({ music, playlog }: ChuniMusicPlaylogProps) => {
|
||||||
type Music = (typeof music)[number];
|
type Music = (typeof music)[number];
|
||||||
type Playlog = (typeof playlog)['data'][number];
|
type Playlog = (typeof playlog)['data'][number];
|
||||||
const defaultExpanded: Record<string, Set<string>> = {}
|
|
||||||
|
const [selected, setSelected] = useState(new Set<string>());
|
||||||
|
|
||||||
const difficulties: (Music & { playlog: Playlog[] })[] = [];
|
const difficulties: (Music & { playlog: Playlog[] })[] = [];
|
||||||
music.forEach(m => {
|
music.forEach(m => {
|
||||||
@ -27,15 +28,13 @@ export const ChuniMusicPlaylog = ({ music, playlog }: ChuniMusicPlaylogProps) =>
|
|||||||
});
|
});
|
||||||
|
|
||||||
playlog.data.forEach(play => {
|
playlog.data.forEach(play => {
|
||||||
defaultExpanded[play.chartId!] = new Set();
|
|
||||||
difficulties[play.chartId!].playlog.push(play);
|
difficulties[play.chartId!].playlog.push(play);
|
||||||
});
|
});
|
||||||
|
|
||||||
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
||||||
|
|
||||||
const badgeClass = 'h-6 sm:h-8';
|
const badgeClass = 'h-6 sm:h-8';
|
||||||
|
|
||||||
return (<div className="flex flex-col w-full px-2 sm:px-0">
|
return (<div className="flex flex-col w-full px-1 sm:px-0">
|
||||||
|
<Accordion selectionMode="multiple" selectedKeys={selected}>
|
||||||
{difficulties.map((data, i) => {
|
{difficulties.map((data, i) => {
|
||||||
const rank = CHUNI_SCORE_RANKS[data.scoreRank!];
|
const rank = CHUNI_SCORE_RANKS[data.scoreRank!];
|
||||||
const badges = [
|
const badges = [
|
||||||
@ -46,16 +45,17 @@ export const ChuniMusicPlaylog = ({ music, playlog }: ChuniMusicPlaylogProps) =>
|
|||||||
</> : rank}
|
</> : rank}
|
||||||
</ChuniScoreBadge>,
|
</ChuniScoreBadge>,
|
||||||
data.isSuccess ? <ChuniLampSuccessBadge key="2" className={badgeClass} success={data.isSuccess} /> : null,
|
data.isSuccess ? <ChuniLampSuccessBadge key="2" className={badgeClass} success={data.isSuccess} /> : null,
|
||||||
<ChuniLampComboBadge key="3" className={badgeClass} {...data} />
|
(data.isFullCombo || data.isAllJustice) && <ChuniLampComboBadge key="3" className={badgeClass} {...data} />
|
||||||
].filter(x => x);
|
].filter(x => x);
|
||||||
|
|
||||||
const toggleExpanded = () => expanded[i] && setExpanded(e =>
|
|
||||||
({ ...e,
|
|
||||||
[i]: e[i].size ? new Set() : new Set(['1'])
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (<div key={i} className="mb-2 border-b pb-2 border-gray-500 flex flex-row flex-wrap">
|
// <div key={i} className="mb-2 border-b pb-2 border-gray-500 flex flex-row flex-wrap items-center">
|
||||||
<div className={`flex items-center gap-2 flex-wrap w-full lg:w-auto lg:flex-grow ${data.playlog.length ? 'cursor-pointer' : ''}`} onClick={toggleExpanded}>
|
return (<AccordionItem key={i.toString()} classNames={{ trigger: 'py-0 my-2' }} title={<div className="flex flex-row flex-wrap items-center gap-y-1.5"
|
||||||
|
onClick={() => {
|
||||||
|
const key = i.toString();
|
||||||
|
setSelected(s => s.has(key) ? new Set([...s].filter(k => k !== key)) : new Set([...s, key]))
|
||||||
|
}}>
|
||||||
|
<div className={`flex items-center gap-2 flex-wrap lg:flex-grow ${data.playlog.length ? 'cursor-pointer w-full lg:w-auto' : 'flex-grow'}`}>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<div className="w-14 mr-2 p-0.5 bg-black">
|
<div className="w-14 mr-2 p-0.5 bg-black">
|
||||||
<ChuniLevelBadge className="w-full" music={data} />
|
<ChuniLevelBadge className="w-full" music={data} />
|
||||||
@ -64,28 +64,33 @@ export const ChuniMusicPlaylog = ({ music, playlog }: ChuniMusicPlaylogProps) =>
|
|||||||
</div>
|
</div>
|
||||||
{!data.playlog.length && <div className="text-right italic text-gray-500 flex-grow">No Play History</div>}
|
{!data.playlog.length && <div className="text-right italic text-gray-500 flex-grow">No Play History</div>}
|
||||||
{data.rating ? <ChuniRating className="text-2xl text-right" rating={+data.rating * 100} /> : null}
|
{data.rating ? <ChuniRating className="text-2xl text-right" rating={+data.rating * 100} /> : null}
|
||||||
{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 max-sm:text-sm">
|
||||||
<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">
|
{data.maxComboCount ? <div className="ml-2 text-center flex-grow sm:flex-grow-0 max-sm:text-sm">
|
||||||
<span className="font-semibold">Max Combo: </span>{data.maxComboCount.toLocaleString()}
|
<span className="font-semibold">Max Combo: </span>{data.maxComboCount.toLocaleString()}
|
||||||
</div> : null}
|
</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 items-center lg:flex-grow-0 ml-auto mr-auto sm:ml-0 lg:ml-auto lg:mr-0 flex gap-0.5 flex-wrap justify-center sm:justify-start ${data.playlog.length ? 'cursor-pointer' : ''}`}>
|
||||||
{badges}
|
{badges}
|
||||||
</div> : null}
|
</div> : null}
|
||||||
{data.playlog.length ? <Accordion selectedKeys={expanded[i]} onSelectionChange={k => setExpanded(e => ({ ...e, [i]: k as any }))}>
|
</div>}>
|
||||||
<AccordionItem key="1" title="Play History">
|
<div className="flex flex-wrap gap-x-4 gap-y-2 mb-3 justify-center sm:justify-end max-sm:text-xs">
|
||||||
|
<span className="mr-auto max-sm:w-full text-center"><span className="font-semibold">Chart designer:</span> {data.chartDesigner}</span>
|
||||||
|
{!!data.tapJudgeCount && <span><span className="font-semibold">Tap:</span> {data.tapJudgeCount}</span>}
|
||||||
|
{!!data.flickJudgeCount && <span><span className="font-semibold">Flick:</span> {data.flickJudgeCount}</span>}
|
||||||
|
{!!data.holdJudgeCount && <span><span className="font-semibold">Hold:</span> {data.holdJudgeCount}</span>}
|
||||||
|
{!!data.slideJudgeCount && <span><span className="font-semibold">Slide:</span> {data.slideJudgeCount}</span>}
|
||||||
|
{!!data.airJudgeCount && <span><span className="font-semibold">Air:</span> {data.airJudgeCount}</span>}
|
||||||
|
</div>
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-3 4xl:grid-cols-4 5xl:grid-cols-5 6xl:grid-cols-6 gap-2">
|
<div className="grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-3 4xl:grid-cols-4 5xl:grid-cols-5 6xl:grid-cols-6 gap-2">
|
||||||
{data.playlog.map(p => <ChuniPlaylogCard key={p.id}
|
{data.playlog.map(p => <ChuniPlaylogCard key={p.id}
|
||||||
showDetails
|
showDetails
|
||||||
badgeClass="h-5 sm:h-6 md:h-5 lg:h-[1.125rem] 3xl:h-5"
|
badgeClass="h-5 sm:h-6 md:h-5 lg:h-[1.125rem] 3xl:h-5 md:-mt-1"
|
||||||
playlog={p} className="h-64 md:h-52" />)}
|
playlog={p} className="h-64 md:h-52" />)}
|
||||||
</div>
|
</div>
|
||||||
</AccordionItem>
|
</AccordionItem>);
|
||||||
</Accordion> : null
|
|
||||||
}
|
|
||||||
</div>)
|
|
||||||
})}
|
})}
|
||||||
|
</Accordion>
|
||||||
</div>);
|
</div>);
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user