add verified mappools

This commit is contained in:
2026-03-06 16:33:19 +01:00
parent 10906560f4
commit 2a73be97b3
5 changed files with 77 additions and 17 deletions

View File

@@ -40,7 +40,8 @@ export const mappool = pgTable('mappool', {
id: uuid('id').primaryKey().defaultRandom(), id: uuid('id').primaryKey().defaultRandom(),
name: text('name').notNull(), name: text('name').notNull(),
createdBy: text('created_by'), createdBy: text('created_by'),
createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull() createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
verifiedAt: timestamp('verified_at', { withTimezone: true })
}); });
// ── Mappool Slots ─────────────────────────────────────────────────────── // ── Mappool Slots ───────────────────────────────────────────────────────

View File

@@ -184,8 +184,9 @@ async function tryMatchFromQueue() {
} }
async function selectMappoolForRating(avgElo: number) { async function selectMappoolForRating(avgElo: number) {
// Get all mappools with their slots // Only use verified mappools
const pools = await db.query.mappool.findMany({ const pools = await db.query.mappool.findMany({
where: (m, { isNotNull }) => isNotNull(m.verifiedAt),
with: { slots: true } with: { slots: true }
}); });

View File

@@ -60,7 +60,12 @@
class="group flex items-center justify-between rounded-lg border border-border bg-surface-800 p-4 transition-colors hover:border-accent/40 hover:bg-surface-700" class="group flex items-center justify-between rounded-lg border border-border bg-surface-800 p-4 transition-colors hover:border-accent/40 hover:bg-surface-700"
> >
<div> <div>
<h2 class="text-sm font-600">{pool.name}</h2> <div class="flex items-center gap-2">
<h2 class="text-sm font-600">{pool.name}</h2>
{#if pool.verifiedAt}
<span class="rounded border border-green-500/30 bg-green-500/10 px-1.5 py-0.5 text-[10px] font-600 text-green-400">✓ Verified</span>
{/if}
</div>
<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}

View File

@@ -88,7 +88,8 @@ export const load: PageServerLoad = async ({ params, locals }) => {
return { return {
pool: { ...pool, slots: slotsWithBeatmaps }, pool: { ...pool, slots: slotsWithBeatmaps },
canEdit: isOwner || isAdmin canEdit: isOwner || isAdmin,
isAdmin
}; };
}; };
@@ -188,6 +189,30 @@ export const actions: Actions = {
return { success: true }; return { success: true };
}, },
verify: async ({ params, locals }) => {
requireAuth(locals);
if (locals.user!.role !== 'admin') error(403, 'Admins only');
await db
.update(mappool)
.set({ verifiedAt: new Date() })
.where(eq(mappool.id, params.id));
return { success: true };
},
unverify: async ({ params, locals }) => {
requireAuth(locals);
if (locals.user!.role !== 'admin') error(403, 'Admins only');
await db
.update(mappool)
.set({ verifiedAt: null })
.where(eq(mappool.id, params.id));
return { success: true };
},
deletePool: async ({ params, locals }) => { deletePool: async ({ params, locals }) => {
const pool = await db.query.mappool.findFirst({ const pool = await db.query.mappool.findFirst({
where: eq(mappool.id, params.id) where: eq(mappool.id, params.id)

View File

@@ -108,6 +108,11 @@
{:else} {:else}
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<h1 class="text-2xl font-700 tracking-tight">{data.pool.name}</h1> <h1 class="text-2xl font-700 tracking-tight">{data.pool.name}</h1>
{#if data.pool.verifiedAt}
<span class="flex items-center gap-1 rounded border border-green-500/30 bg-green-500/10 px-2 py-0.5 text-xs font-600 text-green-400">
✓ Verified
</span>
{/if}
{#if data.canEdit} {#if data.canEdit}
<button <button
onclick={() => { onclick={() => {
@@ -128,19 +133,42 @@
</div> </div>
</div> </div>
{#if data.canEdit} <div class="flex items-center gap-2">
<form method="post" action="?/deletePool" use:enhance> {#if data.isAdmin}
<button {#if data.pool.verifiedAt}
type="submit" <form method="post" action="?/unverify" use:enhance>
onclick={(e) => { <button
if (!confirm('Delete this mappool?')) e.preventDefault(); type="submit"
}} class="rounded-md border border-green-500/30 px-3 py-1.5 text-sm text-green-400 transition-colors hover:bg-green-500/10"
class="rounded-md border border-red-500/30 px-3 py-1.5 text-sm text-red-400 transition-colors hover:bg-red-500/10" >
> Unverify
Delete Pool </button>
</button> </form>
</form> {:else}
{/if} <form method="post" action="?/verify" use:enhance>
<button
type="submit"
class="rounded-md border border-green-500/30 px-3 py-1.5 text-sm text-green-400 transition-colors hover:bg-green-500/10"
>
✓ Verify
</button>
</form>
{/if}
{/if}
{#if data.canEdit}
<form method="post" action="?/deletePool" use:enhance>
<button
type="submit"
onclick={(e) => {
if (!confirm('Delete this mappool?')) e.preventDefault();
}}
class="rounded-md border border-red-500/30 px-3 py-1.5 text-sm text-red-400 transition-colors hover:bg-red-500/10"
>
Delete Pool
</button>
</form>
{/if}
</div>
</div> </div>
<!-- Add Map --> <!-- Add Map -->