feature added: checkmate detection and ending game on checkmate
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import { Button, Group, Stack, Text, Title } from '@mantine/core';
|
||||
import React, { useEffect, useState } from 'react'
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import { getUserData } from '../../utils/auth'
|
||||
import { getAuthToken, getUserData } from '../../utils/auth'
|
||||
|
||||
const Challenges = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -15,7 +15,11 @@ const Challenges = () => {
|
||||
const fetchData = async () => {
|
||||
let url = `${import.meta.env.VITE_BACKEND_HOST}/api/user/${username}/challenges`;
|
||||
try {
|
||||
response = await fetch(url, { signal: abortController.signal })
|
||||
response = await fetch(url, {
|
||||
signal: abortController.signal, headers: {
|
||||
'Authorization': `Bearer ${getAuthToken()}`
|
||||
}
|
||||
})
|
||||
const data = await response.json();
|
||||
if (data.success) {
|
||||
setChallenges(data.challenges);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
export const SOCKET_EVENTS = {
|
||||
CONNECT:'connect',
|
||||
DISCONNECT:'disconnect',
|
||||
CONNECTION: "connection",
|
||||
JOIN_ROOM: "join-room",
|
||||
JOIN_ROOM_SUCCESS: "join-room-success",
|
||||
|
||||
@@ -22,8 +22,12 @@ const reducer = (state, action) => {
|
||||
let updatedGameHistory = state.gameHistory;
|
||||
let { san, after } = newChessObj.move(action.val);
|
||||
updatedGameHistory.push({ move: san, fen: after });
|
||||
if (newChessObj.isCheckmate()) {
|
||||
return { ...state, chess: newChessObj, chessBoard: newChessObj.getBoard(localStorage.getItem('myColor')), moveHints: [], selected: null, gameHistory: updatedGameHistory, currentIndex: updatedGameHistory.length - 1, hasGameEnded: true, gameEndedReason: 'CHECKMATE' };
|
||||
} else {
|
||||
return { ...state, chess: newChessObj, chessBoard: newChessObj.getBoard(localStorage.getItem('myColor')), moveHints: [], selected: null, gameHistory: updatedGameHistory, currentIndex: updatedGameHistory.length - 1 };
|
||||
}
|
||||
}
|
||||
case CAPTURE_PIECE:
|
||||
{
|
||||
console.log('Capture', action.val, state.chess.turn());
|
||||
@@ -31,8 +35,12 @@ const reducer = (state, action) => {
|
||||
let updatedGameHistory = state.gameHistory;
|
||||
let { san, after } = newChessObj.move(action.val);
|
||||
updatedGameHistory.push({ move: san, fen: after });
|
||||
if (newChessObj.isCheckmate()) {
|
||||
return { ...state, chess: newChessObj, chessBoard: newChessObj.getBoard(localStorage.getItem('myColor')), moveHints: [], selected: null, gameHistory: updatedGameHistory, currentIndex: updatedGameHistory.length - 1, hasGameEnded: true, gameEndedReason: 'CHECKMATE' };
|
||||
} else {
|
||||
return { ...state, chess: newChessObj, chessBoard: newChessObj.getBoard(localStorage.getItem('myColor')), moveHints: [], selected: null, gameHistory: updatedGameHistory, currentIndex: updatedGameHistory.length - 1 };
|
||||
}
|
||||
}
|
||||
case JUMP_TO:
|
||||
{
|
||||
let index = action.val;
|
||||
@@ -61,8 +69,10 @@ function chessGameStateInit(myColor) {
|
||||
let gameHistory = [];
|
||||
let selected = null;
|
||||
let currentIndex = -1;
|
||||
let hasGameEnded = false;
|
||||
let gameEndedReason = "";
|
||||
|
||||
return { chess, chessBoard, moveHints, selected, gameHistory, currentIndex };
|
||||
return { chess, chessBoard, moveHints, selected, gameHistory, currentIndex, hasGameEnded, gameEndedReason };
|
||||
}
|
||||
|
||||
// the ChessGameContextProvider seperates the game logic from the ChessBoard component and exposes
|
||||
@@ -70,7 +80,7 @@ function chessGameStateInit(myColor) {
|
||||
const ChessGameContextProvider = ({ children }) => {
|
||||
let myColor = localStorage.getItem('myColor');
|
||||
console.log('INSIDE CONTEXT PROVIDER');
|
||||
const [{ chess, chessBoard, moveHints, selected, gameHistory, currentIndex }, dispatch] = useReducer(reducer, myColor, chessGameStateInit);
|
||||
const [{ chess, chessBoard, moveHints, selected, gameHistory, currentIndex, hasGameEnded, gameEndedReason }, dispatch] = useReducer(reducer, myColor, chessGameStateInit);
|
||||
const [isTimerOn, setIsTimerOn] = useState(true);
|
||||
console.log(gameHistory);
|
||||
|
||||
@@ -192,7 +202,9 @@ const ChessGameContextProvider = ({ children }) => {
|
||||
|
||||
return (
|
||||
<ChessGameContext.Provider value={{
|
||||
myColor, chessBoard, moveHints, selected, handleOpponentMove, handleSquareClick, getSquareColor, isSquareMarked, selectPiece, handleDrop, gameHistory, jumpTo, getChessBoard, currentIndex, goAhead, goBack, setGameHistory, isTimerOn
|
||||
myColor, chessBoard, moveHints, selected, handleOpponentMove, handleSquareClick, getSquareColor, isSquareMarked,
|
||||
selectPiece, handleDrop, gameHistory, jumpTo, getChessBoard, currentIndex, goAhead, goBack, setGameHistory,
|
||||
isTimerOn, hasGameEnded, gameEndedReason
|
||||
}}>
|
||||
{children}
|
||||
<audio src='/src/assets/move-self.mp3' ref={moveAudioRef} />
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import React from 'react'
|
||||
|
||||
const useQuery = () => {
|
||||
|
||||
}
|
||||
|
||||
export default useQuery
|
||||
@@ -34,10 +34,16 @@ const useStyles = createStyles((theme) => ({
|
||||
|
||||
const ChessBoard = () => {
|
||||
const { classes } = useStyles();
|
||||
const { getChessBoard, handleOpponentMove, handleDrop } = useContext(ChessGameContext)
|
||||
const { getChessBoard, handleOpponentMove, handleDrop,hasGameEnded,gameEndedReason } = useContext(ChessGameContext)
|
||||
let roomID = localStorage.getItem('roomID');
|
||||
const chessBoard = getChessBoard();
|
||||
|
||||
if(hasGameEnded) {
|
||||
console.log('Game ended due to',gameEndedReason)
|
||||
} else {
|
||||
console.log('Game not ended yet')
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
socket.on(CHESS_OPPONENT_MOVE, handleOpponentMove)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Avatar, Button, Flex, Group, Image, Loader, MediaQuery, NavLink, Text, Title } from '@mantine/core'
|
||||
import { Avatar, Button, Flex, Group, Image, Loader, MediaQuery, Modal, NavLink, Text, Title } from '@mantine/core'
|
||||
import React, { useContext, useEffect, useState } from 'react'
|
||||
import ChessBoard from '../Chess/ChessBoard'
|
||||
import { useNavigate, useParams } from 'react-router-dom'
|
||||
@@ -7,9 +7,14 @@ import { getUserData } from '../../../utils/auth'
|
||||
import { ChessGameContext } from '../../context/chess-game-context'
|
||||
import GameHistory from '../../components/GameHistory'
|
||||
import Timer from './Timer'
|
||||
import { useDisclosure } from '@mantine/hooks'
|
||||
import { SOCKET_EVENTS } from '../../constants'
|
||||
const { CONNECT, DISCONNECT, CHESS_MOVE, CHESS_OPPONENT_MOVE, CONNECTION, JOIN_ROOM, JOIN_ROOM_ERROR, JOIN_ROOM_SUCCESS, ROOM_FULL, USER_JOINED_ROOM } = SOCKET_EVENTS;
|
||||
|
||||
const ChessGame = () => {
|
||||
const { gameHistory, setGameHistory, isTimerOn,setIsTimerOn } = useContext(ChessGameContext);
|
||||
const { setGameHistory, isTimerOn, setIsTimerOn, hasGameEnded, gameEndedReason } = useContext(ChessGameContext);
|
||||
const [gameEndedModalOpen, modalFunctions] = useDisclosure(true);
|
||||
|
||||
const user = getUserData();
|
||||
let username = user.username;
|
||||
let color = localStorage.getItem('myColor')
|
||||
@@ -31,37 +36,40 @@ const ChessGame = () => {
|
||||
|
||||
useEffect(() => {
|
||||
socket.connect();
|
||||
|
||||
socket.on('connect', () => {
|
||||
socket.on(CONNECT, () => {
|
||||
console.log('Connected');
|
||||
});
|
||||
|
||||
socket.on('join-room-success', (fetchedGameHistory) => {
|
||||
socket.on(JOIN_ROOM_SUCCESS, (fetchedGameHistory) => {
|
||||
console.log('Room joined:', roomID);
|
||||
setGameHistory(fetchedGameHistory);
|
||||
setHasJoinedRoom(true);
|
||||
});
|
||||
|
||||
socket.on('room-full', () => {
|
||||
socket.on(ROOM_FULL, () => {
|
||||
console.log('Room is full');
|
||||
})
|
||||
|
||||
socket.on("join-room-error", (err) => {
|
||||
socket.on(JOIN_ROOM_ERROR, (err) => {
|
||||
console.error("Error:", err);
|
||||
})
|
||||
|
||||
console.log('JOINING ROOM')
|
||||
socket.emit("join-room", roomID, { username, color })
|
||||
socket.emit(JOIN_ROOM, roomID, { username, color })
|
||||
|
||||
socket.on('disconnect', (reason) => {
|
||||
socket.on(DISCONNECT, (reason) => {
|
||||
console.log('Socket disconnected due to', reason);
|
||||
})
|
||||
});
|
||||
|
||||
socket.on('opponent-move', (data) => {
|
||||
socket.on(CHESS_OPPONENT_MOVE, (data) => {
|
||||
console.log(data);
|
||||
// setIsTimerOn(true);
|
||||
})
|
||||
|
||||
socket.on(USER_JOINED_ROOM, () => {
|
||||
setIsWaiting(false);
|
||||
});
|
||||
|
||||
}, []);
|
||||
|
||||
if (!hasJoinedRoom) return (
|
||||
@@ -69,19 +77,38 @@ const ChessGame = () => {
|
||||
)
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal onClose={modalFunctions.close} opened={hasGameEnded && gameEndedModalOpen} centered>
|
||||
<Text>Game ended due to {gameEndedReason}</Text>
|
||||
<Button color='lime' onClick={exitGame}>Go back</Button>
|
||||
<Button mx='md' color='lime' onClick={modalFunctions.close}>OK</Button>
|
||||
</Modal>
|
||||
<Flex gap="xl" miw={360} justify='center' align='center' wrap='nowrap' mt={{ base: '50px', sm: '0px' }} direction={{ base: 'column', lg: 'row' }}>
|
||||
<Flex gap="xs" justify='center' align='start' wrap='nowrap' direction='column' >
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<NavLink
|
||||
style={{ width: "500px" }}
|
||||
p="2px"
|
||||
label={opponent}
|
||||
label={isWaiting ? "Waiting for opponent..." : opponent}
|
||||
icon={<Avatar radius="3px" children={opponent[0].toUpperCase()} />}
|
||||
description={"description"}
|
||||
/>
|
||||
{/* <Timer on={!isTimerOn} /> */}
|
||||
</div>
|
||||
{
|
||||
// TODO: handle isWaiting state
|
||||
false ?
|
||||
<>
|
||||
<MediaQuery smallerThan="sm" styles={{ display: 'none' }}>
|
||||
<Image width={600} miw={480} src="/src/assets/chess_board.png" />
|
||||
</MediaQuery>
|
||||
<MediaQuery largerThan="sm" styles={{ display: 'none' }}>
|
||||
<Image width="100%" maw={540} src="/src/assets/chess_board.png" />
|
||||
</MediaQuery>
|
||||
</>
|
||||
:
|
||||
<ChessBoard />
|
||||
}
|
||||
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
|
||||
<NavLink
|
||||
style={{ width: "500px" }}
|
||||
@@ -110,6 +137,7 @@ const ChessGame = () => {
|
||||
</Flex>
|
||||
</MediaQuery>
|
||||
</Flex>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user