bug fixes
This commit is contained in:
+2
-2
@@ -44,8 +44,8 @@ app.use((error, req, res, next) => {
|
|||||||
const status = error.status || 500;
|
const status = error.status || 500;
|
||||||
console.log(error);
|
console.log(error);
|
||||||
res.status(status).json({
|
res.status(status).json({
|
||||||
userMessage: "Something went wrong",
|
message: "Something went wrong",
|
||||||
devMessage: error?.message || "Internal server error",
|
description: error?.message || "Internal server error",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ router.post("/signup", async (req, res, next) => {
|
|||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof ZodError) {
|
if (err instanceof ZodError) {
|
||||||
return res.status(400).json({ userMessage: "Invalid data submitted", devMessage: "Invalid schema" });
|
return res.status(400).json({ message: "Invalid data submitted", description: "Invalid schema" });
|
||||||
}
|
}
|
||||||
next(err);
|
next(err);
|
||||||
}
|
}
|
||||||
@@ -84,16 +84,16 @@ router.post("/login", async (req, res, next) => {
|
|||||||
user = await User.findOne({ username });
|
user = await User.findOne({ username });
|
||||||
if (!user)
|
if (!user)
|
||||||
return res.status(404).json({
|
return res.status(404).json({
|
||||||
userMessage: "User does not exist",
|
message: "User does not exist",
|
||||||
devMessage: "'username' not found in db",
|
description: "'username' not found in db",
|
||||||
});
|
});
|
||||||
|
|
||||||
const pwIsValid = await isValidPassword(password, user.password_hash);
|
const pwIsValid = await isValidPassword(password, user.password_hash);
|
||||||
if (!pwIsValid) {
|
if (!pwIsValid) {
|
||||||
return res.status(401).json({
|
return res.status(401).json({
|
||||||
success: false,
|
success: false,
|
||||||
userMessage: "Invalid credentials",
|
message: "Invalid credentials",
|
||||||
devMessage: "Invalid credentials",
|
description: "Invalid credentials",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ router.post("/login", async (req, res, next) => {
|
|||||||
.json({ token, user: { id: user.id, username: user.username, email: user.email }, success: true });
|
.json({ token, user: { id: user.id, username: user.username, email: user.email }, success: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error instanceof ZodError) {
|
if (error instanceof ZodError) {
|
||||||
return res.status(401).json({ userMessage: "Invalid Credentials", devMessage: "Invalid schema" });
|
return res.status(401).json({ message: "Invalid Credentials", description: "Invalid schema" });
|
||||||
}
|
}
|
||||||
next(error);
|
next(error);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,20 +4,22 @@ const { createRoom } = require("../socket");
|
|||||||
const { checkAuth } = require("../util/auth");
|
const { checkAuth } = require("../util/auth");
|
||||||
const { Challenge } = require("../models/challenge");
|
const { Challenge } = require("../models/challenge");
|
||||||
|
|
||||||
async function fetchChallenge({ challenger, challenged }) {}
|
// async function fetchChallenge({ challenger, challenged }) {}
|
||||||
|
|
||||||
// rooms can only be created through HTTP requests and destroyed only by socket.io server
|
// rooms can only be created through HTTP requests and destroyed only by socket.io server
|
||||||
// and vice versa is not true
|
// and vice versa is not true
|
||||||
router.post("/create", checkAuth, async (req, res, next) => {
|
router.post("/", checkAuth, async (req, res, next) => {
|
||||||
console.log(req.body);
|
console.log(req.body);
|
||||||
// challenger and challenged are username, color is the color played by challenger, timeLimit is the timeLimit for one player
|
// challenger and challenged are username, color is the color played by challenger, timeLimit is the timeLimit for one player
|
||||||
const { challenger, challenged, color, timeLimit } = req.body;
|
const { challenger, challenged, color, timeLimit } = req.body;
|
||||||
|
|
||||||
let challenge = await Challenge.findOne({ challenger });
|
let challenge = await Challenge.findOne({ challenger });
|
||||||
|
|
||||||
// a user can create only one challenge at a time
|
// a user can create only one challenge at a time
|
||||||
if (challenge) {
|
if (challenge) {
|
||||||
return res.status(405).json({ success: false, error: { message: "Cannot create new challenge" } });
|
return res.status(405).json({
|
||||||
|
message: "Cannot create new challenge",
|
||||||
|
description: "User already created a challenge",
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// get email of the challenged person
|
// get email of the challenged person
|
||||||
@@ -45,7 +47,8 @@ router.post("/create", checkAuth, async (req, res, next) => {
|
|||||||
// `Challenge from ${challenger}`,
|
// `Challenge from ${challenger}`,
|
||||||
// `To accept the challenge follow the link: http://192.168.136.99:5173/game/challenges/${challenged}/${roomID} \n login through: http://192.168.136.99:5173/login \n roomid:${roomID}`
|
// `To accept the challenge follow the link: http://192.168.136.99:5173/game/challenges/${challenged}/${roomID} \n login through: http://192.168.136.99:5173/login \n roomid:${roomID}`
|
||||||
// );
|
// );
|
||||||
res.json({ roomID });
|
console.log(roomID);
|
||||||
|
res.status(201).json({ roomID });
|
||||||
});
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
+186
-135
@@ -5,177 +5,228 @@ const { User } = require("../models/user");
|
|||||||
const { checkAuth } = require("../util/auth");
|
const { checkAuth } = require("../util/auth");
|
||||||
const { catchAsync } = require("../util/errors");
|
const { catchAsync } = require("../util/errors");
|
||||||
|
|
||||||
// TO BE TESTED
|
// get the logged in user details
|
||||||
// attaches user data to the route object
|
router.get("/", checkAuth, async (req, res, next) => {
|
||||||
router.use(
|
try {
|
||||||
catchAsync(async (req, res, next) => {
|
let { userId } = req;
|
||||||
let userID = req.url.split("/")[1];
|
const user = await User.findById(userId);
|
||||||
if (userID?.length !== 24)
|
let { id, username, email, fname, lname, country, location } = user;
|
||||||
return res.status(404).json({ userMessage: "User not found", devMessage: "Invalid user ID" });
|
let friends = await user.getFriends();
|
||||||
let userData = await User.findById(userID);
|
let games = await user.getGames();
|
||||||
if (userData) {
|
|
||||||
req.userData = userData;
|
|
||||||
next();
|
|
||||||
} else {
|
|
||||||
res.status(404).json({
|
|
||||||
success: false,
|
|
||||||
userMessage: "User not found",
|
|
||||||
devMessage: "User ID does not exists",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// TO BE TESTED
|
|
||||||
// get user details
|
|
||||||
router.get(
|
|
||||||
"/:userid",
|
|
||||||
catchAsync(async (req, res, next) => {
|
|
||||||
let userData = req.userData;
|
|
||||||
let { id, username, email, fname, lname, country, location } = userData;
|
|
||||||
let friends = await userData.getFriends();
|
|
||||||
let games = await userData.getGames();
|
|
||||||
return res.status(200).json({ id, username, email, friends, fname, lname, country, location, games });
|
return res.status(200).json({ id, username, email, friends, fname, lname, country, location, games });
|
||||||
})
|
} catch (err) {
|
||||||
);
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/friends", checkAuth, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
let { userId } = req;
|
||||||
|
let user = await User.findById(userId);
|
||||||
|
let friends = await user.getFriends();
|
||||||
|
return res.status(200).json(friends);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
router.get("/challenges", checkAuth, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
let { userId } = req;
|
||||||
|
let user = await User.findById(userId);
|
||||||
|
let challenges = await Challenge.find({ challenged: user.username });
|
||||||
|
challenges = challenges.map((challenge) => {
|
||||||
|
let { id, challenged, challenger, color, roomID, timeLimit } = challenge;
|
||||||
|
return { id, challenged, challenger, color, roomID, timeLimit };
|
||||||
|
});
|
||||||
|
console.log(challenges);
|
||||||
|
res.status(200).json(challenges);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// get history of games played
|
||||||
|
router.get("/games", checkAuth, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
let { userId } = req;
|
||||||
|
const user = await User.findById(userId);
|
||||||
|
let games = await user.getGames();
|
||||||
|
if (!games) games = [];
|
||||||
|
return res.status(200).json(gamesData);
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
router.get("/games/:gameid", checkAuth, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
router.get("");
|
||||||
|
|
||||||
// TO BE TESTED
|
// TO BE TESTED
|
||||||
// update user details
|
// update user details
|
||||||
router.patch(
|
router.patch("/", checkAuth, async (req, res, next) => {
|
||||||
"/:userid",
|
try {
|
||||||
checkAuth,
|
let { userId } = req;
|
||||||
catchAsync(async (req, res, next) => {
|
|
||||||
let { userid } = req.params;
|
|
||||||
let updatedData = req.body;
|
let updatedData = req.body;
|
||||||
console.log("Updated data: ", updatedData);
|
await User.findByIdAndUpdate(userId, { ...updatedData });
|
||||||
// console.log(updatedData)
|
let { id, username, email, fname, lname, location, country, fullName } = await User.findById(userId);
|
||||||
await User.findByIdAndUpdate(userid, { ...updatedData });
|
return res.status(200).json({ user: { id, username, email, fname, lname, location, country, fullName } });
|
||||||
let { id, username, email, fname, lname, location, country, fullName } = await User.findById(userid);
|
} catch (err) {
|
||||||
// console.log(req.userData);
|
next(err);
|
||||||
console.log({ id, username, email, fname, lname, location, country, fullName });
|
}
|
||||||
return res.json({ success: true, user: { id, username, email, fname, lname, location, country, fullName } });
|
});
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// TO BE TESTED
|
// TO BE TESTED
|
||||||
// delete the user
|
// delete the user
|
||||||
router.delete(
|
router.delete("/", checkAuth, async (req, res, next) => {
|
||||||
"/:userid",
|
try {
|
||||||
checkAuth,
|
let { userId } = req;
|
||||||
catchAsync(async (req, res, next) => {
|
let user = await User.findById(userId);
|
||||||
let { userData } = req;
|
await user.deleteOne();
|
||||||
await userData.deleteOne();
|
return res.status(204).json({ message: "Account deleted succesfully" });
|
||||||
})
|
} catch (err) {
|
||||||
);
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// get friends of the user
|
// TO BE TESTED
|
||||||
router.get(
|
// TODO: add some logic to notify the challenger if the challenged user declines the challenge
|
||||||
"/:userid/friends",
|
// accept or decline a challenge
|
||||||
checkAuth,
|
// challengeID here refers to the roomID associated with the challenge
|
||||||
catchAsync(async (req, res, next) => {
|
router.delete("/challenges/:challengeID", checkAuth, async (req, res, next) => {
|
||||||
const friends = await req.userData.getFriends();
|
try {
|
||||||
return res.json({ success: true, friends });
|
let { challengeID } = req.params;
|
||||||
})
|
let challenge = await Challenge.findById(challengeID);
|
||||||
);
|
if (!challenge)
|
||||||
|
return res
|
||||||
|
.status(404)
|
||||||
|
.json({ message: "Challenge not found", description: "Challenge ID does not exists" });
|
||||||
|
await challenge.deleteOne();
|
||||||
|
return res.status(200).json({});
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// TO BE TESTED
|
// TO BE TESTED
|
||||||
// add a friend
|
// add a friend
|
||||||
router.post(
|
router.post("/friends/:friendusername", checkAuth, async (req, res, next) => {
|
||||||
"/:userid/friends/:friendusername",
|
let { friendusername } = req.params;
|
||||||
checkAuth,
|
let { userId } = req;
|
||||||
catchAsync(async (req, res, next) => {
|
const user = await User.findById(userId);
|
||||||
let { friendusername } = req.params;
|
if (req.user.username === friendusername)
|
||||||
if (req.userData.username === friendusername)
|
res.json({
|
||||||
res.json({ success: false, error: { message: "Cannot add yourself as friend" } });
|
error: { description: "Cannot add yourself as friend", message: "Cannot add this user as friends" },
|
||||||
let friendData = await User.findOne({ username: friendusername });
|
});
|
||||||
if (friendData) {
|
let friendData = await User.findOne({ username: friendusername });
|
||||||
if (friendData.friends.includes(req.userData._id)) {
|
if (friendData) {
|
||||||
res.json({ success: false, error: { message: "User is already added as a friend" } });
|
if (friendData.friends.includes(req.user._id)) {
|
||||||
} else {
|
res.json({
|
||||||
friendData.friends.push(req.userData._id);
|
error: {
|
||||||
await friendData.save();
|
message: "User is already added as a friend",
|
||||||
req.userData.friends.push(friendData._id);
|
description: "User is already added as a friend",
|
||||||
await req.userData.save();
|
},
|
||||||
res.json({ success: true });
|
});
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
res.status(404).json({ success: false, error: { message: "username does not exist" } });
|
friendData.friends.push(req.user._id);
|
||||||
|
await friendData.save();
|
||||||
|
req.user.friends.push(friendData._id);
|
||||||
|
await req.user.save();
|
||||||
|
res.status(204).json(null);
|
||||||
}
|
}
|
||||||
})
|
} else {
|
||||||
);
|
res.status(404).json({
|
||||||
|
error: { message: "User not found", description: "username not found in DB" },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// remove a user from friends list
|
// remove a user from friends list
|
||||||
router.delete(
|
router.delete(
|
||||||
"/:userid/friends/:friendid",
|
"/friends/:friendid",
|
||||||
checkAuth,
|
checkAuth,
|
||||||
catchAsync(async (req, res, next) => {
|
catchAsync(async (req, res, next) => {
|
||||||
const { friendid } = req.params;
|
const { friendid } = req.params;
|
||||||
const { userData } = req;
|
const { userId } = req;
|
||||||
|
const user = await User.findById(userId);
|
||||||
|
|
||||||
// Find the friend user to be removed
|
// Find the friend user to be removed
|
||||||
const friendData = await User.findById(friendid);
|
const friendData = await User.findById(friendid);
|
||||||
if (!friendData) {
|
if (!friendData) {
|
||||||
return res.status(404).json({ success: false, error: { message: "Friend user not found" } });
|
return res.status(404).json({ error: { message: "Friend user not found" } });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the friend from the user's friends list
|
// Remove the friend from the user's friends list
|
||||||
const friendIndex = userData.friends.indexOf(friendData._id);
|
const friendIndex = user.friends.indexOf(friendData._id);
|
||||||
if (friendIndex === -1) {
|
if (friendIndex === -1) {
|
||||||
return res
|
return res.status(400).json({ error: { message: "Friend user not found in the friends list" } });
|
||||||
.status(400)
|
|
||||||
.json({ success: false, error: { message: "Friend user not found in the friends list" } });
|
|
||||||
}
|
}
|
||||||
userData.friends.splice(friendIndex, 1);
|
user.friends.splice(friendIndex, 1);
|
||||||
await userData.save();
|
await user.save();
|
||||||
|
|
||||||
// Remove the user from the friend's friends list
|
// Remove the user from the friend's friends list
|
||||||
const userIndex = friendData.friends.indexOf(userData._id);
|
const userIndex = friendData.friends.indexOf(user._id);
|
||||||
if (userIndex === -1) {
|
if (userIndex === -1) {
|
||||||
return res
|
return res.status(400).json({ error: { message: "User not found in the friend's friends list" } });
|
||||||
.status(400)
|
|
||||||
.json({ success: false, error: { message: "User not found in the friend's friends list" } });
|
|
||||||
}
|
}
|
||||||
friendData.friends.splice(userIndex, 1);
|
friendData.friends.splice(userIndex, 1);
|
||||||
await friendData.save();
|
await friendData.save();
|
||||||
|
|
||||||
return res.json({ success: true });
|
return res.json({});
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
// get current challenges of the user
|
// =============================================================
|
||||||
router.get(
|
|
||||||
"/:userid/challenges",
|
|
||||||
checkAuth,
|
|
||||||
catchAsync(async (req, res, next) => {
|
|
||||||
let { userData } = req;
|
|
||||||
let challenges = await Challenge.find({ challenged: userData.username });
|
|
||||||
if (!challenges) challenges = [];
|
|
||||||
console.log("Challenges to", userData.username, challenges);
|
|
||||||
res.json({ success: true, challenges: challenges });
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
// TO BE TESTED
|
// TO BE TESTED
|
||||||
// accept or decline a challenge
|
// get user details
|
||||||
// challengeID here refers to the roomID associated with the challenge
|
router.get("/:userid", async (req, res, next) => {
|
||||||
router.delete(
|
try {
|
||||||
"/:userid/challenges/:challengeID",
|
let userId = req.params.userid;
|
||||||
checkAuth,
|
const user = await User.findById(userId);
|
||||||
catchAsync(async (req, res) => {
|
let { id, username, email, fname, lname, country, location } = user;
|
||||||
let challengeResponse = req.query.response;
|
let friends = await user.getFriends();
|
||||||
let { challengeID } = req.params;
|
let games = await user.getGames();
|
||||||
if (challengeResponse === "accept") {
|
return res.status(200).json({ id, username, email, friends, fname, lname, country, location, games });
|
||||||
let { deletedCount } = await Challenge.deleteOne({ roomID: challengeID });
|
} catch (err) {
|
||||||
return res.json({ success: true });
|
next(err);
|
||||||
} else if (challengeResponse === "decline") {
|
}
|
||||||
let { deletedCount } = await Challenge.deleteOne({ roomID: challengeID });
|
});
|
||||||
return res.json({ success: true });
|
|
||||||
} else {
|
// get friends of the user
|
||||||
res.json({ success: false, error: { message: "Invalid query parameter" } });
|
router.get("/:userid/friends", async (req, res, next) => {
|
||||||
}
|
try {
|
||||||
})
|
const user = await User.findById(req.params.userid);
|
||||||
);
|
const friends = await user.getFriends();
|
||||||
|
return res.json({ friends });
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// get current challenges of the user
|
||||||
|
router.get("/:userid/challenges", checkAuth, async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
let { userId } = req;
|
||||||
|
const user = await user.findById(userId);
|
||||||
|
let challenges = await Challenge.find({ challenged: user.username });
|
||||||
|
if (!challenges) challenges = [];
|
||||||
|
console.log("Challenges to", user.username, challenges);
|
||||||
|
res.json({ challenges: challenges });
|
||||||
|
} catch (err) {
|
||||||
|
next(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
// get history of games played
|
// get history of games played
|
||||||
@@ -183,10 +234,10 @@ router.get(
|
|||||||
"/:userid/games",
|
"/:userid/games",
|
||||||
checkAuth,
|
checkAuth,
|
||||||
catchAsync(async (req, res, next) => {
|
catchAsync(async (req, res, next) => {
|
||||||
const userData = await User.findOne();
|
const user = await User.findOne();
|
||||||
let gamesData = await userData.getGames();
|
let gamesData = await user.getGames();
|
||||||
if (!gamesData) gamesData = [];
|
if (!gamesData) gamesData = [];
|
||||||
return res.status(200).json({ success: true, data: gamesData });
|
return res.status(200).json({ data: gamesData });
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -195,7 +246,7 @@ router.get(
|
|||||||
router.post("/:userid/game", checkAuth, async (req, res, next) => {
|
router.post("/:userid/game", checkAuth, async (req, res, next) => {
|
||||||
const gameData = req.body;
|
const gameData = req.body;
|
||||||
const gameDoc = await Game.create(gameData);
|
const gameDoc = await Game.create(gameData);
|
||||||
return res.json({ success: true, data: gameDoc });
|
return res.json({ data: gameDoc });
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
@@ -207,9 +258,9 @@ router.get(
|
|||||||
const { gameid } = req.params;
|
const { gameid } = req.params;
|
||||||
const gameData = await Game.findById(gameid);
|
const gameData = await Game.findById(gameid);
|
||||||
if (gameData) {
|
if (gameData) {
|
||||||
return res.status(200).json({ success: true, data: gameData });
|
return res.status(200).json({ data: gameData });
|
||||||
} else {
|
} else {
|
||||||
return res.status(404).json({ success: false, error: { message: "Game not found" } });
|
return res.status(404).json({ error: { message: "Game not found" } });
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ const { Game } = require("./models/game");
|
|||||||
const {
|
const {
|
||||||
CHESS_MOVE,
|
CHESS_MOVE,
|
||||||
CHESS_OPPONENT_MOVE,
|
CHESS_OPPONENT_MOVE,
|
||||||
CONNECTION,
|
|
||||||
JOIN_ROOM,
|
JOIN_ROOM,
|
||||||
JOIN_ROOM_ERROR,
|
JOIN_ROOM_ERROR,
|
||||||
JOIN_ROOM_SUCCESS,
|
JOIN_ROOM_SUCCESS,
|
||||||
|
|||||||
@@ -52,14 +52,15 @@ function checkAuthMiddleware(req, res, next) {
|
|||||||
}
|
}
|
||||||
let authToken = req.cookies["auth-token"];
|
let authToken = req.cookies["auth-token"];
|
||||||
if (!authToken) {
|
if (!authToken) {
|
||||||
return res.status(401).json({ userMessage: "Not authenticated", devMessage: "Auth token not found" });
|
return res.status(401).json({ message: "Not authenticated", description: "Auth token not found" });
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const validatedToken = validateJSONToken(authToken);
|
const validatedToken = validateJSONToken(authToken);
|
||||||
req.userid = validatedToken;
|
req.userId = validatedToken.id;
|
||||||
|
req.isAuthenticated = true;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log("NOT AUTH. TOKEN INVALID.");
|
console.log("NOT AUTH. TOKEN INVALID.");
|
||||||
return res.status(401).json({ userMessage: "Not authenticated", devMessage: "Invalid auth token" });
|
return res.status(401).json({ message: "Not authenticated", description: "Invalid auth token" });
|
||||||
}
|
}
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
|
.prettierrc.js
|
||||||
|
.eslintrc.js
|
||||||
|
env.d.ts
|
||||||
+36
-14
@@ -1,15 +1,37 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
env: { browser: true, es2020: true },
|
extends: [
|
||||||
extends: [
|
// By extending from a plugin config, we can get recommended rules without having to add them manually.
|
||||||
'eslint:recommended',
|
'eslint:recommended',
|
||||||
'plugin:react/recommended',
|
'plugin:react/recommended',
|
||||||
'plugin:react/jsx-runtime',
|
'plugin:import/recommended',
|
||||||
'plugin:react-hooks/recommended',
|
'plugin:jsx-a11y/recommended',
|
||||||
],
|
'plugin:@typescript-eslint/recommended',
|
||||||
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
// This disables the formatting rules in ESLint that Prettier is going to be responsible for handling.
|
||||||
settings: { react: { version: '18.2' } },
|
// Make sure it's always the last config, so it gets the chance to override other configs.
|
||||||
plugins: ['react-refresh'],
|
'eslint-config-prettier',
|
||||||
rules: {
|
],
|
||||||
'react-refresh/only-export-components': 'warn',
|
settings: {
|
||||||
},
|
react: {
|
||||||
}
|
// Tells eslint-plugin-react to automatically detect the version of React to use.
|
||||||
|
version: 'detect',
|
||||||
|
},
|
||||||
|
// Tells eslint how to resolve imports
|
||||||
|
'import/resolver': {
|
||||||
|
node: {
|
||||||
|
paths: ['src'],
|
||||||
|
extensions: ['.js', '.jsx', '.ts', '.tsx'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// Add your own rules here to override ones from the extended configs.
|
||||||
|
"react/react-in-jsx-scope": "off",
|
||||||
|
"react/jsx-uses-react": "off",
|
||||||
|
"no-console": "off",
|
||||||
|
},
|
||||||
|
"env":{
|
||||||
|
"browser":true,
|
||||||
|
"node":true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Generated
+1169
-510
File diff suppressed because it is too large
Load Diff
@@ -17,8 +17,16 @@
|
|||||||
"@mantine/hooks": "^6.0.14",
|
"@mantine/hooks": "^6.0.14",
|
||||||
"@radix-ui/react-icons": "^1.3.0",
|
"@radix-ui/react-icons": "^1.3.0",
|
||||||
"@tabler/icons-react": "^2.23.0",
|
"@tabler/icons-react": "^2.23.0",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^6.2.0",
|
||||||
|
"@typescript-eslint/parser": "^6.2.0",
|
||||||
"chess.js": "^1.0.0-beta.6",
|
"chess.js": "^1.0.0-beta.6",
|
||||||
|
"eslint": "^8.45.0",
|
||||||
|
"eslint-config-prettier": "^8.8.0",
|
||||||
|
"eslint-plugin-import": "^2.27.5",
|
||||||
|
"eslint-plugin-jsx-a11y": "^6.7.1",
|
||||||
|
"eslint-plugin-react": "^7.33.0",
|
||||||
"js-cookie": "^3.0.5",
|
"js-cookie": "^3.0.5",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-hook-form": "^7.45.2",
|
"react-hook-form": "^7.45.2",
|
||||||
@@ -30,8 +38,6 @@
|
|||||||
"@types/react": "^18.0.37",
|
"@types/react": "^18.0.37",
|
||||||
"@types/react-dom": "^18.0.11",
|
"@types/react-dom": "^18.0.11",
|
||||||
"@vitejs/plugin-react": "^4.0.0",
|
"@vitejs/plugin-react": "^4.0.0",
|
||||||
"eslint": "^8.38.0",
|
|
||||||
"eslint-plugin-react": "^7.32.2",
|
|
||||||
"eslint-plugin-react-hooks": "^4.6.0",
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"eslint-plugin-react-refresh": "^0.3.4",
|
"eslint-plugin-react-refresh": "^0.3.4",
|
||||||
"vite": "^4.3.9"
|
"vite": "^4.3.9"
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import './App.css'
|
|
||||||
import { createBrowserRouter, redirect, RouterProvider } from 'react-router-dom'
|
import { createBrowserRouter, redirect, RouterProvider } from 'react-router-dom'
|
||||||
import Home from './pages/Home'
|
import Home from './pages/Home'
|
||||||
import MainLayout from './layout/MainLayout'
|
import MainLayout from './layout/MainLayout'
|
||||||
import Settings from './pages/Settings/Settings'
|
import Settings from './pages/Settings/Settings'
|
||||||
import Profile from './pages/Settings/Profile'
|
|
||||||
import Friends from './pages/Settings/Friends'
|
import Friends from './pages/Settings/Friends'
|
||||||
import Password from './pages/Settings/Password'
|
import Password from './pages/Settings/Password'
|
||||||
import Themes from './pages/Settings/Themes'
|
import Themes from './pages/Settings/Themes'
|
||||||
@@ -11,12 +9,11 @@ import PlayLayout from './pages/Play/Layout'
|
|||||||
import PlayFriend from './pages/Play/PlayFriend'
|
import PlayFriend from './pages/Play/PlayFriend'
|
||||||
import Play from './pages/Play/Play'
|
import Play from './pages/Play/Play'
|
||||||
import AuthenticationPage, { loginAction, signupAction } from './pages/Authentication/Authentication'
|
import AuthenticationPage, { loginAction, signupAction } from './pages/Authentication/Authentication'
|
||||||
import { getAuthToken, getUserData } from '../utils/auth'
|
import { getAuthToken, getUserData } from './utils/auth'
|
||||||
import { logoutAction } from './components/Logout'
|
|
||||||
import ChallengeFriend, { playFriendAction } from './pages/Play/ChallengeFriend'
|
import ChallengeFriend, { playFriendAction } from './pages/Play/ChallengeFriend'
|
||||||
import ChessGame from './pages/Chess/ChessGame'
|
import ChessGame from './pages/Chess/ChessGame'
|
||||||
import ChessGameContextProvider from './context/chess-game-context'
|
import ChessGameContextProvider from './context/chess-game-context'
|
||||||
import { action as profileAction } from './pages/Settings/Profile'
|
import Profile, { action as profileAction } from './pages/Settings/Profile'
|
||||||
|
|
||||||
const router = createBrowserRouter([{
|
const router = createBrowserRouter([{
|
||||||
path: '/',
|
path: '/',
|
||||||
@@ -58,7 +55,7 @@ const router = createBrowserRouter([{
|
|||||||
}, {
|
}, {
|
||||||
path: '/signup', element: <AuthenticationPage isLogin={false} />, action: signupAction, loader: () => { if (getAuthToken()) return redirect('/signup'); else return null; }
|
path: '/signup', element: <AuthenticationPage isLogin={false} />, action: signupAction, loader: () => { if (getAuthToken()) return redirect('/signup'); else return null; }
|
||||||
}, {
|
}, {
|
||||||
path: '/logout', loader: () => { getAuthToken() || redirect('/home') }, action: logoutAction
|
path: '/logout', loader: () => { getAuthToken() || redirect('/home') }
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import React, { useContext, useState } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import Piece from './Piece';
|
import Piece from './Piece';
|
||||||
import { socket } from '../socket';
|
import { socket } from '../socket';
|
||||||
import { Box, Flex, Modal } from '@mantine/core';
|
import { Box, Flex } from '@mantine/core';
|
||||||
import { useDroppable } from '@dnd-kit/core'
|
import { useDroppable } from '@dnd-kit/core'
|
||||||
import { ChessGameContext } from '../context/chess-game-context';
|
import { ChessGameContext } from '../context/chess-game-context';
|
||||||
import { SOCKET_EVENTS } from '../constants';
|
import { SOCKET_EVENTS } from '../constants';
|
||||||
@@ -9,7 +9,7 @@ const { CHESS_MOVE } = SOCKET_EVENTS
|
|||||||
|
|
||||||
const Cell = ({ cell }) => {
|
const Cell = ({ cell }) => {
|
||||||
let roomID = localStorage.getItem('roomID');
|
let roomID = localStorage.getItem('roomID');
|
||||||
let { square, type, color } = cell;
|
let { square, type } = cell;
|
||||||
const { getSquareColor, isSquareMarked, handleSquareClick } = useContext(ChessGameContext)
|
const { getSquareColor, isSquareMarked, handleSquareClick } = useContext(ChessGameContext)
|
||||||
const { isOver, setNodeRef } = useDroppable({ id: square });
|
const { isOver, setNodeRef } = useDroppable({ id: square });
|
||||||
let squareColor = getSquareColor(square);
|
let squareColor = getSquareColor(square);
|
||||||
@@ -24,11 +24,16 @@ const Cell = ({ cell }) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = marked && !type ? <Mark /> : <Piece cell={cell} />;
|
let content = null;
|
||||||
|
if (marked) {
|
||||||
|
content = <Mark />
|
||||||
|
} else if (type) {
|
||||||
|
content = <Piece cell={cell} />
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex ref={setNodeRef} style={{ aspectRatio: '1/1', position: 'relative' }} sx={theme => {
|
<Flex ref={setNodeRef} style={{ aspectRatio: '1/1' }} sx={theme => {
|
||||||
let color = theme.colors.lime
|
let color = theme.colors.lime;
|
||||||
return { backgroundColor: squareColor === 'b' ? color[8] : color[1], filter: 'saturate(0.5)' }
|
return { backgroundColor: squareColor === 'b' ? color[8] : color[1], filter: 'saturate(0.5)' }
|
||||||
}} onClick={handleClick} bg={squareColor === 'w' ? "white" : "gray"} >
|
}} onClick={handleClick} bg={squareColor === 'w' ? "white" : "gray"} >
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,88 +1,35 @@
|
|||||||
import { Button, Group, Stack, Text, Title } from '@mantine/core';
|
import { Button, Group, Stack, Text, Title } from '@mantine/core';
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import { getAuthToken, getUserData } from '../../utils/auth'
|
|
||||||
|
|
||||||
const Challenges = () => {
|
const Challenges = () => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [challenges, setChallenges] = useState([]);
|
const [challenges, setChallenges] = useState([]);
|
||||||
const { id: userid } = getUserData();
|
|
||||||
const [error, setError] = useState(null);
|
const [error, setError] = useState(null);
|
||||||
|
console.log(challenges)
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const abortController = new AbortController();
|
if (error) return;
|
||||||
let response = null;
|
|
||||||
|
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
let url = `${import.meta.env.VITE_BACKEND_HOST}/api/user/${userid}/challenges`;
|
let url = `${import.meta.env.VITE_BACKEND_HOST}/api/user/challenges`;
|
||||||
try {
|
try {
|
||||||
response = await fetch(url, {
|
const response = await fetch(url, {
|
||||||
signal: abortController.signal, headers: {
|
credentials: 'include'
|
||||||
'Authorization': `Bearer ${getAuthToken()}`
|
});
|
||||||
}
|
|
||||||
})
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.success) {
|
if (response.ok) {
|
||||||
setChallenges(data.challenges);
|
setChallenges(data);
|
||||||
} else {
|
} else {
|
||||||
throw data.error;
|
setError('Cannot')
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.message === 'The user aborted a request.');
|
console.log(error);
|
||||||
else {
|
setError("Something went wrong")
|
||||||
console.log('Error fetching data');
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fetchData();
|
fetchData();
|
||||||
|
}, [error])
|
||||||
return () => {
|
|
||||||
if (!response) {
|
|
||||||
abortController.abort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const acceptChallengeHandler = ({ challenger, roomID, color, timeLimit }) => {
|
|
||||||
async function handler() {
|
|
||||||
const res = await deleteChallenge(roomID, 'accept');
|
|
||||||
if (res?.success) {
|
|
||||||
localStorage.setItem('myColor', color === 'b' ? 'w' : 'b');
|
|
||||||
localStorage.setItem('roomID', roomID);
|
|
||||||
localStorage.setItem('opponent', challenger);
|
|
||||||
localStorage.setItem('timeLimit', timeLimit);
|
|
||||||
navigate(`/game/friend/${roomID}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
const declineChallengeHandler = ({ challenger, roomID, color, timeLimit }) => {
|
|
||||||
async function handler() {
|
|
||||||
const res = await deleteChallenge(roomID, 'decline');
|
|
||||||
}
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
|
|
||||||
const deleteChallenge = async (challengeID, response) => {
|
|
||||||
try {
|
|
||||||
let url = `${import.meta.env.VITE_BACKEND_HOST}/api/user/${userid}/challenges/${challengeID}?response=${response}`
|
|
||||||
console.log(url)
|
|
||||||
let res = await fetch(url, {
|
|
||||||
method: 'DELETE', headers: {
|
|
||||||
Authorization: `Bearer ${getAuthToken()}`,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
const resData = await res.json();
|
|
||||||
return resData;
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err)
|
|
||||||
setError(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!challenges || challenges.length === 0) {
|
if (!challenges || challenges.length === 0) {
|
||||||
return (
|
return (
|
||||||
@@ -93,19 +40,65 @@ const Challenges = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Title mt="20px" mb="10px" order={3}>Challenges</Title>
|
||||||
|
<Text>{error}</Text><Text onClick={() => setError(null)} fw={800} sx={{ cursor: 'pointer' }}>Retry</Text>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Title mt="20px" mb="10px" order={3}>Challenges</Title>
|
<Title mt="20px" mb="10px" order={3}>Challenges</Title>
|
||||||
<Stack>
|
<Stack>
|
||||||
{
|
{
|
||||||
challenges.map(({ challenger, roomID, color, timeLimit }) => {
|
challenges.map(({ id, challenger, roomID, color, timeLimit }, index) => {
|
||||||
console.log(challenger, roomID, color, timeLimit);
|
console.log(challenger, roomID, color, timeLimit);
|
||||||
return (
|
return (
|
||||||
<Group position='apart'>
|
<Group position='apart' key={id}>
|
||||||
<Text>Challenge by {challenger}</Text>
|
<Text>Challenge by {challenger}</Text>
|
||||||
<Group position='center'>
|
<Group position='center'>
|
||||||
<Button color='lime' onClick={acceptChallengeHandler({ challenger, roomID, color, timeLimit })}>Accept</Button>
|
<Button color='lime' onClick={async () => {
|
||||||
<Button color='gray' onClick={declineChallengeHandler({ challenger, roomID, color, timeLimit })}>Decline</Button>
|
try {
|
||||||
|
let url = `${import.meta.env.VITE_BACKEND_HOST}/api/user/challenges/${id}`
|
||||||
|
const response = await fetch(url, { method: 'DELETE', credentials: 'include' });
|
||||||
|
console.log(id, challenger);
|
||||||
|
const resData = await response.json();
|
||||||
|
if (response.ok) {
|
||||||
|
localStorage.setItem('myColor', color === 'b' ? 'w' : 'b');
|
||||||
|
localStorage.setItem('roomID', roomID);
|
||||||
|
localStorage.setItem('opponent', challenger);
|
||||||
|
localStorage.setItem('timeLimit', timeLimit);
|
||||||
|
navigate(`/game/friend/${roomID}`);
|
||||||
|
} else {
|
||||||
|
console.log(resData)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setError("Something went wrong");
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}}>Accept</Button>
|
||||||
|
<Button color='gray' onClick={async () => {
|
||||||
|
try {
|
||||||
|
let url = `${import.meta.env.VITE_BACKEND_HOST}/api/user/challenges/${id}`
|
||||||
|
const response = await fetch(url, { method: 'DELETE', credentials: 'include' });
|
||||||
|
console.log(id, challenger);
|
||||||
|
if (response.ok) {
|
||||||
|
challenges.splice(index, 1);
|
||||||
|
setChallenges(challenges);
|
||||||
|
} else {
|
||||||
|
const resData = await response.json();
|
||||||
|
console.log(resData)
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
setError("Something went wrong");
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
}}>Decline</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const FriendsList = () => {
|
|||||||
No friends
|
No friends
|
||||||
</Text>
|
</Text>
|
||||||
:
|
:
|
||||||
friends.map((friend, index) => <NavLink key={index} component={Link} to={`/play/friend/${friend.username}`} p='5px' icon={<Avatar size='sm' color='blue' children={friend.username[0].toUpperCase()} />} label={<Text fw={700}>{friend.username}</Text>} />)
|
friends.map((friend, index) => <NavLink key={index} component={Link} to={`/play/friend/${friend.username}`} p='5px' icon={<Avatar size='sm' color='blue' >{friend.username[0].toUpperCase()}</Avatar>} label={<Text fw={700}>{friend.username}</Text>} />)
|
||||||
}
|
}
|
||||||
</Flex>
|
</Flex>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import { ChessGameContext } from '../context/chess-game-context'
|
import { ChessGameContext } from '../context/chess-game-context'
|
||||||
import { Button, Flex, Group, ScrollArea, Text, Tooltip, createStyles } from '@mantine/core';
|
import { Button, Flex, ScrollArea, Tooltip, createStyles } from '@mantine/core';
|
||||||
import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'
|
import { IconChevronLeft, IconChevronRight } from '@tabler/icons-react'
|
||||||
|
|
||||||
const useStyles = createStyles(theme => {
|
const useStyles = createStyles(() => {
|
||||||
return {
|
return {
|
||||||
movebtn: {
|
movebtn: {
|
||||||
fontSize: '14px',
|
fontSize: '14px',
|
||||||
@@ -26,7 +26,7 @@ const useStyles = createStyles(theme => {
|
|||||||
|
|
||||||
const GameHistory = () => {
|
const GameHistory = () => {
|
||||||
let { classes } = useStyles();
|
let { classes } = useStyles();
|
||||||
const { gameHistory, jumpTo, currentIndex, goBack, goAhead } = useContext(ChessGameContext)
|
const { gameHistory, jumpTo, goBack, goAhead } = useContext(ChessGameContext)
|
||||||
|
|
||||||
let gameHistoryJSX = [];
|
let gameHistoryJSX = [];
|
||||||
for (let i = 0; i < gameHistory.length;) {
|
for (let i = 0; i < gameHistory.length;) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Button, Flex, Modal, Text, Title } from '@mantine/core'
|
import { Button, Flex, Modal, Text, Title } from '@mantine/core'
|
||||||
import { Form, redirect, useNavigate } from 'react-router-dom'
|
import { redirect, useNavigate } from 'react-router-dom'
|
||||||
import { useDisclosure } from '@mantine/hooks'
|
import { useDisclosure } from '@mantine/hooks'
|
||||||
|
|
||||||
const Logout = () => {
|
const Logout = () => {
|
||||||
@@ -27,7 +27,7 @@ const Logout = () => {
|
|||||||
localStorage.removeItem('loggedIn');
|
localStorage.removeItem('loggedIn');
|
||||||
return navigate('/login');
|
return navigate('/login');
|
||||||
} else {
|
} else {
|
||||||
return setErrorMsg(resData.userMessage || "Something went wrong")
|
return setErrorMsg(resData.message || "Something went wrong")
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setIsLoading(false)
|
setIsLoading(false)
|
||||||
@@ -54,11 +54,4 @@ const Logout = () => {
|
|||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const logoutAction = ({ request }) => {
|
|
||||||
localStorage.removeItem('token');
|
|
||||||
localStorage.removeItem('user');
|
|
||||||
return redirect('/login');
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Logout
|
export default Logout
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Group, NavLink, Text, ThemeIcon, UnstyledButton } from '@mantine/core'
|
import { NavLink, Text, ThemeIcon } from '@mantine/core'
|
||||||
import { GearIcon, HomeIcon, PlayIcon } from '@radix-ui/react-icons'
|
import { GearIcon, HomeIcon, PlayIcon } from '@radix-ui/react-icons'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
@@ -31,7 +31,7 @@ const NavbarLink = ({ label, icon, to, index, active, setActive }) => {
|
|||||||
component={Link}
|
component={Link}
|
||||||
to={to}
|
to={to}
|
||||||
icon={
|
icon={
|
||||||
<ThemeIcon variant="filled" color={active===index?'gray':'lime'}>
|
<ThemeIcon variant="filled" color={active === index ? 'gray' : 'lime'}>
|
||||||
{icon}
|
{icon}
|
||||||
</ThemeIcon>
|
</ThemeIcon>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const useStyles = createStyles((theme) => ({
|
|||||||
boxShadow: 'none',
|
boxShadow: 'none',
|
||||||
borderColor: 'transparent'
|
borderColor: 'transparent'
|
||||||
}
|
}
|
||||||
}))
|
}));
|
||||||
|
|
||||||
const Piece = ({ cell }) => {
|
const Piece = ({ cell }) => {
|
||||||
const { classes } = useStyles();
|
const { classes } = useStyles();
|
||||||
@@ -50,7 +50,7 @@ const Piece = ({ cell }) => {
|
|||||||
const style = transform ? {
|
const style = transform ? {
|
||||||
transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
|
transform: `translate3d(${transform.x}px, ${transform.y}px, 0)`,
|
||||||
cursor: isDragging ? 'grabbing' : 'pointer',
|
cursor: isDragging ? 'grabbing' : 'pointer',
|
||||||
zIndex: isDragging ? 100 : 20,
|
zIndex: isDragging ? 1000 : 10,
|
||||||
aspectRatio: '1',
|
aspectRatio: '1',
|
||||||
touchAction: 'none',
|
touchAction: 'none',
|
||||||
borderRadius: '10px',
|
borderRadius: '10px',
|
||||||
@@ -66,15 +66,15 @@ const Piece = ({ cell }) => {
|
|||||||
|
|
||||||
if (logo) {
|
if (logo) {
|
||||||
return (
|
return (
|
||||||
<div style={{ position: 'relative', zIndex: 100 }}>
|
<div style={{ position: 'relative' }}>
|
||||||
<div style={{ position: 'absolute', borderRadius: '50%', boxSizing: 'border-box', borderWidth: '8px', width: '100%', height: '100%', borderStyle: 'solid', borderColor }}>
|
<div style={{ position: 'absolute', borderRadius: '50%', boxSizing: 'border-box', borderWidth: '8px', width: '100%', height: '100%', borderStyle: 'solid', borderColor }}>
|
||||||
</div>
|
</div>
|
||||||
<Image classNames={{ root: classes['chess-piece'] }} ref={setNodeRef} style={style} sx={{ cursor: 'pointer' }} {...listeners} {...attributes} src={`/src/assets/images/pieces/${logo}.png`} />
|
<Image classNames={{ root: classes['chess-piece'] }} ref={setNodeRef} style={style} sx={{ cursor: 'pointer' }} {...listeners} {...attributes} src={`/src/assets/images/${logo}.png`} />
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<div style={{ width: '100%' }}></div>
|
<div style={{ width: '100%', zIndex: 100 }}></div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, { createContext, useReducer, useRef, useState } from 'react'
|
import React, { createContext, useReducer, useRef, useState } from 'react'
|
||||||
import { ChessModified, chessInit } from '../../utils/chess';
|
import { ChessModified, chessInit } from '../utils/chess';
|
||||||
import { DISPATCH_EVENTS, SOCKET_EVENTS } from '../constants';
|
import { DISPATCH_EVENTS, SOCKET_EVENTS } from '../constants';
|
||||||
import { socket } from '../socket';
|
import { socket } from '../socket';
|
||||||
const { CAPTURE_PIECE, MOVE_PIECE, SELECT_PIECE, JUMP_TO, SET_GAME_HISTORY, END_GAME } = DISPATCH_EVENTS
|
const { CAPTURE_PIECE, MOVE_PIECE, SELECT_PIECE, JUMP_TO, SET_GAME_HISTORY, END_GAME } = DISPATCH_EVENTS
|
||||||
const { GAME_END, CHESS_MOVE, CHESS_OPPONENT_MOVE } = SOCKET_EVENTS;
|
const { GAME_END, CHESS_MOVE } = SOCKET_EVENTS;
|
||||||
export const ChessGameContext = createContext();
|
export const ChessGameContext = createContext();
|
||||||
// myColor: null, chess: null, chessBoard: null, moveHints: null, selected: null, dispatch: null, handleOpponentMove: null, handleSquareClick: null, getSquareColor: null, isSquareMarked: null, selectPiece: null, handleDrop: null
|
// myColor: null, chess: null, chessBoard: null, moveHints: null, selected: null, dispatch: null, handleOpponentMove: null, handleSquareClick: null, getSquareColor: null, isSquareMarked: null, selectPiece: null, handleDrop: null
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ const ChessGameContextProvider = ({ children }) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectPiece({ square, type, color: pieceColor }) {
|
function selectPiece({ square, color: pieceColor }) {
|
||||||
if (pieceColor === myColor && myColor === chess.turn()) {
|
if (pieceColor === myColor && myColor === chess.turn()) {
|
||||||
dispatch({ type: SELECT_PIECE, val: square });
|
dispatch({ type: SELECT_PIECE, val: square });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
import React, { createContext, useEffect, useState } from 'react'
|
import React, { createContext, useEffect, useState } from 'react'
|
||||||
import Cookie from 'js-cookie'
|
|
||||||
export const UserDataContext = createContext();
|
|
||||||
|
|
||||||
|
export const UserDataContext = createContext();
|
||||||
|
|
||||||
const UserDataContextProvider = ({ children }) => {
|
const UserDataContextProvider = ({ children }) => {
|
||||||
// TODO: use more secure mechanism insted of localstorage
|
// TODO: use more secure mechanism insted of localstorage
|
||||||
const [isLoggedIn, setIsLoggedIn] = useState(JSON.parse(localStorage.getItem('loggedIn')));
|
const [isLoggedIn, setIsLoggedIn] = useState(JSON.parse(localStorage.getItem('loggedIn')));
|
||||||
const [user, setUser] = useState(null);
|
const [user, setUser] = useState(null);
|
||||||
const [errorMessage, setErrorMessage] = useState("");
|
const [errorMessage, setErrorMessage] = useState("");
|
||||||
console.log(user)
|
|
||||||
|
|
||||||
async function fetchUserDetails() {
|
async function fetchUserDetails() {
|
||||||
try {
|
try {
|
||||||
@@ -22,8 +20,7 @@ const UserDataContextProvider = ({ children }) => {
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
setUser(resData);
|
setUser(resData);
|
||||||
} else {
|
} else {
|
||||||
console.log(resData.devMessage);
|
setErrorMessage(resData.message);
|
||||||
setErrorMessage(resData.userMessage);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -36,7 +33,7 @@ const UserDataContextProvider = ({ children }) => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<UserDataContext.Provider value={{ user, friends: user?.friends , games: user?.games, errorMessage, isLoggedIn, setIsLoggedIn }}>
|
<UserDataContext.Provider value={{ user, friends: user?.friends, games: user?.games, errorMessage, isLoggedIn, setIsLoggedIn }}>
|
||||||
{children}
|
{children}
|
||||||
</UserDataContext.Provider>
|
</UserDataContext.Provider>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import React, { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
|
|
||||||
const useCountDown = (timeLimit,isTimerOn) => {
|
const useCountDown = (timeLimit, isTimerOn) => {
|
||||||
const [timeLeft, setTimeLeft] = useState(timeLimit * 60 * 1000);
|
const [timeLeft, setTimeLeft] = useState(timeLimit * 60 * 1000);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if(!isTimerOn) {
|
if (!isTimerOn) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (timeLeft > 0) {
|
if (timeLeft > 0) {
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ const LoginForm = () => {
|
|||||||
setIsLoggedIn(true);
|
setIsLoggedIn(true);
|
||||||
return navigate('/');
|
return navigate('/');
|
||||||
} else {
|
} else {
|
||||||
setErrorMsg(resData.userMessage || "Something went wrong");
|
setErrorMsg(resData.message || "Something went wrong");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
@@ -123,8 +123,8 @@ const SignupForm = () => {
|
|||||||
} else {
|
} else {
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
console.log(resData);
|
console.log(resData);
|
||||||
console.log(resData.devMessage);
|
console.log(resData.description);
|
||||||
setErrorMsg(resData.userMessage);
|
setErrorMsg(resData.message);
|
||||||
resData?.error?.username && setError('username', { message: resData.error.username });
|
resData?.error?.username && setError('username', { message: resData.error.username });
|
||||||
resData?.error?.email && setError('email', { message: resData.error.email });
|
resData?.error?.email && setError('email', { message: resData.error.email });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
import { Avatar, Button, Flex, Group, Image, Loader, MediaQuery, Modal, 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 React, { useContext, useEffect, useState } from 'react'
|
||||||
import ChessBoard from '../Chess/ChessBoard'
|
import ChessBoard from '../Chess/ChessBoard'
|
||||||
import { useNavigate, useParams } from 'react-router-dom'
|
import { useNavigate } from 'react-router-dom'
|
||||||
import { socket } from '../../socket'
|
import { socket } from '../../socket'
|
||||||
import { getUserData } from '../../../utils/auth'
|
import { getUserData } from '../../utils/auth'
|
||||||
import { ChessGameContext } from '../../context/chess-game-context'
|
import { ChessGameContext } from '../../context/chess-game-context'
|
||||||
import GameHistory from '../../components/GameHistory'
|
import GameHistory from '../../components/GameHistory'
|
||||||
import Timer from './Timer'
|
import MainLoader from '../../components/MainLoader'
|
||||||
import { useDisclosure } from '@mantine/hooks'
|
import { useDisclosure } from '@mantine/hooks'
|
||||||
import { SOCKET_EVENTS } from '../../constants'
|
import { SOCKET_EVENTS } from '../../constants'
|
||||||
const { CONNECT, DISCONNECT, CHESS_OPPONENT_MOVE, USER_RESIGNED, CONNECTION, JOIN_ROOM, JOIN_ROOM_ERROR, JOIN_ROOM_SUCCESS, ROOM_FULL, USER_JOINED_ROOM } = SOCKET_EVENTS;
|
const { CONNECT, DISCONNECT, CHESS_OPPONENT_MOVE, USER_RESIGNED, JOIN_ROOM, JOIN_ROOM_ERROR, JOIN_ROOM_SUCCESS, ROOM_FULL, USER_JOINED_ROOM } = SOCKET_EVENTS;
|
||||||
|
|
||||||
const ChessGame = () => {
|
const ChessGame = () => {
|
||||||
const { setGameHistory, isTimerOn, setIsTimerOn, hasGameEnded, gameEndedReason, endGame } = useContext(ChessGameContext);
|
const { setGameHistory, hasGameEnded, gameEndedReason, endGame } = useContext(ChessGameContext);
|
||||||
const [gameEndedModalOpen, modalFunctions] = useDisclosure(true);
|
const [gameEndedModalOpen, modalFunctions] = useDisclosure(true);
|
||||||
|
|
||||||
const user = getUserData();
|
const user = getUserData();
|
||||||
@@ -67,7 +67,7 @@ const ChessGame = () => {
|
|||||||
console.log('Socket disconnected due to', reason);
|
console.log('Socket disconnected due to', reason);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(CHESS_OPPONENT_MOVE, (data) => {
|
socket.on(CHESS_OPPONENT_MOVE, () => {
|
||||||
// console.log(data);
|
// console.log(data);
|
||||||
// setIsTimerOn(true);
|
// setIsTimerOn(true);
|
||||||
})
|
})
|
||||||
@@ -76,9 +76,9 @@ const ChessGame = () => {
|
|||||||
setIsWaiting(false);
|
setIsWaiting(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on(USER_RESIGNED, (roomID, username) => {
|
socket.on(USER_RESIGNED, () => {
|
||||||
endGame('RESIGN');
|
endGame('RESIGN');
|
||||||
})
|
});
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
socket.offAny();
|
socket.offAny();
|
||||||
@@ -87,7 +87,7 @@ const ChessGame = () => {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!hasJoinedRoom) return (
|
if (!hasJoinedRoom) return (
|
||||||
<Loader variant='bars' />
|
<MainLoader />
|
||||||
)
|
)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -104,7 +104,9 @@ const ChessGame = () => {
|
|||||||
style={{ width: "500px" }}
|
style={{ width: "500px" }}
|
||||||
p="2px"
|
p="2px"
|
||||||
label={isWaiting ? "Waiting for opponent..." : opponent}
|
label={isWaiting ? "Waiting for opponent..." : opponent}
|
||||||
icon={<Avatar radius="3px" children={opponent[0].toUpperCase()} />}
|
icon={<Avatar radius="3px" >
|
||||||
|
{opponent[0].toUpperCase}
|
||||||
|
</Avatar>}
|
||||||
description={"description"}
|
description={"description"}
|
||||||
/>
|
/>
|
||||||
{/* <Timer on={!isTimerOn} /> */}
|
{/* <Timer on={!isTimerOn} /> */}
|
||||||
@@ -128,7 +130,9 @@ const ChessGame = () => {
|
|||||||
style={{ width: "500px" }}
|
style={{ width: "500px" }}
|
||||||
p="2px"
|
p="2px"
|
||||||
label={username}
|
label={username}
|
||||||
icon={<Avatar radius="3px" children={username[0].toUpperCase()} />}
|
icon={<Avatar radius="3px" >
|
||||||
|
{username[0].toUpperCase()}
|
||||||
|
</Avatar>}
|
||||||
description={"description"}
|
description={"description"}
|
||||||
/>
|
/>
|
||||||
{/* <Timer on={isTimerOn} /> */}
|
{/* <Timer on={isTimerOn} /> */}
|
||||||
@@ -140,7 +144,7 @@ const ChessGame = () => {
|
|||||||
height: '100%',
|
height: '100%',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
borderRadius: '10px',
|
borderRadius: '10px',
|
||||||
backgroundColor:'#272623'
|
backgroundColor: '#272623'
|
||||||
}} bg='gray' justify='start' py='md' align='center' direction='column' h="600px">
|
}} bg='gray' justify='start' py='md' align='center' direction='column' h="600px">
|
||||||
<Title my='20px'>Game Data</Title>
|
<Title my='20px'>Game Data</Title>
|
||||||
<Flex direction='column' w='100%'>
|
<Flex direction='column' w='100%'>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { Box } from '@mantine/core';
|
|||||||
import { ChessGameContext } from '../../context/chess-game-context';
|
import { ChessGameContext } from '../../context/chess-game-context';
|
||||||
|
|
||||||
const Timer = ({ on }) => {
|
const Timer = ({ on }) => {
|
||||||
const { isTimerOn } = useContext(ChessGameContext)
|
// const { isTimerOn } = useContext(ChessGameContext)
|
||||||
const timeLimit = localStorage.getItem('timeLimit');
|
const timeLimit = localStorage.getItem('timeLimit');
|
||||||
const [seconds, minutes] = useCountDown(timeLimit, on);
|
const [seconds, minutes] = useCountDown(timeLimit, on);
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Avatar, Button, Card, Flex, Image, Select, Text, TextInput, Title } from '@mantine/core'
|
import { Avatar, Button, Card, Flex, Select, Text, Title } from '@mantine/core'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Form, redirect, useParams } from 'react-router-dom'
|
import { Form, redirect, useParams } from 'react-router-dom'
|
||||||
import { getAuthToken, getUserData } from '../../../utils/auth'
|
import { getUserData } from '../../utils/auth'
|
||||||
|
|
||||||
const ChallengeFriend = () => {
|
const ChallengeFriend = () => {
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
@@ -9,12 +9,12 @@ const ChallengeFriend = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Card
|
<Card
|
||||||
maw={450} sx={{
|
maw={450} sx={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '600px',
|
height: '600px',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
backgroundColor:'#262523'
|
backgroundColor: '#262523'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Form action={`/play/friend/${friend_username}`} method='POST'>
|
<Form action={`/play/friend/${friend_username}`} method='POST'>
|
||||||
<Flex align="center" direction="column" justify="center" gap="xs" my="lg">
|
<Flex align="center" direction="column" justify="center" gap="xs" my="lg">
|
||||||
@@ -42,20 +42,19 @@ export const playFriendAction = async ({ request, params }) => {
|
|||||||
let timeLimit = formData.get('timeLimit');
|
let timeLimit = formData.get('timeLimit');
|
||||||
let username = getUserData().username;
|
let username = getUserData().username;
|
||||||
let challenged = params.friend_username;
|
let challenged = params.friend_username;
|
||||||
console.log(color, timeLimit, username, challenged);
|
|
||||||
|
|
||||||
let roomIDURL = `${import.meta.env.VITE_BACKEND_HOST}/api/room/create`;
|
let roomIDURL = `${import.meta.env.VITE_BACKEND_HOST}/api/room`;
|
||||||
let reqBody = { challenger: username, challenged, timeLimit, color }
|
let reqBody = { challenger: username, challenged, timeLimit, color }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(reqBody);
|
|
||||||
const response = await fetch(roomIDURL, {
|
const response = await fetch(roomIDURL, {
|
||||||
method: 'POST', body: JSON.stringify(reqBody), headers: {
|
method: 'POST', body: JSON.stringify(reqBody), headers: {
|
||||||
'Authorization': `Bearer ${getAuthToken()}`,
|
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
},
|
||||||
|
credentials: 'include'
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(response.status);
|
||||||
const resJSON = await response.json();
|
const resJSON = await response.json();
|
||||||
const { roomID } = resJSON;
|
const { roomID } = resJSON;
|
||||||
console.log('Room ID:', roomID);
|
console.log('Room ID:', roomID);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { Avatar, Box, Card, Divider, Flex, Image, MediaQuery, NavLink, Text, Title } from '@mantine/core'
|
import { Avatar, Flex, Image, MediaQuery, NavLink } from '@mantine/core'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Link, Outlet } from 'react-router-dom'
|
import { Outlet } from 'react-router-dom'
|
||||||
import { getUserData } from '../../../utils/auth';
|
import { getUserData } from '../../utils/auth';
|
||||||
|
|
||||||
const Layout = () => {
|
const Layout = () => {
|
||||||
const user = getUserData();
|
const user = getUserData();
|
||||||
|
|||||||
@@ -1,48 +1,30 @@
|
|||||||
import React, { useState } from 'react'
|
import React from 'react'
|
||||||
import { Button, Card, CopyButton, Flex, Group, Image, Modal, NativeSelect, NavLink, Select, Text, TextInput, Title } from '@mantine/core'
|
import { Button, Card, Flex, Image, Modal, NativeSelect, Text, TextInput, Title } from '@mantine/core'
|
||||||
import { useDisclosure } from '@mantine/hooks'
|
import { useDisclosure } from '@mantine/hooks'
|
||||||
import { IconSearch, IconUserCircle } from '@tabler/icons-react'
|
import { IconSearch } from '@tabler/icons-react'
|
||||||
import FriendsList from '../../components/FriendsList'
|
import FriendsList from '../../components/FriendsList'
|
||||||
import { Form } from 'react-router-dom'
|
|
||||||
import Challenges from '../../components/Challenges'
|
import Challenges from '../../components/Challenges'
|
||||||
|
|
||||||
const createChallengeLink = (color) => {
|
|
||||||
let challengeLink = Math.floor(Math.random() * 100_000_000).toString();
|
|
||||||
if (color === 'RANDOM') {
|
|
||||||
challengeLink = challengeLink.concat(Math.random() < 0.5 ? 'W' : 'B');
|
|
||||||
} else {
|
|
||||||
challengeLink = challengeLink.concat(color);
|
|
||||||
}
|
|
||||||
return challengeLink;
|
|
||||||
}
|
|
||||||
|
|
||||||
const PlayFriend = () => {
|
const PlayFriend = () => {
|
||||||
const [opened, { open, close }] = useDisclosure(false);
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
const [joinChallengeModalState, modalFunctions] = useDisclosure(false);
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal zIndex={10} opened={opened} onClose={close} title={<Text mx="auto" size="xl">Create Challenge Link</Text>} centered>
|
<Modal zIndex={10} opened={opened} onClose={close} title={<Text mx="auto" size="xl">Create Challenge Link</Text>} centered>
|
||||||
<Text>Start a game with anyone</Text>
|
<Text>Start a game with anyone</Text>
|
||||||
<div>
|
<div>
|
||||||
<NativeSelect onChange={(evt) => setColor(evt.target.value)} my="20px" label={<Text mx="auto" order={3}>I play as</Text>} placeholder='choose your color' data={[
|
<NativeSelect my="20px" label={<Text mx="auto" order={3}>I play as</Text>} placeholder='choose your color' data={[
|
||||||
{ value: 'W', label: 'White' },
|
{ value: 'W', label: 'White' },
|
||||||
{ value: 'B', label: 'Black' },
|
{ value: 'B', label: 'Black' },
|
||||||
{ value: 'RANDOM', label: 'Random' }
|
{ value: 'RANDOM', label: 'Random' }
|
||||||
]} />
|
]} />
|
||||||
</div>
|
</div>
|
||||||
{/* TODO: update createChallengeLink function */}
|
|
||||||
{/* <CopyButton>
|
|
||||||
{
|
|
||||||
({ copied, copy }) => <Button disabled onClick={copy} color={copied ? 'gray' : 'lime'}> {copied ? 'Copied' : 'Copy Link'} </Button>
|
|
||||||
}
|
|
||||||
</CopyButton> */}
|
|
||||||
</Modal>
|
</Modal>
|
||||||
<Card
|
<Card
|
||||||
maw={450} sx={{
|
maw={450} sx={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: '600px',
|
height: '600px',
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
backgroundColor:'#262523'
|
backgroundColor: '#262523'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Flex align="center" justify="center" gap="xs" my="lg">
|
<Flex align="center" justify="center" gap="xs" my="lg">
|
||||||
@@ -61,11 +43,11 @@ const PlayFriend = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const friends = [
|
// const friends = [
|
||||||
{ avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
// { avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
||||||
{ avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
// { avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
||||||
{ avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
// { avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
||||||
{ avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
// { avatar: <IconUserCircle />, username: "friend", rating: 100 },
|
||||||
]
|
// ]
|
||||||
|
|
||||||
export default PlayFriend
|
export default PlayFriend
|
||||||
@@ -1,20 +1,16 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { Button, Card, Flex, List, Stack, TextInput, Title } from '@mantine/core'
|
import { Button, Card, Flex, TextInput, Title } from '@mantine/core'
|
||||||
import { IconSearch } from '@tabler/icons-react'
|
import { IconSearch } from '@tabler/icons-react'
|
||||||
import { useForm } from '@mantine/form'
|
import { useForm } from '@mantine/form'
|
||||||
import { getAuthToken, getUserData } from '../../../utils/auth'
|
|
||||||
import FriendsList from '../../components/FriendsList'
|
import FriendsList from '../../components/FriendsList'
|
||||||
|
|
||||||
const Friends = () => {
|
const Friends = () => {
|
||||||
let { id: userid } = getUserData();
|
|
||||||
const form = useForm({ initialValues: { username: '' }, })
|
const form = useForm({ initialValues: { username: '' }, })
|
||||||
|
|
||||||
const addFriend = async () => {
|
const addFriend = async () => {
|
||||||
const response = await fetch(`${import.meta.env.VITE_BACKEND_HOST}/api/user/${userid}/friends/${form.values.username}`, {
|
const response = await fetch(`${import.meta.env.VITE_BACKEND_HOST}/api/user/friends/${form.values.username}`, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
credentials: 'include'
|
||||||
'Authorization': `Bearer ${getAuthToken()}`
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
const resData = await response.json();
|
const resData = await response.json();
|
||||||
if (resData.success === false) {
|
if (resData.success === false) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
import { Avatar, Button, Flex, Grid, Group, Loader, Stack, Text, TextInput, Title } from '@mantine/core'
|
import { Avatar, Button, Flex, Grid, Group, Stack, Text, TextInput, Title } from '@mantine/core'
|
||||||
import { getAuthToken, getUserData } from '../../../utils/auth'
|
import { getUserData } from '../../utils/auth'
|
||||||
import { UserDataContext } from '../../context/user-data-context'
|
import { UserDataContext } from '../../context/user-data-context'
|
||||||
import { useForm } from '@mantine/form'
|
import { useForm } from '@mantine/form'
|
||||||
import { Form } from 'react-router-dom'
|
import { Form } from 'react-router-dom'
|
||||||
@@ -83,9 +83,9 @@ export const action = async ({ request }) => {
|
|||||||
body: JSON.stringify(reqBody),
|
body: JSON.stringify(reqBody),
|
||||||
method: 'PATCH',
|
method: 'PATCH',
|
||||||
headers: {
|
headers: {
|
||||||
Authorization: `Bearer ${getAuthToken()}`,
|
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
}
|
},
|
||||||
|
credentials: 'include'
|
||||||
})
|
})
|
||||||
const resData = await response.json();
|
const resData = await response.json();
|
||||||
console.log(resData)
|
console.log(resData)
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
import { Box, Flex, NavLink, Title } from '@mantine/core'
|
import { Box, Flex, NavLink, Title } from '@mantine/core'
|
||||||
import { ColorWheelIcon, GearIcon, GlobeIcon, LockOpen1Icon, PersonIcon } from '@radix-ui/react-icons'
|
import { ColorWheelIcon, GearIcon, GlobeIcon, LockOpen1Icon, PersonIcon } from '@radix-ui/react-icons'
|
||||||
import React, { useState } from 'react'
|
import React from 'react'
|
||||||
import { Link, Outlet } from 'react-router-dom';
|
import { Link, Outlet } from 'react-router-dom';
|
||||||
|
|
||||||
const Settings = () => {
|
const Settings = () => {
|
||||||
const [active, setActive] = useState(null);
|
|
||||||
return (
|
return (
|
||||||
<Box ml='45px'>
|
<Box ml='45px'>
|
||||||
<Flex align="center" my="lg">
|
<Flex align="center" my="lg">
|
||||||
|
|||||||
Generated
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"name": "_chess_",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user