add verified mappools
This commit is contained in:
@@ -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 ───────────────────────────────────────────────────────
|
||||||
|
|||||||
@@ -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 }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -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>
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
<h2 class="text-sm font-600">{pool.name}</h2>
|
<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}
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,6 +133,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
{#if data.isAdmin}
|
||||||
|
{#if data.pool.verifiedAt}
|
||||||
|
<form method="post" action="?/unverify" 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"
|
||||||
|
>
|
||||||
|
Unverify
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
{:else}
|
||||||
|
<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}
|
{#if data.canEdit}
|
||||||
<form method="post" action="?/deletePool" use:enhance>
|
<form method="post" action="?/deletePool" use:enhance>
|
||||||
<button
|
<button
|
||||||
@@ -142,6 +169,7 @@
|
|||||||
</form>
|
</form>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Add Map -->
|
<!-- Add Map -->
|
||||||
{#if data.canEdit}
|
{#if data.canEdit}
|
||||||
|
|||||||
Reference in New Issue
Block a user