matches fast maybe
This commit is contained in:
@@ -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');
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user