Compare commits

..

2 Commits

Author SHA1 Message Date
pleb d1a4fd0cb4 Add scorebar to mapCard on the headtohead tool 2025-11-04 07:17:59 -08:00
pleb c7b3439fac Add scorebar to mapCard on compare histories tool 2025-11-04 07:13:49 -08:00
5 changed files with 37 additions and 14 deletions
+1 -1
View File
@@ -62,7 +62,7 @@
: `https://beatsaver.com/search/hash/${hash}`;
</script>
<div class="flex flex-wrap gap-2">
<div class="map-action-buttons flex flex-wrap gap-2">
<a
class="rounded-md border border-white/10 px-2 py-1 text-xs hover:border-white/20"
href={beatLeaderUrl}
+31 -12
View File
@@ -2,6 +2,7 @@
import DifficultyLabel from './DifficultyLabel.svelte';
import MapActionButtons from './MapActionButtons.svelte';
import SongPlayer from './SongPlayer.svelte';
import ScoreBar from './ScoreBar.svelte';
// Song metadata
export let hash: string;
@@ -19,10 +20,15 @@ export let modeName: string = 'Standard';
export let leaderboardId: string | undefined = undefined;
export let beatsaverKey: string | undefined = undefined;
// BeatSaver stats
export let score: number | undefined = undefined;
// Layout tweaks
export let compact = false;
export let showActions = true;
export let showPublished = true;
$: hasScore = typeof score === 'number' && Number.isFinite(score);
</script>
<div class:compact-wrapper={compact} class="card-wrapper">
@@ -56,9 +62,9 @@ export let showPublished = true;
<slot name="meta-leading">
<DifficultyLabel {diffName} {modeName} />
</slot>
</div>
<div class="player">
<SongPlayer {hash} preferBeatLeader={true} />
{#if hasScore}
<ScoreBar value={score} showLabel={true} size="sm" decimals={1} className="score-meter--with-max" />
{/if}
</div>
</div>
@@ -73,6 +79,9 @@ export let showPublished = true;
{modeName}
{beatsaverKey}
/>
<div class="player">
<SongPlayer {hash} preferBeatLeader={true} />
</div>
</div>
{/if}
</div>
@@ -197,6 +206,8 @@ export let showPublished = true;
.meta-leading :global(.score-meter) {
width: 100%;
max-width: 45%;
margin-left: auto;
}
.meta.compact-row {
@@ -204,18 +215,30 @@ export let showPublished = true;
gap: 0.35rem;
}
.player {
flex: 1;
}
.actions {
margin-top: auto;
margin-top: 0.6rem;
display: flex;
align-items: center;
gap: 0.75rem;
flex-wrap: wrap;
}
.body.compact-body .actions {
margin-top: 0.3rem;
}
.player {
flex: 1;
max-width: 45%;
margin-left: auto;
}
.actions :global(.map-action-buttons) {
display: inline-flex;
flex-wrap: wrap;
gap: 0.5rem;
}
@media (max-width: 959px) {
.card-wrapper.compact-wrapper {
grid-template-columns: 1fr;
@@ -240,10 +263,6 @@ export let showPublished = true;
.meta.compact-row .meta-leading {
width: 100%;
}
.meta.compact-row .player {
width: 100%;
}
}
:global(.difficulty-label) {
+3 -1
View File
@@ -11,6 +11,7 @@ export type MapMeta = {
key?: string;
coverURL?: string;
mapper?: string;
score?: number;
};
export type StarInfo = {
@@ -180,7 +181,8 @@ export async function fetchBeatSaverMeta(hash: string): Promise<MapMeta | null>
songName: data?.metadata?.songName ?? data?.name ?? undefined,
key: data?.id ?? undefined,
coverURL: cover,
mapper: data?.uploader?.name ?? undefined
mapper: data?.uploader?.name ?? undefined,
score: typeof data?.stats?.score === 'number' ? data.stats.score : undefined
};
} catch {
// Fallback to CDN cover only
@@ -241,6 +241,7 @@
modeName={item.difficulties[0]?.characteristic ?? 'Standard'}
leaderboardId={item.leaderboardId}
beatsaverKey={metaByHash[item.hash]?.key}
score={metaByHash[item.hash]?.score}
/>
</article>
{/each}
@@ -501,6 +501,7 @@
modeName={item.modeName}
leaderboardId={item.leaderboardId}
beatsaverKey={metaByHash[item.hash]?.key}
score={metaByHash[item.hash]?.score}
>
<div slot="content">
<div class="mt-3 grid grid-cols-2 gap-3 neon-surface">