From 87cc55dd6aad2f10c165515953cae8febd3ff5ce Mon Sep 17 00:00:00 2001 From: RickyRAV <101335214+RickyRAV@users.noreply.github.com> Date: Thu, 9 Jan 2025 01:15:30 +0100 Subject: [PATCH] IDA-503: migrate max players update to server action - Add server action for updating room capacity - Create Zod schema for input validation - Migrate lobby component from direct DB queries - Add error handling with toast notifications --- .../src/app/actions/rooms/update-capacity.ts | 21 +++++++ .../schemas/update-max-players-schema.ts | 7 +++ .../src/components/multiplayer-page/lobby.tsx | 59 +++++++++---------- package-lock.json | 15 +++++ 4 files changed, 71 insertions(+), 31 deletions(-) create mode 100644 apps/dashboard/src/app/actions/rooms/update-capacity.ts create mode 100644 apps/dashboard/src/app/actions/schemas/update-max-players-schema.ts diff --git a/apps/dashboard/src/app/actions/rooms/update-capacity.ts b/apps/dashboard/src/app/actions/rooms/update-capacity.ts new file mode 100644 index 0000000..80ba777 --- /dev/null +++ b/apps/dashboard/src/app/actions/rooms/update-capacity.ts @@ -0,0 +1,21 @@ +"use server"; + +import { actionClient } from "../safe-action"; +import { updateMaxPlayersSchema } from "../schemas/update-max-players-schema"; +import { db } from "@/db"; +import { rooms } from "@drizzle/schema"; +import { eq } from "drizzle-orm"; + +export const updateRoomMaxPlayers = actionClient + .schema(updateMaxPlayersSchema) + .action(async ({ parsedInput: { maxPlayers, roomCode } }) => { + const updated = await db + .update(rooms) + .set({ maxPlayers }) + .where(eq(rooms.code, roomCode)) + .returning({ maxPlayers: rooms.maxPlayers }); + + if (!updated[0]) throw new Error("Failed to update room capacity"); + + return { maxPlayers: updated[0].maxPlayers }; + }); diff --git a/apps/dashboard/src/app/actions/schemas/update-max-players-schema.ts b/apps/dashboard/src/app/actions/schemas/update-max-players-schema.ts new file mode 100644 index 0000000..3023d18 --- /dev/null +++ b/apps/dashboard/src/app/actions/schemas/update-max-players-schema.ts @@ -0,0 +1,7 @@ +import { z } from "zod"; +import {roomSchema} from "@/app/api/v1/schemas" + +export const updateMaxPlayersSchema = z.object({ + maxPlayers: z.number().min(2).max(10), + roomCode: roomSchema.shape.roomCode, +}); diff --git a/apps/dashboard/src/components/multiplayer-page/lobby.tsx b/apps/dashboard/src/components/multiplayer-page/lobby.tsx index 831364a..9e9f14e 100644 --- a/apps/dashboard/src/components/multiplayer-page/lobby.tsx +++ b/apps/dashboard/src/components/multiplayer-page/lobby.tsx @@ -23,6 +23,10 @@ import { Player, useMultiplayer } from '@/contexts/multiplayer-context'; import { ScrollArea } from '@/components/ui/scroll-area'; import { User } from '@/contexts/user-context'; import { RealtimeChannel } from '@supabase/supabase-js'; +import { useAction } from 'next-safe-action/hooks'; +import { updateRoomMaxPlayers } from '@/app/actions/rooms/update-capacity'; +import { useToast } from '@/components/ui/use-toast'; + interface PresenceData { currentUser: { id: string; @@ -55,6 +59,7 @@ export default function Lobby() { const router = useRouter(); const roomCode = routerParams['roomCode'] as string; const supabase = createClient(); + const {toast} = useToast(); const checkAndJoinRoom = async (channel: RealtimeChannel) => { try { @@ -224,40 +229,32 @@ export default function Lobby() { } }, [players]); - const changeAmountOfPlayers = async (newAmount: number) => { - if (!channel) { - console.error('Channel is not initialized.'); - return; - } +const updatePlayersAction = useAction(updateRoomMaxPlayers, { + onError: () => { + toast({ + duration: 3500, + variant: 'destructive', + title: 'Something went wrong.', + }); + }, +}); - if (Number.isNaN(newAmount) || newAmount < 2) { - return; - } + const changeAmountOfPlayers = async (newAmount: number) => { + if (!channel || !isCreator) return; try { - if (isCreator) { - // Update database - - const { data, error } = await supabase - .from('rooms') - .update({ max_players: newAmount }) - .eq('code', roomCode) - .select() - .single(); + const result = await updatePlayersAction.execute({ + roomCode, + maxPlayers: newAmount + }); - console.log(data); - if (error) throw error; - - // Update local state and broadcast to others - if (data) { - setMaxPlayers(newAmount); - await channel.send({ - type: 'broadcast', - event: 'change-amount-of-players', - payload: { newAmount }, - }); - } - } + // Update local state and broadcast to others + setMaxPlayers(newAmount); + await channel.send({ + type: 'broadcast', + event: 'change-amount-of-players', + payload: { newAmount }, + }); } catch (error) { console.error('Failed to update max players:', error); } @@ -489,4 +486,4 @@ export default function Lobby() { ); -} +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 7490ce8..1aa7e52 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12115,6 +12115,21 @@ "@types/react-dom": "^18.2.19", "typescript": "^5.3.3" } + }, + "node_modules/react-email/node_modules/@next/swc-darwin-arm64": { + "version": "14.2.11", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.2.11.tgz", + "integrity": "sha512-eiY9u7wEJZWp/Pga07Qy3ZmNEfALmmSS1HtsJF3y1QEyaExu7boENz11fWqDmZ3uvcyAxCMhTrA1jfVxITQW8g==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } } } }