feat: enhance mappool integration; include mappool details and average star rating in match views
This commit is contained in:
@@ -18,13 +18,13 @@ export const load: PageServerLoad = async ({ locals }) => {
|
|||||||
|
|
||||||
// ── LOGGED IN → dashboard data ──
|
// ── LOGGED IN → dashboard data ──
|
||||||
const recentMatches = await db.query.match.findMany({
|
const recentMatches = await db.query.match.findMany({
|
||||||
with: { participants: { with: { team: true } } },
|
with: { participants: { with: { team: true } }, mappool: { with: { slots: true } } },
|
||||||
orderBy: desc(match.createdAt),
|
orderBy: desc(match.createdAt),
|
||||||
limit: 5
|
limit: 5
|
||||||
});
|
});
|
||||||
|
|
||||||
const liveMatches = await db.query.match.findMany({
|
const liveMatches = await db.query.match.findMany({
|
||||||
with: { participants: { with: { team: true } } },
|
with: { participants: { with: { team: true } }, mappool: { with: { slots: true } } },
|
||||||
where: inArray(match.state, ['LOBBY', 'ROLLING', 'PICKING', 'PLAYING'])
|
where: inArray(match.state, ['LOBBY', 'ROLLING', 'PICKING', 'PLAYING'])
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,13 @@
|
|||||||
return () => clearInterval(id);
|
return () => clearInterval(id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function avgSR(mappool: any): string | null {
|
||||||
|
const slots = mappool?.slots;
|
||||||
|
if (!slots?.length) return null;
|
||||||
|
const avg = slots.reduce((s: number, sl: any) => s + (sl.starRating ?? 0), 0) / slots.length;
|
||||||
|
return avg.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
function timeAgo(date: string | Date) {
|
function timeAgo(date: string | Date) {
|
||||||
const d = new Date(date);
|
const d = new Date(date);
|
||||||
const diff = Date.now() - d.getTime();
|
const diff = Date.now() - d.getTime();
|
||||||
@@ -335,6 +342,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<p class="mt-0.5 text-xs text-text-secondary">
|
<p class="mt-0.5 text-xs text-text-secondary">
|
||||||
{m.name ? `${m.name} · ` : ''}BO{config.bestOf}
|
{m.name ? `${m.name} · ` : ''}BO{config.bestOf}
|
||||||
|
{#if m.mappool}
|
||||||
|
· <a href='/mappools/{m.mappool.id}' onclick={(e) => e.stopPropagation()} class='hover:text-accent hover:underline'>{m.mappool.name}</a>{#if avgSR(m.mappool)} <span>{avgSR(m.mappool)}★</span>{/if}
|
||||||
|
{/if}
|
||||||
· {timeAgo(m.finishedAt ?? m.createdAt)}
|
· {timeAgo(m.finishedAt ?? m.createdAt)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -63,7 +63,7 @@
|
|||||||
<h2 class="text-sm font-600">{pool.name}</h2>
|
<h2 class="text-sm font-600">{pool.name}</h2>
|
||||||
<p class="mt-1 text-xs text-text-secondary">
|
<p class="mt-1 text-xs text-text-secondary">
|
||||||
{pool.slots.length} map{pool.slots.length !== 1 ? 's' : ''}
|
{pool.slots.length} map{pool.slots.length !== 1 ? 's' : ''}
|
||||||
{#if avgSr}· ★ {avgSr}{/if}
|
{#if avgSr}· {avgSr}★{/if}
|
||||||
· Created {new Date(pool.createdAt).toLocaleDateString()}
|
· Created {new Date(pool.createdAt).toLocaleDateString()}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -242,7 +242,7 @@
|
|||||||
</a>
|
</a>
|
||||||
<div class="mt-0.5 flex items-center gap-3 text-xs text-text-secondary">
|
<div class="mt-0.5 flex items-center gap-3 text-xs text-text-secondary">
|
||||||
<span>[{slot.beatmap.version}]</span>
|
<span>[{slot.beatmap.version}]</span>
|
||||||
<span>★ {slot.beatmap.starRating.toFixed(2)}</span>
|
<span>{slot.beatmap.starRating.toFixed(2)}★</span>
|
||||||
<span>{slot.beatmap.bpm} BPM</span>
|
<span>{slot.beatmap.bpm} BPM</span>
|
||||||
<span>{formatLength(slot.beatmap.totalLength)}</span>
|
<span>{formatLength(slot.beatmap.totalLength)}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ export const load: PageServerLoad = async ({ locals }) => {
|
|||||||
requireAuth(locals);
|
requireAuth(locals);
|
||||||
|
|
||||||
const matches = await db.query.match.findMany({
|
const matches = await db.query.match.findMany({
|
||||||
with: { participants: { with: { team: true } } },
|
with: { participants: { with: { team: true } }, mappool: { with: { slots: true } } },
|
||||||
orderBy: desc(match.createdAt),
|
orderBy: desc(match.createdAt),
|
||||||
limit: 50
|
limit: 50
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -39,6 +39,13 @@
|
|||||||
return { p1, p2 };
|
return { p1, p2 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function avgSR(mappool: any): string | null {
|
||||||
|
const slots = mappool?.slots;
|
||||||
|
if (!slots?.length) return null;
|
||||||
|
const avg = slots.reduce((s: number, sl: any) => s + (sl.starRating ?? 0), 0) / slots.length;
|
||||||
|
return avg.toFixed(2);
|
||||||
|
}
|
||||||
|
|
||||||
function timeAgo(date: string | Date) {
|
function timeAgo(date: string | Date) {
|
||||||
const d = new Date(date);
|
const d = new Date(date);
|
||||||
const diff = Date.now() - d.getTime();
|
const diff = Date.now() - d.getTime();
|
||||||
@@ -281,6 +288,9 @@
|
|||||||
</div>
|
</div>
|
||||||
<p class="mt-0.5 text-xs text-text-secondary">
|
<p class="mt-0.5 text-xs text-text-secondary">
|
||||||
{m.name ? `${m.name} · ` : ''}BO{config.bestOf}
|
{m.name ? `${m.name} · ` : ''}BO{config.bestOf}
|
||||||
|
{#if m.mappool}
|
||||||
|
· <a href='/mappools/{m.mappool.id}' onclick={(e) => e.stopPropagation()} class='hover:text-accent hover:underline'>{m.mappool.name}</a>{#if avgSR(m.mappool)} <span>{avgSR(m.mappool)}★</span>{/if}
|
||||||
|
{/if}
|
||||||
{#if m.finishedAt}
|
{#if m.finishedAt}
|
||||||
· {timeAgo(m.finishedAt)}
|
· {timeAgo(m.finishedAt)}
|
||||||
{:else if m.createdAt}
|
{:else if m.createdAt}
|
||||||
|
|||||||
@@ -304,7 +304,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{#if bm}
|
{#if bm}
|
||||||
<p class="mt-2 text-center text-sm">{bm.artist} - {bm.title} <span class="text-text-secondary">[{bm.version}]</span></p>
|
<p class="mt-2 text-center text-sm">{bm.artist} - {bm.title} <span class="text-text-secondary">[{bm.version}]</span></p>
|
||||||
<p class="mt-1 text-center text-xs text-text-secondary">★{bm.starRating.toFixed(1)} · {bm.bpm}bpm · {formatLength(bm.totalLength)}</p>
|
<p class="mt-1 text-center text-xs text-text-secondary">{bm.starRating.toFixed(2)}★ · {bm.bpm}bpm · {formatLength(bm.totalLength)}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<!-- Per-player lobby status -->
|
<!-- Per-player lobby status -->
|
||||||
@@ -370,7 +370,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</h2>
|
</h2>
|
||||||
{#if mappoolAvgSR()}
|
{#if mappoolAvgSR()}
|
||||||
<span class="text-xs text-text-secondary">avg ★{mappoolAvgSR()}</span>
|
<span class="text-xs text-text-secondary">avg {mappoolAvgSR()}★</span>
|
||||||
{/if}
|
{/if}
|
||||||
{#if pickingPhase}
|
{#if pickingPhase}
|
||||||
<span class="rounded bg-blue-500/20 px-2 py-0.5 text-[10px] font-600 text-blue-400">
|
<span class="rounded bg-blue-500/20 px-2 py-0.5 text-[10px] font-600 text-blue-400">
|
||||||
@@ -452,7 +452,7 @@
|
|||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
{#if bm}
|
{#if bm}
|
||||||
<p class="truncate text-xs font-500">{bm.artist} - {bm.title}</p>
|
<p class="truncate text-xs font-500">{bm.artist} - {bm.title}</p>
|
||||||
<p class="text-xs text-text-secondary">[{bm.version}] · ★{bm.starRating.toFixed(1)} · {bm.bpm}bpm</p>
|
<p class="text-xs text-text-secondary">[{bm.version}] · {bm.starRating.toFixed(2)}★ · {bm.bpm}bpm</p>
|
||||||
{:else}
|
{:else}
|
||||||
<p class="text-xs text-text-secondary">#{slot.beatmapId}</p>
|
<p class="text-xs text-text-secondary">#{slot.beatmapId}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user