predictions

This commit is contained in:
2026-07-14 14:15:34 -07:00
parent e6c72a5789
commit 1783f0e6bc
28 changed files with 2085 additions and 89 deletions
+4 -1
View File
@@ -7,6 +7,7 @@ import { createReactionsService } from "./services/reactions";
import { createActivitiesService } from "./services/activities";
import { createBadgesService } from "./services/badges";
import { createGroupsService } from "./services/groups";
import { createPredictionsService } from "./services/predictions";
class PocketBaseAdminClient {
private pb: PocketBase;
@@ -48,6 +49,7 @@ class PocketBaseAdminClient {
Object.assign(this, createActivitiesService(this.pb));
Object.assign(this, createBadgesService(this.pb));
Object.assign(this, createGroupsService(this.pb));
Object.assign(this, createPredictionsService(this.pb));
this.authPromise = this.authenticate();
this.authPromise.then(() => {
@@ -126,7 +128,8 @@ interface AdminClient
ReturnType<typeof createReactionsService>,
ReturnType<typeof createActivitiesService>,
ReturnType<typeof createBadgesService>,
ReturnType<typeof createGroupsService> {
ReturnType<typeof createGroupsService>,
ReturnType<typeof createPredictionsService> {
authPromise: Promise<void>;
}
@@ -0,0 +1,68 @@
import PocketBase from "pocketbase";
import { PicksMap, Prediction } from "@/features/predictions/types";
import { transformPrediction } from "../util/transform-types";
export function createPredictionsService(pb: PocketBase) {
return {
async getPrediction(
tournamentId: string,
playerId: string
): Promise<Prediction | null> {
try {
const record = await pb
.collection("predictions")
.getFirstListItem(
`tournament="${tournamentId}" && player="${playerId}"`,
{ expand: "player" }
);
return transformPrediction(record);
} catch (error) {
return null;
}
},
async getPredictionsForTournament(
tournamentId: string
): Promise<Prediction[]> {
const records = await pb.collection("predictions").getFullList({
filter: `tournament="${tournamentId}"`,
expand: "player",
sort: "updated",
});
return records.map(transformPrediction);
},
async upsertPrediction(
tournamentId: string,
playerId: string,
picks: PicksMap
): Promise<Prediction> {
const existing = await this.getPrediction(tournamentId, playerId);
const record = existing
? await pb
.collection("predictions")
.update(existing.id, { picks }, { expand: "player" })
: await pb.collection("predictions").create(
{
tournament: tournamentId,
player: playerId,
picks,
},
{ expand: "player" }
);
return transformPrediction(record);
},
async deletePredictionsForTournament(tournamentId: string): Promise<void> {
const records = await pb.collection("predictions").getFullList({
filter: `tournament="${tournamentId}"`,
fields: "id",
});
for (const record of records) {
await pb.collection("predictions").delete(record.id);
}
},
};
}
@@ -3,6 +3,7 @@ import { Player, PlayerInfo } from "@/features/players/types";
import { Team, TeamInfo } from "@/features/teams/types";
import { Tournament, TournamentInfo } from "@/features/tournaments/types";
import { Badge, BadgeInfo, BadgeProgress, EarnedBadge } from "@/features/badges/types";
import { Prediction } from "@/features/predictions/types";
import { Activity } from "../services/activities";
// pocketbase does this weird thing with relations where it puts them under a seperate "expand" field
@@ -295,6 +296,17 @@ export function transformReaction(record: any) {
};
}
export function transformPrediction(record: any): Prediction {
return {
id: record.id,
tournament: record.tournament,
player: transformPlayerInfo(record.expand?.player ?? { id: record.player }),
picks: record.picks || {},
created: record.created,
updated: record.updated,
};
}
export function transformBadgeInfo(record: any): BadgeInfo {
return {
id: record.id,