From e6c6ed097bb1e03f1976350cff5f7b45a45d95d1 Mon Sep 17 00:00:00 2001 From: Kalle <38327916+Sendouc@users.noreply.github.com> Date: Sun, 8 Mar 2026 21:54:19 +0200 Subject: [PATCH] Add some max count checks --- app/features/friends/FriendRepository.server.ts | 12 ++++++++++++ app/features/friends/actions/friends.server.ts | 10 ++++++++++ app/features/friends/friends-constants.ts | 3 +++ .../tournament/SavedTournamentRepository.server.ts | 10 ++++++++++ .../tournament/actions/to.$id.register.server.ts | 7 +++++++ app/features/tournament/tournament-constants.ts | 1 + 6 files changed, 43 insertions(+) create mode 100644 app/features/friends/friends-constants.ts diff --git a/app/features/friends/FriendRepository.server.ts b/app/features/friends/FriendRepository.server.ts index 17f812958..093722dde 100644 --- a/app/features/friends/FriendRepository.server.ts +++ b/app/features/friends/FriendRepository.server.ts @@ -321,6 +321,18 @@ export async function findMutualFriends({ .execute(); } +export async function countPendingSentRequests( + senderId: number, +): Promise { + const result = await db + .selectFrom("FriendRequest") + .select((eb) => eb.fn.countAll().as("count")) + .where("FriendRequest.senderId", "=", senderId) + .executeTakeFirstOrThrow(); + + return result.count; +} + export async function findFriendship({ userOneId, userTwoId, diff --git a/app/features/friends/actions/friends.server.ts b/app/features/friends/actions/friends.server.ts index 084989a59..8bb023784 100644 --- a/app/features/friends/actions/friends.server.ts +++ b/app/features/friends/actions/friends.server.ts @@ -2,7 +2,9 @@ import type { ActionFunction } from "react-router"; import { requireUser } from "~/features/auth/core/user.server"; import { notify } from "~/features/notifications/core/notify.server"; import { parseFormData } from "~/form/parse.server"; +import { errorToastIfFalsy } from "~/utils/remix.server"; import * as FriendRepository from "../FriendRepository.server"; +import { FRIEND } from "../friends-constants"; import { friendsActionSchema } from "../friends-schemas.server"; export const action: ActionFunction = async ({ request }) => { @@ -19,6 +21,14 @@ export const action: ActionFunction = async ({ request }) => { switch (result.data._action) { case "SEND_REQUEST": { + const pendingCount = await FriendRepository.countPendingSentRequests( + user.id, + ); + errorToastIfFalsy( + pendingCount < FRIEND.MAX_PENDING_REQUESTS, + "Maximum pending friend requests reached", + ); + await FriendRepository.insertFriendRequest({ senderId: user.id, receiverId: result.data.userId, diff --git a/app/features/friends/friends-constants.ts b/app/features/friends/friends-constants.ts new file mode 100644 index 000000000..10ec3530d --- /dev/null +++ b/app/features/friends/friends-constants.ts @@ -0,0 +1,3 @@ +export const FRIEND = { + MAX_PENDING_REQUESTS: 20, +} as const; diff --git a/app/features/tournament/SavedTournamentRepository.server.ts b/app/features/tournament/SavedTournamentRepository.server.ts index 3bbea0fb1..e94e746a9 100644 --- a/app/features/tournament/SavedTournamentRepository.server.ts +++ b/app/features/tournament/SavedTournamentRepository.server.ts @@ -47,6 +47,16 @@ export async function isSaved({ return Boolean(row); } +export async function countByUserId(userId: number): Promise { + const result = await db + .selectFrom("SavedTournament") + .select((eb) => eb.fn.countAll().as("count")) + .where("userId", "=", userId) + .executeTakeFirstOrThrow(); + + return result.count; +} + export async function findTournamentIdsByUserId( userId: number, ): Promise { diff --git a/app/features/tournament/actions/to.$id.register.server.ts b/app/features/tournament/actions/to.$id.register.server.ts index 1f06cb15c..8a0ed14ef 100644 --- a/app/features/tournament/actions/to.$id.register.server.ts +++ b/app/features/tournament/actions/to.$id.register.server.ts @@ -28,6 +28,7 @@ import deleteTeamMember from "../queries/deleteTeamMember.server"; import { findOwnTournamentTeam } from "../queries/findOwnTournamentTeam.server"; import { joinTeam } from "../queries/joinLeaveTeam.server"; import { upsertCounterpickMaps } from "../queries/upsertCounterpickMaps.server"; +import { TOURNAMENT } from "../tournament-constants"; import { registerSchema } from "../tournament-schemas.server"; import { isOneModeTournamentOf, @@ -352,6 +353,12 @@ export const action: ActionFunction = async ({ request, params }) => { break; } case "SAVE_TOURNAMENT": { + const count = await SavedTournamentRepository.countByUserId(user.id); + errorToastIfFalsy( + count < TOURNAMENT.MAX_SAVED_COUNT, + "Maximum saved tournaments reached", + ); + await SavedTournamentRepository.save({ userId: user.id, tournamentId }); break; } diff --git a/app/features/tournament/tournament-constants.ts b/app/features/tournament/tournament-constants.ts index ee8a92cb7..afe7feef7 100644 --- a/app/features/tournament/tournament-constants.ts +++ b/app/features/tournament/tournament-constants.ts @@ -16,6 +16,7 @@ export const TOURNAMENT = { SWISS_DEFAULT_GROUP_COUNT: 1, SWISS_DEFAULT_ROUND_COUNT: 5, SE_DEFAULT_HAS_THIRD_PLACE_MATCH: true, + MAX_SAVED_COUNT: 20, ROUND_NAMES: { WB_FINALS: "WB Finals", GRAND_FINALS: "Grand Finals",