diff --git a/pb_migrations/1757615830_updated_matches.js b/pb_migrations/1757615830_updated_matches.js
new file mode 100644
index 0000000..12ce5a4
--- /dev/null
+++ b/pb_migrations/1757615830_updated_matches.js
@@ -0,0 +1,31 @@
+///
+migrate((app) => {
+ const collection = app.findCollectionByNameOrId("pbc_2541054544")
+
+ // add field
+ collection.fields.addAt(21, new Field({
+ "hidden": false,
+ "id": "select2063623452",
+ "maxSelect": 1,
+ "name": "status",
+ "presentable": false,
+ "required": false,
+ "system": false,
+ "type": "select",
+ "values": [
+ "tbd",
+ "ready",
+ "started",
+ "ended"
+ ]
+ }))
+
+ return app.save(collection)
+}, (app) => {
+ const collection = app.findCollectionByNameOrId("pbc_2541054544")
+
+ // remove field
+ collection.fields.removeById("select2063623452")
+
+ return app.save(collection)
+})
diff --git a/src/app/routes/_authed/admin/tournaments/run.$id.tsx b/src/app/routes/_authed/admin/tournaments/run.$id.tsx
index b3c91b1..d00930c 100644
--- a/src/app/routes/_authed/admin/tournaments/run.$id.tsx
+++ b/src/app/routes/_authed/admin/tournaments/run.$id.tsx
@@ -1,5 +1,5 @@
import { createFileRoute, redirect, useRouter } from '@tanstack/react-router'
-import { tournamentQueries } from '@/features/tournaments/queries'
+import { tournamentQueries, useTournament } from '@/features/tournaments/queries'
import { ensureServerQueryData } from '@/lib/tanstack-query/utils/ensure'
import SeedTournament from '@/features/tournaments/components/seed-tournament'
import { Container, Alert, Text } from '@mantine/core'
@@ -32,8 +32,8 @@ export const Route = createFileRoute('/_authed/admin/tournaments/run/$id')({
})
function RouteComponent() {
- const { tournament } = Route.useRouteContext()
- const router = useRouter()
+ const { id } = Route.useParams();
+ const { data: tournament } = useTournament(id)
const bracket: BracketData = useMemo(() => {
if (!tournament.matches || tournament.matches.length === 0) {
@@ -67,18 +67,12 @@ function RouteComponent() {
return { winners, losers }
}, [tournament.matches])
-
- const handleSuccess = () => {
- router.navigate({
- to: '/admin/tournaments/$id',
- params: { id: tournament.id }
- })
- }
-
const handleStartMatch = (match: Match) => {
}
+ console.log(tournament.matches)
+
return (
{
@@ -88,7 +82,6 @@ function RouteComponent() {
)
}
diff --git a/src/app/routes/refresh-session.tsx b/src/app/routes/refresh-session.tsx
index 615318c..8ab33a8 100644
--- a/src/app/routes/refresh-session.tsx
+++ b/src/app/routes/refresh-session.tsx
@@ -18,7 +18,7 @@ function RouteComponent() {
const urlParams = new URLSearchParams(window.location.search)
const redirect = urlParams.get('redirect')
- if (redirect) {
+ if (redirect && !redirect.startsWith('/_serverFn')) {
window.location.href = decodeURIComponent(redirect)
} else {
window.location.href = '/'
diff --git a/src/features/bracket/components/match-card.tsx b/src/features/bracket/components/match-card.tsx
index ef6b37b..403eef4 100644
--- a/src/features/bracket/components/match-card.tsx
+++ b/src/features/bracket/components/match-card.tsx
@@ -35,8 +35,8 @@ export const MatchCard: React.FC = ({
);
const showToolbar = useMemo(
- () => match.home && match.away && onStartMatch,
- [match.home, match.away]
+ () => match.status === "ready" && onStartMatch,
+ [match.status, onStartMatch]
);
const handleAnnounce = useCallback(
diff --git a/src/features/matches/server.ts b/src/features/matches/server.ts
index 798e3b9..d094695 100644
--- a/src/features/matches/server.ts
+++ b/src/features/matches/server.ts
@@ -58,6 +58,7 @@ export const generateTournamentBracket = createServerFn()
home_from_loser: match.home_from_loser || false,
away_from_loser: match.away_from_loser || false,
is_losers_bracket: false,
+ status: "tbd",
tournament: tournamentId,
};
@@ -77,6 +78,10 @@ export const generateTournamentBracket = createServerFn()
}
}
+ if (matchInput.home && matchInput.away) {
+ matchInput.status = "ready"
+ }
+
matchInputs.push(matchInput);
});
});
@@ -97,6 +102,7 @@ export const generateTournamentBracket = createServerFn()
home_from_loser: match.home_from_loser || false,
away_from_loser: match.away_from_loser || false,
is_losers_bracket: true,
+ status: "tbd",
tournament: tournamentId,
};
@@ -135,7 +141,38 @@ export const startMatch = createServerFn()
}
match = await pbAdmin.updateMatch(data, {
- start_time: new Date().toISOString()
+ start_time: new Date().toISOString(),
+ status: "started"
+ });
+
+ return match;
+ }
+ ));
+
+const endMatchSchema = z.object({
+ matchId: z.string(),
+ home_cups: z.number(),
+ away_cups: z.number(),
+ ot_count: z.number()
+});
+export const endMatch = createServerFn()
+ .validator(endMatchSchema)
+ .middleware([superTokensAdminFunctionMiddleware])
+ .handler(async ({ data: { matchId, home_cups, away_cups, ot_count } }) =>
+ toServerResult(async () => {
+ logger.info('Ending match', matchId);
+
+ let match = await pbAdmin.getMatch(matchId);
+ if (!match) {
+ throw new Error('Match not found');
+ }
+
+ match = await pbAdmin.updateMatch(matchId, {
+ end_time: new Date().toISOString(),
+ status: "ended",
+ home_cups,
+ away_cups,
+ ot_count
})
}
));
\ No newline at end of file
diff --git a/src/features/matches/types.ts b/src/features/matches/types.ts
index 2174cc6..341165e 100644
--- a/src/features/matches/types.ts
+++ b/src/features/matches/types.ts
@@ -2,6 +2,8 @@ import { z } from "zod";
import { TeamInfo } from "../teams/types";
import { TournamentInfo } from "../tournaments/types";
+export type MatchStatus = "tbd" | "ready" | "started" | "ended";
+
/**
* class TMatchSlot(BaseModel):
pass
@@ -52,6 +54,7 @@ export interface Match {
home_from_loser: boolean;
away_from_loser: boolean;
is_losers_bracket: boolean;
+ status: MatchStatus;
tournament: TournamentInfo;
home?: TeamInfo;
away?: TeamInfo;
@@ -77,6 +80,7 @@ export const matchInputSchema = z.object({
home_from_loser: z.boolean().optional().default(false),
away_from_loser: z.boolean().optional().default(false),
is_losers_bracket: z.boolean().optional().default(false),
+ status: z.enum(["tbd", "ready", "started", "ended"]).optional().default("tbd"),
tournament: z.string().min(1),
home: z.string().min(1).optional(),
away: z.string().min(1).optional(),
diff --git a/src/features/tournaments/components/seed-tournament.tsx b/src/features/tournaments/components/seed-tournament.tsx
index cec071e..74fdd6a 100644
--- a/src/features/tournaments/components/seed-tournament.tsx
+++ b/src/features/tournaments/components/seed-tournament.tsx
@@ -17,20 +17,21 @@ import Avatar from "@/components/avatar";
import { useBracketPreview } from "@/features/bracket/queries";
import { BracketData } from "@/features/bracket/types";
import BracketView from "@/features/bracket/components/bracket-view";
+import { useQueryClient } from "@tanstack/react-query";
+import { tournamentKeys } from "../queries";
interface SeedTournamentProps {
tournamentId: string;
teams: TeamInfo[];
- onSuccess?: () => void;
}
const SeedTournament: React.FC = ({
tournamentId,
- teams,
- onSuccess,
+ teams
}) => {
const [orderedTeams, setOrderedTeams] = useState(teams);
const { data: bracketPreview } = useBracketPreview(teams.length);
+ const queryClient = useQueryClient()
const bracket: BracketData = useMemo(
() => ({
@@ -56,7 +57,9 @@ const SeedTournament: React.FC = ({
mutationFn: generateTournamentBracket,
successMessage: "Tournament bracket generated successfully!",
onSuccess: () => {
- onSuccess?.();
+ queryClient.invalidateQueries({
+ queryKey: tournamentKeys.details(tournamentId)
+ })
},
});
diff --git a/src/lib/pocketbase/util/transform-types.ts b/src/lib/pocketbase/util/transform-types.ts
index 9883a36..2f0e5e3 100644
--- a/src/lib/pocketbase/util/transform-types.ts
+++ b/src/lib/pocketbase/util/transform-types.ts
@@ -43,6 +43,7 @@ export const transformMatch = (record: any): Match => {
home_from_loser: record.home_from_loser,
away_from_loser: record.away_from_loser,
is_losers_bracket: record.is_losers_bracket,
+ status: record.status || "tbd",
tournament: transformTournamentInfo(record.expand?.tournament),
home: record.expand?.home ? transformTeamInfo(record.expand.home) : undefined,
away: record.expand?.away ? transformTeamInfo(record.expand.away) : undefined,