groups init

This commit is contained in:
yohlo
2026-02-25 19:54:51 -06:00
parent 2dd3e5b170
commit f83a7d69c8
17 changed files with 1306 additions and 17 deletions

View File

@@ -38,6 +38,7 @@ import { Route as AuthedAdminPreviewRouteImport } from './routes/_authed/admin/p
import { Route as AuthedAdminBadgesRouteImport } from './routes/_authed/admin/badges'
import { Route as AuthedAdminActivitiesRouteImport } from './routes/_authed/admin/activities'
import { Route as AuthedAdminTournamentsIndexRouteImport } from './routes/_authed/admin/tournaments/index'
import { Route as AuthedTournamentsIdGroupsRouteImport } from './routes/_authed/tournaments/$id.groups'
import { Route as AuthedTournamentsIdBracketRouteImport } from './routes/_authed/tournaments/$id.bracket'
import { Route as AuthedAdminTournamentsIdIndexRouteImport } from './routes/_authed/admin/tournaments/$id/index'
import { Route as ApiFilesCollectionRecordIdFileRouteImport } from './routes/api/files/$collection/$recordId/$file'
@@ -192,6 +193,12 @@ const AuthedAdminTournamentsIndexRoute =
path: '/tournaments/',
getParentRoute: () => AuthedAdminRoute,
} as any)
const AuthedTournamentsIdGroupsRoute =
AuthedTournamentsIdGroupsRouteImport.update({
id: '/tournaments/$id/groups',
path: '/tournaments/$id/groups',
getParentRoute: () => AuthedRoute,
} as any)
const AuthedTournamentsIdBracketRoute =
AuthedTournamentsIdBracketRouteImport.update({
id: '/tournaments/$id/bracket',
@@ -258,6 +265,7 @@ export interface FileRoutesByFullPath {
'/admin/': typeof AuthedAdminIndexRoute
'/tournaments/': typeof AuthedTournamentsIndexRoute
'/tournaments/$id/bracket': typeof AuthedTournamentsIdBracketRoute
'/tournaments/$id/groups': typeof AuthedTournamentsIdGroupsRoute
'/admin/tournaments/': typeof AuthedAdminTournamentsIndexRoute
'/admin/tournaments/$id/assign-partners': typeof AuthedAdminTournamentsIdAssignPartnersRoute
'/admin/tournaments/$id/teams': typeof AuthedAdminTournamentsIdTeamsRoute
@@ -293,6 +301,7 @@ export interface FileRoutesByTo {
'/admin': typeof AuthedAdminIndexRoute
'/tournaments': typeof AuthedTournamentsIndexRoute
'/tournaments/$id/bracket': typeof AuthedTournamentsIdBracketRoute
'/tournaments/$id/groups': typeof AuthedTournamentsIdGroupsRoute
'/admin/tournaments': typeof AuthedAdminTournamentsIndexRoute
'/admin/tournaments/$id/assign-partners': typeof AuthedAdminTournamentsIdAssignPartnersRoute
'/admin/tournaments/$id/teams': typeof AuthedAdminTournamentsIdTeamsRoute
@@ -331,6 +340,7 @@ export interface FileRoutesById {
'/_authed/admin/': typeof AuthedAdminIndexRoute
'/_authed/tournaments/': typeof AuthedTournamentsIndexRoute
'/_authed/tournaments/$id/bracket': typeof AuthedTournamentsIdBracketRoute
'/_authed/tournaments/$id/groups': typeof AuthedTournamentsIdGroupsRoute
'/_authed/admin/tournaments/': typeof AuthedAdminTournamentsIndexRoute
'/_authed/admin/tournaments/$id/assign-partners': typeof AuthedAdminTournamentsIdAssignPartnersRoute
'/_authed/admin/tournaments/$id/teams': typeof AuthedAdminTournamentsIdTeamsRoute
@@ -369,6 +379,7 @@ export interface FileRouteTypes {
| '/admin/'
| '/tournaments/'
| '/tournaments/$id/bracket'
| '/tournaments/$id/groups'
| '/admin/tournaments/'
| '/admin/tournaments/$id/assign-partners'
| '/admin/tournaments/$id/teams'
@@ -404,6 +415,7 @@ export interface FileRouteTypes {
| '/admin'
| '/tournaments'
| '/tournaments/$id/bracket'
| '/tournaments/$id/groups'
| '/admin/tournaments'
| '/admin/tournaments/$id/assign-partners'
| '/admin/tournaments/$id/teams'
@@ -441,6 +453,7 @@ export interface FileRouteTypes {
| '/_authed/admin/'
| '/_authed/tournaments/'
| '/_authed/tournaments/$id/bracket'
| '/_authed/tournaments/$id/groups'
| '/_authed/admin/tournaments/'
| '/_authed/admin/tournaments/$id/assign-partners'
| '/_authed/admin/tournaments/$id/teams'
@@ -673,6 +686,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof AuthedAdminTournamentsIndexRouteImport
parentRoute: typeof AuthedAdminRoute
}
'/_authed/tournaments/$id/groups': {
id: '/_authed/tournaments/$id/groups'
path: '/tournaments/$id/groups'
fullPath: '/tournaments/$id/groups'
preLoaderRoute: typeof AuthedTournamentsIdGroupsRouteImport
parentRoute: typeof AuthedRoute
}
'/_authed/tournaments/$id/bracket': {
id: '/_authed/tournaments/$id/bracket'
path: '/tournaments/$id/bracket'
@@ -758,6 +778,7 @@ interface AuthedRouteChildren {
AuthedTournamentsTournamentIdRoute: typeof AuthedTournamentsTournamentIdRoute
AuthedTournamentsIndexRoute: typeof AuthedTournamentsIndexRoute
AuthedTournamentsIdBracketRoute: typeof AuthedTournamentsIdBracketRoute
AuthedTournamentsIdGroupsRoute: typeof AuthedTournamentsIdGroupsRoute
}
const AuthedRouteChildren: AuthedRouteChildren = {
@@ -771,6 +792,7 @@ const AuthedRouteChildren: AuthedRouteChildren = {
AuthedTournamentsTournamentIdRoute: AuthedTournamentsTournamentIdRoute,
AuthedTournamentsIndexRoute: AuthedTournamentsIndexRoute,
AuthedTournamentsIdBracketRoute: AuthedTournamentsIdBracketRoute,
AuthedTournamentsIdGroupsRoute: AuthedTournamentsIdGroupsRoute,
}
const AuthedRouteWithChildren =

View File

@@ -5,6 +5,8 @@ import {
} from "@/features/tournaments/queries";
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
import SeedTournament from "@/features/tournaments/components/seed-tournament";
import SetupGroupStage from "@/features/tournaments/components/setup-group-stage";
import GroupStageView from "@/features/tournaments/components/group-stage-view";
import { Container } from "@mantine/core";
import { useMemo } from "react";
import { BracketData } from "@/features/bracket/types";
@@ -43,6 +45,10 @@ function RouteComponent() {
const { roles } = useAuth();
const isAdmin = roles?.includes('Admin') || false;
const isGroupStage = useMemo(() => {
return tournament.matches?.some((match) => match.round === -1) || false;
}, [tournament.matches]);
const bracket: BracketData = useMemo(() => {
if (!tournament.matches || tournament.matches.length === 0) {
return { winners: [], losers: [] };
@@ -52,6 +58,7 @@ function RouteComponent() {
const losersMap = new Map<number, Match[]>();
tournament.matches
.filter((match) => match.round !== -1)
.sort((a, b) => a.lid - b.lid)
.forEach((match) => {
if (!match.is_losers_bracket) {
@@ -79,15 +86,30 @@ function RouteComponent() {
return (
<Container size="md" px={0}>
{ isAdmin && <SpotifyControlsBar />}
{ isAdmin && !tournament.regional && <SpotifyControlsBar />}
{tournament.matches?.length ? (
<BracketView bracket={bracket} showControls />
isGroupStage ? (
<GroupStageView
groups={tournament.groups || []}
matches={tournament.matches}
showControls
/>
) : (
<BracketView bracket={bracket} showControls />
)
) : (
<SeedTournament
tournamentId={tournament.id}
teams={tournament.teams || []}
isRegional={tournament.regional}
/>
tournament.regional === true ? (
<SetupGroupStage
tournamentId={tournament.id}
teams={tournament.teams || []}
/>
) : (
<SeedTournament
tournamentId={tournament.id}
teams={tournament.teams || []}
isRegional={tournament.regional}
/>
)
)}
</Container>
);

View File

@@ -4,7 +4,6 @@ import {
useTournament,
} from "@/features/tournaments/queries";
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
import SeedTournament from "@/features/tournaments/components/seed-tournament";
import { Container } from "@mantine/core";
import { useMemo } from "react";
import { BracketData } from "@/features/bracket/types";
@@ -18,7 +17,7 @@ export const Route = createFileRoute("/_authed/tournaments/$id/bracket")({
queryClient,
tournamentQueries.details(params.id)
);
if (!tournament) throw redirect({ to: "/admin/tournaments" });
if (!tournament) throw redirect({ to: "/tournaments" });
return {
tournament,
};
@@ -26,10 +25,9 @@ export const Route = createFileRoute("/_authed/tournaments/$id/bracket")({
loader: ({ context }) => ({
fullWidth: true,
withPadding: false,
showSpotifyPanel: true,
header: {
withBackButton: true,
title: `${context.tournament.name}`,
title: `${context.tournament.name} - Bracket`,
},
}),
component: RouteComponent,
@@ -48,6 +46,7 @@ function RouteComponent() {
const losersMap = new Map<number, Match[]>();
tournament.matches
.filter((match) => match.round !== -1)
.sort((a, b) => a.lid - b.lid)
.forEach((match) => {
if (!match.is_losers_bracket) {

View File

@@ -0,0 +1,45 @@
import { createFileRoute, redirect } from "@tanstack/react-router";
import {
tournamentQueries,
useTournament,
} from "@/features/tournaments/queries";
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
import GroupStageView from "@/features/tournaments/components/group-stage-view";
import { Container } from "@mantine/core";
export const Route = createFileRoute("/_authed/tournaments/$id/groups")({
beforeLoad: async ({ context, params }) => {
const { queryClient } = context;
const tournament = await ensureServerQueryData(
queryClient,
tournamentQueries.details(params.id)
);
if (!tournament) throw redirect({ to: "/tournaments" });
return {
tournament,
};
},
loader: ({ context }) => ({
fullWidth: true,
withPadding: false,
header: {
withBackButton: true,
title: `${context.tournament.name} - Groups`,
},
}),
component: RouteComponent,
});
function RouteComponent() {
const { id } = Route.useParams();
const { data: tournament } = useTournament(id);
return (
<Container size="md" px={0}>
<GroupStageView
groups={tournament.groups || []}
matches={tournament.matches || []}
/>
</Container>
);
}