diff --git a/inertia/features/matchmaking/use_matchmaking.ts b/inertia/features/matchmaking/use_matchmaking.ts new file mode 100644 index 0000000..6822d39 --- /dev/null +++ b/inertia/features/matchmaking/use_matchmaking.ts @@ -0,0 +1,65 @@ +import { useEffect, useState } from 'react' +import { useTransmit } from '~/hooks/use_transmit' +import { useTranslation } from 'react-i18next' +import { Api } from '~/services/api' +import { router } from '@inertiajs/react' +import type { SearchProps } from '~/pages/search' + +export const useMatchmaking = (props: SearchProps) => { + const { user, existingSession } = props + const [queueCount, setQueueCount] = useState(0) + const { subscription: userListener } = useTransmit({ url: `game/user/${user.id}` }) + const { subscription: queueListener } = useTransmit({ url: 'game/search' }) + + const { t } = useTranslation() + + const registerToQueue = async () => { + const response: { message: string; queueCount: number } = await new Api().post('/game/search') + setQueueCount(response.queueCount) + } + + useEffect(() => { + if (existingSession) { + router.visit(`/game/session/${existingSession}`) + return + } + registerToQueue() + }, []) + + userListener?.create() + queueListener?.create() + + userListener?.onMessage(async (message: { status: string; sessionId: string }) => { + if (message.status === 'accept') { + await new Api().get(`/game/session/${message.sessionId}/accept`) + return + } + + if (message.status === 'removed') { + await queueListener?.delete() + await userListener?.delete() + return router.visit('/game') + } + + if (message.status === 'start') { + return router.visit(`/game/session/${message.sessionId}`) + } + }) + + queueListener?.onMessage((message: { queueCount: number }) => { + setQueueCount(message.queueCount) + }) + + const cancelQueue = async () => { + await new Api().delete('/game/search') + await queueListener?.delete() + await userListener?.delete() + return router.visit('/game') + } + + return { + cancelQueue, + queueCount, + t, + } +} diff --git a/inertia/pages/search.tsx b/inertia/pages/search.tsx index 3f97552..2ae3a1d 100644 --- a/inertia/pages/search.tsx +++ b/inertia/pages/search.tsx @@ -1,68 +1,15 @@ -import { useTransmit } from '~/hooks/use_transmit' import User from '#models/user' -import { useEffect, useState } from 'react' -import { Api } from '~/services/api' -import { router } from '@inertiajs/react' import type { GameSessionId } from '#features/game_session/types/game_session' import { Button } from '~/features/utils/components/button' -import { useTranslation } from 'react-i18next' +import { useMatchmaking } from '~/features/matchmaking/use_matchmaking' -type Props = { +export type SearchProps = { user: User existingSession: GameSessionId } -export default function Search(props: Props) { - const { user, existingSession } = props - const [queueCount, setQueueCount] = useState(0) - const { subscription: userListener } = useTransmit({ url: `game/user/${user.id}` }) - const { subscription: queueListener } = useTransmit({ url: 'game/search' }) - - const { t } = useTranslation() - - const registerToQueue = async () => { - const response: { message: string; queueCount: number } = await new Api().post('/game/search') - setQueueCount(response.queueCount) - } - - useEffect(() => { - if (existingSession) { - router.visit(`/game/session/${existingSession}`) - return - } - registerToQueue() - }, []) - - userListener?.create() - queueListener?.create() - - userListener?.onMessage(async (message: { status: string; sessionId: string }) => { - if (message.status === 'accept') { - await new Api().get(`/game/session/${message.sessionId}/accept`) - return - } - - if (message.status === 'removed') { - await queueListener?.delete() - await userListener?.delete() - return router.visit('/game') - } - - if (message.status === 'start') { - return router.visit(`/game/session/${message.sessionId}`) - } - }) - - queueListener?.onMessage((message: { queueCount: number }) => { - setQueueCount(message.queueCount) - }) - - const cancelQueue = async () => { - await new Api().delete('/game/search') - await queueListener?.delete() - await userListener?.delete() - return router.visit('/game') - } +export default function Search(props: SearchProps) { + const { queueCount, cancelQueue, t } = useMatchmaking(props) return (