/** * This file is part of the SplendidBear Websites' projects. * * Copyright (c) 2026 @ www.splendidbear.org * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ import { useQuery, useMutation } from '@tanstack/react-query'; /** * Game Data Provider Hook * Centralized API communication layer for game-related queries and mutations */ const useGameDataProvider = gameAssoc => { // Queries const connectQuery = useQuery({ queryKey: ['game-connect', gameAssoc], queryFn: () => fetch(`/api/game/connect/${gameAssoc}`) .then(r => r.text()) .then(b64 => JSON.parse(window.atob(b64))), enabled: false, retry: false, }); // Mutations const startMutation = useMutation({ mutationFn: () => fetch('/api/game/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ gameAssoc }), }).then(r => r.json()), }); const joinMutation = useMutation({ mutationFn: () => fetch(`/api/game/join/${gameAssoc}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, }), }); const stepMutation = useMutation({ mutationFn: dataPack => fetch(`/api/game/step/${gameAssoc}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(dataPack), }).then(r => r.json()), }); const heartbeatMutation = useMutation({ mutationFn: color => fetch(`/api/game/heartbeat/${gameAssoc}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ color }), }).then(r => r.json()), }); const challengeRespondMutation = useMutation({ mutationFn: ({ challengerGameAssoc, accepted, targetGameAssoc }) => fetch('/api/game/challenge/respond/' + challengerGameAssoc, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ accepted, targetGameAssoc }), }).then(r => r.json()), }); const leaveMutation = useMutation({ mutationFn: () => fetch(`/api/game/leave/${gameAssoc}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, }).then(r => r.json()), }); return { // Queries connectQuery, // Mutations startMutation, joinMutation, stepMutation, heartbeatMutation, challengeRespondMutation, leaveMutation, }; }; /** * Lobby Data Provider Hook * Centralized API communication layer for lobby-related queries and mutations */ export const useLobbyDataProvider = () => { const waitingPlayersQuery = useQuery({ queryKey: ['game-waiting'], queryFn: () => fetch('/api/game/waiting') .then(r => r.json()), }); const challengeMutation = useMutation({ mutationFn: ({ targetGameAssoc, challengerGameAssoc }) => fetch(`/api/game/challenge/${targetGameAssoc}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ challengerGameAssoc }), }).then(r => r.json()), }); return { // Queries waitingPlayersQuery, // Mutations challengeMutation, }; }; export default useGameDataProvider; /** * Profile Data Provider Hook * Centralized API communication layer for profile-related mutations */ export const useProfileDataProvider = () => { const uploadAvatarMutation = useMutation({ mutationFn: ({ uploadUrl, file }) => { const fd = new FormData(); fd.append('avatar', file); return fetch(uploadUrl, { method: 'POST', body: fd }) .then(r => r.json()) .then(data => { if (data.error) throw new Error(data.error); return data; }); }, }); return { uploadAvatarMutation }; };