Files
flxn-app/src/lib/pocketbase/services/teams.ts
T
2026-07-12 21:26:16 -07:00

131 lines
4.3 KiB
TypeScript

import { logger } from "@/lib/logger";
import PocketBase from "pocketbase";
import { transformMatch, transformTeam, transformTeamInfo } from "@/lib/pocketbase/util/transform-types";
import { Team, TeamInfo, TeamInput, TeamUpdateInput, TeamStats } from "@/features/teams/types";
import { Match } from "@/features/matches/types";
export function createTeamsService(pb: PocketBase) {
return {
async getTeamInfo(id: string): Promise<TeamInfo> {
const result = await pb.collection("teams").getOne(id, {
fields: "id,name,primary_color,accent_color,logo",
expand: "players"
});
return transformTeamInfo(result);
},
async listTeamInfos(): Promise<TeamInfo[]> {
logger.info("PocketBase | Listing team infos");
const result = await pb.collection("teams").getFullList({
fields: "id,name,primary_color,accent_color,logo",
expand: "players"
});
return result.map(transformTeamInfo);
},
async getTeam(id: string): Promise<Team | null> {
const result = await pb.collection("teams").getOne(id, {
expand: "players, tournaments",
});
return transformTeam(result);
},
async createTeam(data: TeamInput): Promise<Team> {
logger.info("PocketBase | Creating team", data);
try {
if (data.players.length > 0) {
const playerFilter = data.players
.map((playerId) => `id = "${playerId}"`)
.join(" || ");
const existingPlayers = await pb.collection("players").getFullList({
filter: playerFilter,
fields: "id",
});
if (existingPlayers.length !== data.players.length) {
const foundIds = new Set(existingPlayers.map((player) => player.id));
const missingId = data.players.find((playerId) => !foundIds.has(playerId));
throw new Error(`Player with ID ${missingId} not found`);
}
}
const result = await pb.collection("teams").create({
...data,
players: data.players
});
await Promise.all(
data.players.map((playerId) =>
pb.collection("players").update(playerId, {
"teams+": result.id
})
)
);
return transformTeam(await pb.collection("teams").getOne(result.id, {
expand: "players, tournaments"
}));
} catch (error) {
logger.error("PocketBase | Error creating team", error);
throw error;
}
},
async updateTeam(id: string, data: TeamUpdateInput): Promise<Team> {
logger.info("PocketBase | Updating team", { id, updates: Object.keys(data) });
try {
const existingTeam = await pb.collection("teams").getOne(id).catch(() => null);
if (!existingTeam) {
throw new Error(`Team with ID ${id} not found`);
}
const result = await pb.collection("teams").update(id, data);
const updated = await pb.collection("teams").getOne(result.id, {
expand: "players, tournaments",
// @ts-ignore - Add cache busting
$cancelKey: Date.now().toString()
});
return transformTeam(updated);
} catch (error) {
logger.error("PocketBase | Error updating team", error);
throw error;
}
},
async getTeamStats(id: string): Promise<TeamStats | null> {
try {
const result = await pb.collection("team_stats").getFirstListItem(`team_id="${id}"`);
return result as unknown as TeamStats;
} catch (error) {
logger.info("PocketBase | No team stats found", id);
return null;
}
},
async getTeamMatches(teamId: string): Promise<Match[]> {
const teamFilter = `home = "${teamId}" || away = "${teamId}"`
const result = await pb.collection("matches").getFullList({
filter: `(${teamFilter}) && (status = "ended" || status = "started")`,
sort: "-start_time",
expand: "tournament,home,away,home.players,away.players",
});
return result.map((match) => transformMatch(match));
},
async getTeamsWithFilter(filter: string, expand?: string): Promise<any[]> {
logger.info("PocketBase | Getting teams with filter", { filter, expand });
const result = await pb.collection("teams").getFullList({
filter,
expand,
});
return result;
},
};
}