matches fast maybe

This commit is contained in:
nicksales72
2026-03-13 11:08:27 -04:00
committed by Stan Runge
parent 703c602905
commit 90420aa18d
2 changed files with 61 additions and 32 deletions

View File

@@ -11,12 +11,23 @@ import type { PageServerLoad, Actions } from './$types';
export const load: PageServerLoad = async ({ locals }) => { export const load: PageServerLoad = async ({ locals }) => {
requireAuth(locals); requireAuth(locals);
const [matches, teams, mappools, userTeamMemberships] = await Promise.all([ const matches = await db.query.match.findMany({
db.query.match.findMany({
with: { participants: { with: { team: true } }, mappool: { with: { slots: true } } }, with: { participants: { with: { team: true } }, mappool: { with: { slots: true } } },
orderBy: desc(match.createdAt), orderBy: desc(match.createdAt),
limit: 50 limit: 50
}), });
return {
matches,
canCreateMatch: hasRole(locals.user!.role, 'referee')
};
};
export const actions: Actions = {
loadCreateFormData: async ({ locals }) => {
requireAuth(locals);
const [teams, mappools, userTeamMemberships] = await Promise.all([
db.query.team.findMany({ db.query.team.findMany({
with: { members: true }, with: { members: true },
orderBy: (t, { asc }) => [asc(t.name)] orderBy: (t, { asc }) => [asc(t.name)]
@@ -32,15 +43,12 @@ export const load: PageServerLoad = async ({ locals }) => {
]); ]);
return { return {
matches,
teams: teams.map((t) => ({ ...t, memberCount: t.members.length })), teams: teams.map((t) => ({ ...t, memberCount: t.members.length })),
mappools, mappools,
userTeams: userTeamMemberships.map((m) => m.team), userTeams: userTeamMemberships.map((m) => m.team)
canCreateMatch: hasRole(locals.user!.role, 'referee')
}; };
}; },
export const actions: Actions = {
createMatch: async ({ request, locals }) => { createMatch: async ({ request, locals }) => {
// Only referees and admins can create matches manually // Only referees and admins can create matches manually
requireRole(locals, 'referee', 'Only referees and admins can create matches'); requireRole(locals, 'referee', 'Only referees and admins can create matches');

View File

@@ -9,6 +9,8 @@
let createError = $state(''); let createError = $state('');
let inviteError = $state(''); let inviteError = $state('');
let inviteSuccess = $state(false); let inviteSuccess = $state(false);
let formDataLoading = $state(false);
let formData = $state<any>(null);
// Challenge form state // Challenge form state
let selectedCreatorTeamId = $state(''); let selectedCreatorTeamId = $state('');
@@ -18,8 +20,25 @@
let useCustomBo = $state(false); let useCustomBo = $state(false);
let opponentSearch = $state(''); let opponentSearch = $state('');
const personalTeam = $derived((data as any).userTeams?.find((t: any) => t.isPersonal)); // Load form data when create/invite modals open
const nonPersonalUserTeams = $derived((data as any).userTeams?.filter((t: any) => !t.isPersonal) ?? []); $effect(async () => {
if ((showCreate || showInvite) && !formData && !formDataLoading) {
formDataLoading = true;
const formData_elem = new FormData();
const response = await fetch('?/loadCreateFormData', {
method: 'POST',
body: formData_elem
});
const result = await response.json();
if (result.data) {
formData = result.data;
}
formDataLoading = false;
}
});
const personalTeam = $derived((formData ?? data).userTeams?.find((t: any) => t.isPersonal));
const nonPersonalUserTeams = $derived((formData ?? data).userTeams?.filter((t: any) => !t.isPersonal) ?? []);
const hasMultipleTeams = $derived(nonPersonalUserTeams.length > 0); const hasMultipleTeams = $derived(nonPersonalUserTeams.length > 0);
// Auto-select personal team by default // Auto-select personal team by default
@@ -29,8 +48,8 @@
} }
}); });
const selectedCreatorTeam = $derived(data.teams.find((t: any) => t.id === selectedCreatorTeamId)); const selectedCreatorTeam = $derived((formData ?? data).teams.find((t: any) => t.id === selectedCreatorTeamId));
const selectedInvitedTeam = $derived(data.teams.find((t: any) => t.id === selectedInvitedTeamId)); const selectedInvitedTeam = $derived((formData ?? data).teams.find((t: any) => t.id === selectedInvitedTeamId));
const creatorIsPersonal = $derived(selectedCreatorTeam?.isPersonal ?? true); const creatorIsPersonal = $derived(selectedCreatorTeam?.isPersonal ?? true);
const creatorMaxSize = $derived(selectedCreatorTeam?.memberCount ?? 1); const creatorMaxSize = $derived(selectedCreatorTeam?.memberCount ?? 1);
@@ -40,7 +59,7 @@
// Filter opponent teams for search // Filter opponent teams for search
const filteredOpponentTeams = $derived( const filteredOpponentTeams = $derived(
data.teams.filter((t: any) => { (formData ?? data).teams.filter((t: any) => {
if (t.id === selectedCreatorTeamId) return false; if (t.id === selectedCreatorTeamId) return false;
if (!opponentSearch) return true; if (!opponentSearch) return true;
return t.name.toLowerCase().includes(opponentSearch.toLowerCase()); return t.name.toLowerCase().includes(opponentSearch.toLowerCase());
@@ -139,20 +158,22 @@
</p> </p>
</div> </div>
<div class="flex gap-2"> <div class="flex gap-2">
{#if (data as any).userTeams?.length > 0} {#if (formData ?? data).userTeams?.length > 0}
<button <button
onclick={() => { showInvite = !showInvite; if (showInvite) showCreate = false; }} onclick={() => { showInvite = !showInvite; if (showInvite) showCreate = false; }}
class="rounded-md border border-accent/30 px-4 py-2 text-sm font-600 text-accent transition-colors hover:bg-accent/10" disabled={formDataLoading && showInvite}
class="rounded-md border border-accent/30 px-4 py-2 text-sm font-600 text-accent transition-colors hover:bg-accent/10 disabled:opacity-50"
> >
{showInvite ? 'Cancel' : 'Challenge'} {showInvite && formDataLoading ? 'Loading...' : showInvite ? 'Cancel' : 'Challenge'}
</button> </button>
{/if} {/if}
{#if data.canCreateMatch} {#if data.canCreateMatch}
<button <button
onclick={() => { showCreate = !showCreate; if (showCreate) showInvite = false; }} onclick={() => { showCreate = !showCreate; if (showCreate) showInvite = false; }}
class="rounded-md bg-accent px-4 py-2 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover" disabled={formDataLoading && showCreate}
class="rounded-md bg-accent px-4 py-2 text-sm font-600 text-surface-900 transition-colors hover:bg-accent-hover disabled:opacity-50"
> >
{showCreate ? 'Cancel' : 'New Match'} {showCreate && formDataLoading ? 'Loading...' : showCreate ? 'Cancel' : 'New Match'}
</button> </button>
{/if} {/if}
</div> </div>