import { createFileRoute, redirect, useNavigate } from "@tanstack/react-router";
import { tournamentQueries, useFreeAgents, useTournament } from "@/features/tournaments/queries";
import { ensureServerQueryData } from "@/lib/tanstack-query/utils/ensure";
import { Stack, Text, Button, Alert, LoadingOverlay, Group, Skeleton } from "@mantine/core";
import { useState } from "react";
import useGenerateRandomTeams from "@/features/tournaments/hooks/use-generate-random-teams";
import useConfirmTeamAssignments from "@/features/tournaments/hooks/use-confirm-team-assignments";
import TeamAssignmentPreview from "@/features/tournaments/components/team-assignment-preview";
import { WarningCircleIcon, ShuffleIcon, CheckCircleIcon } from "@phosphor-icons/react";
import { PlayerInfo } from "@/features/players/types";
import { useQueryClient } from "@tanstack/react-query";
export const Route = createFileRoute("/_authed/admin/tournaments/$id/assign-partners")({
beforeLoad: async ({ context, params }) => {
const { queryClient } = context;
const tournament = await ensureServerQueryData(
queryClient,
tournamentQueries.details(params.id)
);
if (!tournament) throw redirect({ to: "/admin/tournaments" });
return { tournament };
},
loader: ({ context }) => ({
header: {
withBackButton: true,
title: `Manage ${context.tournament.name}`,
},
}),
component: RouteComponent,
pendingComponent: AssignPartnersPending,
});
function AssignPartnersPending() {
return (
);
}
interface TeamAssignment {
player1: PlayerInfo;
player2: PlayerInfo;
teamName: string;
}
function RouteComponent() {
const { id } = Route.useParams();
const navigate = useNavigate();
const queryClient = useQueryClient();
const { data: freeAgents } = useFreeAgents(id);
const [assignments, setAssignments] = useState(null);
const [currentSeed, setCurrentSeed] = useState(undefined);
const generateMutation = useGenerateRandomTeams();
const confirmMutation = useConfirmTeamAssignments();
const hasOddPlayers = freeAgents.length % 2 !== 0;
const hasEnoughPlayers = freeAgents.length >= 2;
const handleGenerate = () => {
generateMutation.mutate(
{ data: { tournamentId: id, seed: currentSeed } },
{
onSuccess: (result) => {
setAssignments(result.assignments);
setCurrentSeed(result.seed);
},
}
);
};
const handleReroll = () => {
if (currentSeed === undefined) return;
generateMutation.mutate(
{ data: { tournamentId: id, seed: currentSeed + 1 } },
{
onSuccess: (result) => {
setAssignments(result.assignments);
setCurrentSeed(result.seed);
},
}
);
};
const handleConfirm = () => {
if (!assignments) return;
const formattedAssignments = assignments.map((a) => ({
player1Id: a.player1.id,
player2Id: a.player2.id,
teamName: a.teamName,
}));
confirmMutation.mutate(
{ data: { tournamentId: id, assignments: formattedAssignments } },
{
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: tournamentQueries.details(id).queryKey });
queryClient.invalidateQueries({ queryKey: tournamentQueries.free_agents(id).queryKey });
navigate({ to: "/admin/tournaments/$id", params: { id } });
},
}
);
};
return (
{freeAgents.length}
{freeAgents.length === 1 ? "player enrolled" : "players enrolled"}
{!hasEnoughPlayers && (
}>
Need at least 2 players to create teams
)}
{hasOddPlayers && (
}>
Cannot create teams with an odd number of players. Please have one player unenroll.
)}
{!assignments && hasEnoughPlayers && !hasOddPlayers && (
}
onClick={handleGenerate}
loading={generateMutation.isPending}
>
Generate Random Pairings
)}
{assignments && (
Partner Assignments
}
onClick={handleReroll}
loading={generateMutation.isPending}
size="sm"
>
Re-roll
}
onClick={handleConfirm}
loading={confirmMutation.isPending}
size="sm"
>
Confirm & Create Teams
)}
);
}