Files
flxn-app/src/lib/pocketbase/services/tournaments.ts
2025-10-16 09:12:11 -05:00

194 lines
6.3 KiB
TypeScript

import { logger } from "@/lib/logger";
import type {
Tournament,
TournamentInfo,
TournamentInput,
TournamentUpdateInput,
} from "@/features/tournaments/types";
import type { Team } from "@/features/teams/types";
import PocketBase from "pocketbase";
import { transformFreeAgent, transformTournament, transformTournamentInfo } from "@/lib/pocketbase/util/transform-types";
import { transformTeam } from "@/lib/pocketbase/util/transform-types";
import { PlayerInfo } from "@/features/players/types";
export function createTournamentsService(pb: PocketBase) {
return {
async getTournament(id: string, isAdmin: boolean = false): Promise<Tournament> {
const [tournamentResult, teamStatsResult] = await Promise.all([
pb.collection("tournaments").getOne(id, {
expand: "teams, teams.players, matches, matches.tournament, matches.home, matches.away, matches.home.players, matches.away.players",
}),
pb.collection("team_stats_per_tournament").getFullList({
filter: `tournament_id = "${id}"`,
sort: "-wins,-total_cups_made"
})
]);
tournamentResult.team_stats = teamStatsResult;
return transformTournament(tournamentResult, isAdmin);
},
async getMostRecentTournament(): Promise<Tournament> {
const result = await pb
.collection("tournaments")
.getFirstListItem('',
{
expand: "teams, teams.players, matches, matches.tournament, matches.home, matches.away, matches.home.players, matches.away.players",
sort: "-start_time",
}
);
const teamStatsResult = await pb.collection("team_stats_per_tournament").getFullList({
filter: `tournament_id = "${result.id}"`,
sort: "-wins,-total_cups_made"
});
result.team_stats = teamStatsResult;
return transformTournament(result);
},
async listTournaments(): Promise<TournamentInfo[]> {
const result = await pb
.collection("tournaments")
.getFullList({
expand: "teams,teams.players,matches",
sort: "-start_time",
});
const tournamentsWithStats = await Promise.all(result.map(async (tournament) => {
const teamStats = await pb.collection("team_stats_per_tournament").getFullList({
filter: `tournament_id = "${tournament.id}"`,
sort: "-wins,-total_cups_made"
});
tournament.team_stats = teamStats;
return tournament;
}));
return tournamentsWithStats.map(transformTournamentInfo);
},
async createTournament(data: TournamentInput): Promise<Tournament> {
const result = await pb
.collection("tournaments")
.create<Tournament>(data);
return transformTournament(result);
},
async updateTournament(
id: string,
data: Partial<TournamentUpdateInput>
): Promise<Tournament> {
const result = await pb
.collection("tournaments")
.update<Tournament>(id, data);
return transformTournament(result);
},
async enrollTeam(
tournamentId: string,
teamId: string
): Promise<Tournament> {
const result = await pb
.collection("tournaments")
.update<Tournament>(
tournamentId,
{ "teams+": teamId },
{ expand: "teams, teams.players" }
);
await pb
.collection("teams")
.update(teamId, { "tournaments+": tournamentId });
return transformTournament(result);
},
async unenrollTeam(
tournamentId: string,
teamId: string
): Promise<Tournament> {
const result = await pb
.collection("tournaments")
.update<Tournament>(
tournamentId,
{ "teams-": teamId },
{ expand: "teams, teams.players" }
);
await pb
.collection("teams")
.update(teamId, { "tournaments-": tournamentId });
return transformTournament(result);
},
async updateTournamentMatches(
tournamentId: string,
matchIds: string[]
): Promise<Tournament> {
logger.info("PocketBase | Updating tournament matches", { tournamentId, matchCount: matchIds.length });
const result = await pb
.collection("tournaments")
.update<Tournament>(tournamentId, {
matches: matchIds
});
return transformTournament(result);
},
async getUnenrolledTeams(tournamentId: string): Promise<Team[]> {
try {
const tournament = await pb
.collection("tournaments")
.getOne(tournamentId, {
fields: "teams",
});
const enrolledTeamIds = tournament.teams || [];
if (enrolledTeamIds.length === 0) {
const allTeams = await pb.collection("teams").getFullList({
expand: "players",
});
return allTeams.map(transformTeam);
}
const filter = enrolledTeamIds
.map((teamId: string) => `id != "${teamId}"`)
.join(" && ");
const availableTeams = await pb.collection("teams").getFullList({
filter,
expand: "players",
});
return availableTeams.map(transformTeam);
} catch (error) {
logger.error("PocketBase | Error getting unenrolled teams", error);
throw error;
}
},
async enrollFreeAgent(playerId: string, phone: string, tournamentId: string): Promise<void> {
await pb.collection("free_agents").create({
tournament: tournamentId,
player: playerId,
phone: phone
});
},
async unenrollFreeAgent(playerId: string, tournamentId: string): Promise<void> {
const result = await pb.collection("free_agents").getFirstListItem(
`player = "${playerId}" && tournament = "${tournamentId}"`
);
await pb.collection("free_agents").delete(result.id);
},
async getFreeAgents(tournamentId: string): Promise<{ id: string, phone: string, player: PlayerInfo | undefined }[]> {
try {
const free_agents = await pb
.collection("free_agents")
.getFullList({ filter: `tournament = "${tournamentId}"`,
expand: 'player'
});
return free_agents.map(transformFreeAgent);
} catch (error) {
logger.error("PocketBase | Error getting unenrolled teams", error);
throw error;
}
},
};
}