Compare commits

...

26 Commits

Author SHA1 Message Date
Lara REALI
cf0edf5bc0 Merge remote-tracking branch 'origin/apommier' into ereali 2023-06-24 20:18:46 +02:00
Lara REALI
92f3f496de Friend request css + change navbar Social+ button border qr butonn desactivate qr 2023-06-24 20:02:14 +02:00
Alexandre POMMIER
c6fe3a5a99 fix invite and match history not done 2023-06-24 19:39:16 +02:00
Alexandre POMMIER
38052b5034 fix invit 2023-06-24 18:19:41 +02:00
Alexandre POMMIER
fc280662b9 merge 2023-06-24 16:17:16 +02:00
Lara REALI
b04683576d merge apommier 2023-06-24 15:52:24 +02:00
Lara REALI
c011ea2b04 merge 2023-06-24 15:50:10 +02:00
Alexandre POMMIER
e44320a88f Merge remote-tracking branch 'origin/ereali' into apommier 2023-06-24 15:39:27 +02:00
Alexandre POMMIER
cf7c648813 before merge 2023-06-24 15:38:16 +02:00
Elisee ADJIGUIDI
a84b932355 merge 2023-06-24 15:14:08 +02:00
Elisee ADJIGUIDI
44fb3cdecd responsive pages/game nickname already Taken/Nickname too short 2023-06-24 14:35:50 +02:00
Lara REALI
6fd9660bff message sans decalage 2023-06-24 01:04:47 +02:00
Lara REALI
bdeb414c09 border message + responsive on profile 2023-06-24 00:51:36 +02:00
Alexandre POMMIER
071f30764a canvas background page, fix message mute, win loss in profile 2023-06-24 00:51:32 +02:00
Elisee ADJIGUIDI
de59d21671 change 2023-06-24 00:37:20 +02:00
Elisee ADJIGUIDI
6ad04baf06 merge 2023-06-23 20:32:35 +02:00
Alexandre POMMIER
d5e3532bd0 merge all all 2023-06-23 20:30:14 +02:00
Alexandre POMMIER
6d1cd933e2 Merge remote-tracking branch 'origin/ereali' into apommier 2023-06-23 20:21:36 +02:00
Alexandre POMMIER
b50d789d1d merge all syd 2023-06-23 20:20:10 +02:00
Alexandre POMMIER
c07a169794 fix mute ? fix socket fix infinite request profile, modify port 2023-06-23 19:59:23 +02:00
Elisee ADJIGUIDI
72a4f42cdb change design 2023-06-23 19:59:07 +02:00
Lara REALI
4d98765009 margin on leaderboard pic + auto input qr 2023-06-23 19:58:45 +02:00
Lara REALI
b27cb189b3 Qrcode number without arrows 2023-06-23 18:45:59 +02:00
Elisee ADJIGUIDI
0d42eda749 change 2023-06-23 15:38:58 +02:00
Little Dipper
f9a26e8e0f longeur messages et logueur modal nouveau message 2023-06-18 23:04:49 +02:00
Little Dipper
263e3332a1 js to ts 2023-06-18 21:22:25 +02:00
35 changed files with 599 additions and 345 deletions

11
.env
View File

@ -12,14 +12,9 @@
#URL #URL
NGINX_ENVSUBST_TEMPLATE_SUFFIX=".conf" NGINX_ENVSUBST_TEMPLATE_SUFFIX=".conf"
BASE_URL=bess-f2r2s16:8080
# BASE_URL=http://localhost REACT_APP_BASE_URL=bess-f2r2s16:8080
BASE_URL=localhost:8080 REDIRECT_URI=http://bess-f2r2s16:8080/api/auth/login
REACT_APP_BASE_URL=localhost:8080
REDIRECT_URI=http://localhost:8080/api/auth/login
#postgres var
# POSTGRES_HOST=127.0.0.1
# DB_TYPE=postgres
POSTGRES_HOST=postgresql POSTGRES_HOST=postgresql
POSTGRES_USER=postgres POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres POSTGRES_PASSWORD=postgres

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
#.env .env
containers/react/.env
backend/node_modules/ backend/node_modules/
containers/backend/dist/ containers/backend/dist/

View File

@ -1 +1 @@
ALTER USER postgres WITH PASSWORD 'pass'; ALTER USER postgres WITH PASSWORD 'postgres';

View File

@ -10,7 +10,7 @@ server {
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://react_app:8001; proxy_pass http://react_app:8081;
} }
location /api { location /api {
@ -21,7 +21,7 @@ server {
proxy_pass http://api:3000/api; proxy_pass http://api:3000/api;
} }
location /socket { location /socket.io {
# Forward requests to socket server running on port 4001 # Forward requests to socket server running on port 4001
if ($request_uri ~ ^/socket/4001) { if ($request_uri ~ ^/socket/4001) {
proxy_pass http://chat:4001; proxy_pass http://chat:4001;

View File

@ -6,7 +6,7 @@
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */ /* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/06/17 01:00:00 by apommier #+# #+# */ /* Created: 2023/06/17 01:00:00 by apommier #+# #+# */
/* Updated: 2023/06/21 01:19:01 by apommier ### ########.fr */ /* Updated: 2023/06/23 23:24:16 by apommier ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -180,6 +180,9 @@ export class AppController {
// let user = req.user // let user = req.user
// user.nickname = data.nickname // user.nickname = data.nickname
console.log(`user= ${req.user.username}`) console.log(`user= ${req.user.username}`)
const taken = await this.userService.findNickname(data.nickname)
if (taken)
return (0);
let user = await this.userService.findOne(req.user.username) let user = await this.userService.findOne(req.user.username)
user.nickname = data.nickname; user.nickname = data.nickname;
// return await this.userService.getFriends(req.user.username); // return await this.userService.getFriends(req.user.username);
@ -480,8 +483,6 @@ export class AppController {
// res.json(messages); // res.json(messages);
} }
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@Get('/conv') @Get('/conv')
async getConv(@Request() req) { async getConv(@Request() req) {
@ -588,7 +589,7 @@ export class AppController {
async muteUser(@Body() data: any) { async muteUser(@Body() data: any) {
if (!data.username) if (!data.username)
return ; return ;
return await this.chatService.muteUser(data.convId, data.username) return await this.chatService.muteUser(data.convId, data.username, data.time)
} }
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@ -598,11 +599,16 @@ export class AppController {
return await this.chatService.isAdmin(data.convId, req.user.username) return await this.chatService.isAdmin(data.convId, req.user.username)
} }
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)
@Post('/private') @Post('/private')
async setPrivate(@Body() data: any) { async setPrivate(@Body() data: any) {
return await this.chatService.setPrivate(data.convId) return await this.chatService.setPrivate(data.convId, true)
}
@UseGuards(JwtAuthGuard)
@Post('/public')
async setPublic(@Body() data: any) {
return await this.chatService.setPrivate(data.convId, false)
} }
@UseGuards(JwtAuthGuard) @UseGuards(JwtAuthGuard)

View File

@ -6,7 +6,7 @@
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */ /* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/06/17 01:00:25 by apommier #+# #+# */ /* Created: 2023/06/17 01:00:25 by apommier #+# #+# */
/* Updated: 2023/06/20 16:47:02 by apommier ### ########.fr */ /* Updated: 2023/06/24 18:47:59 by apommier ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -119,14 +119,22 @@ async verifyPassword(convId: number, password: string) {
// conv.password = password // conv.password = password
} }
async muteUser(convId: number, username: string) { async muteUser(convId: number, username: string, time: string) {
const conv = await this.findConv(convId); const conv = await this.findConv(convId);
console.log("MUTE USER");
conv.muted = conv.muted || []; conv.muted = conv.muted || [];
if (conv.muted.find(item => item === username)) if (conv.muted.find(item => item === username))
return (1); return (1);
conv.muted.push(username); conv.muted.push(username);
this.save(conv); this.save(conv);
setTimeout(() => {
conv.muted = conv.muted.filter((item) => item !== username)
this.save(conv);
}, 5000);
console.log("END MUTE USER");
} }
async setAdmin(convId: number, username: string) { async setAdmin(convId: number, username: string) {
@ -149,12 +157,14 @@ async isAdmin(convId: number, username: string) {
return (0); return (0);
} }
async setPrivate(convId: number) { async setPrivate(convId: number, bool: boolean) {
const conv = await this.findConv(convId); const conv = await this.findConv(convId);
if (conv.private === true) console.log("bool= ", bool);
conv.private = false; conv.private = bool;
else // if (conv.private === true)
conv.private = true; // conv.private = false;
// else
// conv.private = true;
this.save(conv); this.save(conv);
} }

View File

@ -3,10 +3,10 @@
/* ::: :::::::: */ /* ::: :::::::: */
/* config.service.ts :+: :+: :+: */ /* config.service.ts :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */ /* By: sadjigui <sadjigui@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/04/09 14:53:49 by apommier #+# #+# */ /* Created: 2023/04/09 14:53:49 by apommier #+# #+# */
/* Updated: 2023/06/22 20:42:32 by apommier ### ########.fr */ /* Updated: 2023/06/24 15:09:20 by sadjigui ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */

View File

@ -82,7 +82,7 @@ export class User {
} }
@Entity() @Entity({name: 'MatchLog' })
export class MatchLog { export class MatchLog {
@PrimaryGeneratedColumn() @PrimaryGeneratedColumn()
id: number; id: number;

View File

@ -6,7 +6,7 @@
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */ /* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/06/17 01:00:07 by apommier #+# #+# */ /* Created: 2023/06/17 01:00:07 by apommier #+# #+# */
/* Updated: 2023/06/21 01:31:44 by apommier ### ########.fr */ /* Updated: 2023/06/24 19:29:33 by apommier ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -41,6 +41,10 @@ export class UsersService {
return await this.userRepository.findOneBy({username: username}); return await this.userRepository.findOneBy({username: username});
} }
async findNickname(username: string): Promise<User> {
return await this.userRepository.findOneBy({nickname: username});
}
async save(user: User): Promise<User> { async save(user: User): Promise<User> {
return await this.userRepository.save(user); return await this.userRepository.save(user);
} }
@ -71,6 +75,8 @@ export class UsersService {
user.friendRequest = user.friendRequest || []; user.friendRequest = user.friendRequest || [];
if (user.friendRequest.find(item => item === username)) if (user.friendRequest.find(item => item === username))
return (1); return (1);
if (user.friends.find(item => item === username))
return (1);
user.friendRequest.push(username); user.friendRequest.push(username);
this.save(user); this.save(user);
return (1); return (1);
@ -96,16 +102,24 @@ export class UsersService {
async getHistory(username: string) { async getHistory(username: string) {
const user = await this.findOne(username); const user = await this.findOne(username);
if (user) { if (user)
const children = user.children; {
console.log(user);
console.log(user.children); // or perform any operations with the children // const ret = await this.matchRepository.query("SELECT * FROM \"MatchLog\" WHERE id = ($1);", [user.id]);
return children; const ret = await this.matchRepository.query("SELECT * FROM \"MatchLog\"");
console.log("all match= ", ret);
} }
// const children = user.children;
// console.log(user);
// console.log(user.children); // or perform any operations with the children
// return children;
// }
} }
async addFriend(user: User, username: string) { async addFriend(user: User, username: string) {
if (!(await this.findOne(username))) const user2 = await this.findOne(username)
if (!user)
return (0); return (0);
// user.friendRequest = user.friendRequest || []; // user.friendRequest = user.friendRequest || [];
user.friends = user.friends || []; user.friends = user.friends || [];
@ -117,6 +131,9 @@ export class UsersService {
} }
user.friends.push(username); user.friends.push(username);
user.friendRequest = user.friendRequest.filter((item) => item !== username); user.friendRequest = user.friendRequest.filter((item) => item !== username);
user2.friends = user2.friends || [];
user2.friends.push(user.username);
this.save(user2);
this.save(user); this.save(user);
return (1); return (1);
} }

View File

@ -6,10 +6,12 @@
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */ /* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/06/19 15:18:38 by apommier #+# #+# */ /* Created: 2023/06/19 15:18:38 by apommier #+# #+# */
/* Updated: 2023/06/23 15:19:12 by apommier ### ########.fr */ /* Updated: 2023/06/24 17:20:24 by apommier ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
//0.0001
import { SubscribeMessage, WebSocketGateway, OnGatewayInit, WebSocketServer, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets'; import { SubscribeMessage, WebSocketGateway, OnGatewayInit, WebSocketServer, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
import { Server, Socket } from 'socket.io'; import { Server, Socket } from 'socket.io';
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
@ -165,8 +167,9 @@ addMatchmaking(client: Socket, payload: any): void {
player.join(gameId); player.join(gameId);
console.log(`Player ${player.id} joined game ${gameId}`); console.log(`Player ${player.id} joined game ${gameId}`);
}); });
payload.gameId = gameId;
players.forEach((player) => { players.forEach((player) => {
player.emit('pong:gameId', gameId); player.emit('pong:gameId', payload);
}); });
} }
@ -200,8 +203,8 @@ joinPrivateParty(client: Socket, payload: any): void {
{ {
game.push(client); game.push(client);
const playersIds = game.map(socket => socket.id); const playersIds = game.map(socket => socket.id);
this.clients[playersIds[0]].emit('pong:gameId', payload.gameId); this.clients[playersIds[0]].emit('pong:gameId', payload);
this.clients[playersIds[1]].emit('pong:gameId', payload.gameId); this.clients[playersIds[1]].emit('pong:gameId', payload);
} }
else else
{ {
@ -337,6 +340,24 @@ addPrivateParty(client: Socket, payload: any): void {
} }
} }
@SubscribeMessage('pong:myPoint')
handleMyPoint(client: Socket, payload: any): void
{
const game = this.games.get(payload.gameId);
const playersIds = game.map(socket => socket.id);
console.log(`id of 0 mypoint= ${playersIds[0]}`);
if (playersIds[0] === payload.id)
{
this.clients[playersIds[1]].emit('pong:hisPoint', payload);
}
else if (playersIds[1] === payload.id)
{
this.clients[playersIds[0]].emit('pong:hisPoint', payload);
}
}
@SubscribeMessage('pong:name') @SubscribeMessage('pong:name')
getName(client: Socket, payload: any): void getName(client: Socket, payload: any): void
{ {
@ -347,11 +368,11 @@ addPrivateParty(client: Socket, payload: any): void {
if (playersIds[0] === payload.id) if (playersIds[0] === payload.id)
{ {
this.clients[playersIds[1]].emit('pong:name', payload.name); this.clients[playersIds[1]].emit('pong:name', payload);
} }
if (playersIds[1] === payload.id) if (playersIds[1] === payload.id)
{ {
this.clients[playersIds[0]].emit('pong:name', payload.name); this.clients[playersIds[0]].emit('pong:name', payload);
} }
} }

View File

@ -1,5 +1,7 @@
REACT_APP_BASE_URL=localhost:8080 REACT_APP_BASE_URL=bess-f2r2s16:8080
REACT_APP_SOCKET_URL=bess-f2r2s16
REACT_APP_API_SECRET=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 REACT_APP_API_SECRET=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
REACT_APP_CLIENT_UID=u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41 REACT_APP_CLIENT_UID=u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41
# REACT_APP_BASE_URL=92.143.191.152 # REACT_APP_BASE_URL=92.143.191.152
# REACT_APP_BASE_URL=192.168.1.19 # REACT_APP_BASE_URL=192.168.1.19

View File

@ -22,7 +22,7 @@
"web-vitals": "^2.1.4" "web-vitals": "^2.1.4"
}, },
"scripts": { "scripts": {
"start": "HOST=0.0.0.0 PORT=8001 react-scripts start", "start": "HOST=0.0.0.0 PORT=8081 react-scripts start",
"start:dev": "npm run start --watch", "start:dev": "npm run start --watch",
"build": "react-scripts build", "build": "react-scripts build",
"test": "react-scripts test", "test": "react-scripts test",

View File

@ -40,9 +40,9 @@ function PlayButton() {
<button onClick={handleButtonClick} className="playButton">Play</button> <button onClick={handleButtonClick} className="playButton">Play</button>
{/* !buttonClicked && <button onClick={handleButtonClick}>Draw on Canvas</button> */} {/* !buttonClicked && <button onClick={handleButtonClick}>Draw on Canvas</button> */}
<div className='checkbox'> <div className='checkbox'>
<p><input type="checkbox" value="superpower"/> Super Power </p> <p><input className="inside_checkbox" type="checkbox" value="superpower"/> Super Power </p>
<p><input type="checkbox" value="obstacle"/> Obstacle </p> <p><input className="inside_checkbox" type="checkbox" value="obstacle"/> Obstacle </p>
<p><input type="checkbox" value="speed"/> Faster and Faster </p> <p><input className="inside_checkbox" type="checkbox" value="speed"/> Faster and Faster </p>
</div> </div>
</div> </div>
); );

View File

@ -6,7 +6,7 @@
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */ /* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/06/09 08:49:24 by apommier #+# #+# */ /* Created: 2023/06/09 08:49:24 by apommier #+# #+# */
/* Updated: 2023/06/20 13:06:35 by apommier ### ########.fr */ /* Updated: 2023/06/23 17:16:40 by apommier ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -41,7 +41,7 @@ function Rank({user, index}: RankProps){
}; };
fetchProfilePicture(); fetchProfilePicture();
}) }, [])
// console.log(index); // console.log(index);
return ( return (

View File

@ -21,18 +21,15 @@ function Ranking(){
// setFriends(tmpFriends.data); // setFriends(tmpFriends.data);
// return tmpUser; // return tmpUser;
// console.log(`user= ${tmpUser.data.username}`); // console.log(`user= ${tmpUser.data.username}`);
setIsLoading(false) setIsLoading(false);
} }
catch(err){ catch(err){
console.log(err); console.log(err);
} }
}; };
getRanking(); getRanking();
}, []);
}, []) console.log(`ranking after= ${ranking}`);
console.log(`ranking after= ${ranking}`)
return ( return (
<div> <div>

View File

@ -27,6 +27,7 @@ import PartyInvite from "./PartyInvite.tsx";
// import {User, Conv, Message} from "../../../interfaces.tsx" // import {User, Conv, Message} from "../../../interfaces.tsx"
import {User, Conv} from "../../../interfaces.tsx" import {User, Conv} from "../../../interfaces.tsx"
import { IoLogoOctocat } from "react-icons/io5";
const TouchDiv = styled.div` const TouchDiv = styled.div`
margin-left: 10px; margin-left: 10px;
@ -119,7 +120,7 @@ function Chats(){
setUsers(tmpUsers.data); setUsers(tmpUsers.data);
// console.log(`connection....`); // console.log(`connection....`);
socket.current = io('http://' + process.env.REACT_APP_BASE_URL + ':4001', { transports: ['polling'] }); socket.current = io('http://' + process.env.REACT_APP_SOCKET_URL + ':4001', { transports: ['polling'] });
// console.log(`connection done`); // console.log(`connection done`);
socket.current.emit('connection', {username: tmpUser.data.username}) socket.current.emit('connection', {username: tmpUser.data.username})
socket.current.on('message', (data) => { //data should be a message ?) socket.current.on('message', (data) => { //data should be a message ?)
@ -205,11 +206,12 @@ function Chats(){
getMessage(); getMessage();
}, [currentChat]); }, [currentChat]);
const handleSubmit = async (e: { preventDefault: () => void; })=>{ const handleSubmit = async (e: { key?: any; preventDefault: any; })=>{
e.preventDefault(); e.preventDefault();
// console.log(`e= ${e.key}`) // console.log(`e= ${e.key}`)
// console.log(`name= ${user.username}`) // console.log(`name= ${user.username}`)
// let message; // let message;
console.log("in handle");
if (!user || !currentChat) if (!user || !currentChat)
return ; return ;
const message = { const message = {
@ -242,33 +244,11 @@ function Chats(){
} }
} }
const handleKeyPress = async (e: { key: string; })=> { const handleKeyPress = async (e: { key?: any; preventDefault: () => void; })=> {
// console.log(`e in press= ${e.key}`) // console.log(`e in press= ${e.key}`)
if (e.key !== "Enter") if (e.key !== "Enter")
return ; return ;
// console.log(`name= ${user.username}`) handleSubmit(e);
if (!user || !currentChat)
return ;
const message = {
sender: user.username,
text: newMessages,
convId: currentChat.id,
members: null,
id: null,
};
try{
const res = await api.post('/message', message);
const convMember = await api.post('/member', message);
message.members = convMember.data.members;
message.id = res.data.id
setMessage([...messages, res.data]);
setNewMessage("");
if (socket.current)
socket.current.emit('sendMessage', message);
}
catch(err){
console.log(err)
}
} }
@ -323,6 +303,7 @@ function Chats(){
const handleAddFriend = async () => { const handleAddFriend = async () => {
try{ try{
console.log("friend= ", friend);
const res = await api.post("/invite", {username: friend}) const res = await api.post("/invite", {username: friend})
// if (res.data === 1) // if (res.data === 1)
// console.log("res in friend= ", res) // console.log("res in friend= ", res)
@ -371,6 +352,7 @@ function Chats(){
const handleOptionChange = (selectId: number, selectedOption: string) => { const handleOptionChange = (selectId: number, selectedOption: string) => {
console.log("selected Option=", selectedOption) console.log("selected Option=", selectedOption)
setFriend(selectedOption);
setSelectTag((prevTags) => setSelectTag((prevTags) =>
prevTags.map((tag) => prevTags.map((tag) =>
tag.id === selectId ? { ...tag, selectedOption } : tag tag.id === selectId ? { ...tag, selectedOption } : tag
@ -389,12 +371,13 @@ function Chats(){
<div className="chat"> <div className="chat">
<div className='navbar'> <div className='navbar'>
<img src={DefaultPic} alt="profile" className="pic"/> {/* <img src={DefaultPic} alt="profile" className="pic"/> */}
<IoLogoOctocat className="catchat"/>
<span> <span>
{isLoading || !user ? ( {isLoading || !user ? (
<h4>Loading...</h4> <h4>Loading...</h4>
) : ( ) : (
<h4>{user.nickname}</h4> <h2>Chat</h2>
)} )}
</span> </span>
{/* <div className="end"> {/* <div className="end">
@ -463,7 +446,7 @@ function Chats(){
))} ))}
<TouchDiv> <TouchDiv>
<motion.div onClick={handleAddFriend}> <motion.div onClick={handleAddFriend}>
<MdOutlineGroupAdd /> <MdOutlineGroupAdd className="catchat"/>
</motion.div> </motion.div>
<AnimatePresence initial={false} onExitComplete={() => null}> <AnimatePresence initial={false} onExitComplete={() => null}>
{showAddFriendAlert && addFriend && ( {showAddFriendAlert && addFriend && (
@ -476,7 +459,7 @@ function Chats(){
</TouchDiv> </TouchDiv>
<TouchDiv> <TouchDiv>
<motion.div onClick={handleBlockFriend}> <motion.div onClick={handleBlockFriend}>
<ImBlocked /> <ImBlocked className="block"/>
</motion.div> </motion.div>
<AnimatePresence initial={false} onExitComplete={() => null}> <AnimatePresence initial={false} onExitComplete={() => null}>
{showBlockAlert && block && ( {showBlockAlert && block && (

View File

@ -6,7 +6,7 @@
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */ /* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/06/01 18:24:46 by apommier #+# #+# */ /* Created: 2023/06/01 18:24:46 by apommier #+# #+# */
/* Updated: 2023/06/20 19:05:10 by apommier ### ########.fr */ /* Updated: 2023/06/24 16:00:48 by apommier ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -42,15 +42,16 @@ function MessageMe({message, own}: MessageMeProps){
const [user, setUser] = useState<User>(); const [user, setUser] = useState<User>();
const scrollRef = useRef<HTMLDivElement>(null); const scrollRef = useRef<HTMLDivElement>(null);
// console.log("Message eher")
useEffect(() => { useEffect(() => {
if (scrollRef.current) if (scrollRef.current)
{ {
scrollRef.current.scrollIntoView({ behavior: "smooth",}) scrollRef.current.scrollIntoView({ behavior: "smooth"});
} }})
useEffect(() => {
const fetchProfilePicture = async () => { const fetchProfilePicture = async () => {
try { try {
console.log("useEffect message")
// const user = await api.get("/profile"); // const user = await api.get("/profile");
const tmpSender = await api.post("/user", {username: message.sender}) const tmpSender = await api.post("/user", {username: message.sender})
const tmpConv = await api.post("/convId", {convId: message.convId}) const tmpConv = await api.post("/convId", {convId: message.convId})
@ -81,23 +82,37 @@ function MessageMe({message, own}: MessageMeProps){
window.location.reload(); window.location.reload();
}; };
// const isAllowed = async () => {
// const ret = await api.post("/allowed", {convId: message.convId});
// return ret.data;
// }
if (!user || !sender || !conv) if (!user || !sender || !conv)
{
// console.log("return")
return (<></>); return (<></>);
}
// console.log("result includes=", conv.banned.includes(user.username)) // console.log("result includes=", conv.banned.includes(user.username))
// console.log("result includes=", conv.blocked.includes(user.username)) // console.log("result includes=", conv.blocked.includes(user.username))
// const conv2: Conv = getConv();
// if (!conv)
// isAllowed().then((ret: number) => {
// if (!ret)
// {
// console.log("return not allowed");
// return ;
// }
// // Use the resolved currentConv here
// });
if (user.blocked && user.blocked.includes(message.sender)) if (user.blocked && user.blocked.includes(message.sender))
return (<></>); return (<></>);
// else if (conv.banned && conv.banned.includes(user.username)) else if (conv.banned && conv.banned.includes(user.username))
// { return (<></>);
// console.log("return2") else if (conv.muted && conv.muted.includes(user.username))
// return (<></>); {
// } // console.log("muted00")
// console.log("noy return") return (<></>);
}
// if (user.blocked.includes(message.sender))/ // if (user.blocked.includes(message.sender))/
console.log("no return message good");
return ( return (
<div className={own ? "meMessage" : "youMessage"} ref={scrollRef}> <div className={own ? "meMessage" : "youMessage"} ref={scrollRef}>
<div> <div>

View File

@ -7,6 +7,7 @@ import { GrAdd } from "react-icons/gr";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import api from "../../script/axiosApi.tsx"; import api from "../../script/axiosApi.tsx";
import React from "react"; import React from "react";
import {User, Conv} from "../../../interfaces.tsx"
const dropIn = { const dropIn = {
hidden:{y:"-100vh", hidden:{y:"-100vh",
@ -21,16 +22,19 @@ const dropIn = {
}}, }},
exit:{y: "100vh", exit:{y: "100vh",
opacity: 0,}, opacity: 0,},
}; };
const Modal = ({handleClose}) => { interface ModalProps {
handleClose: Function,
}
const Modal = ({handleClose}: ModalProps) => {
// const [multi, setMulti] = useState(false); // const [multi, setMulti] = useState(false);
const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]); const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]);
const [selectedOptionArray, setSelectedOptionArray] = useState([]); const [selectedOptionArray, setSelectedOptionArray] = useState<string[]>([]);
const [users, setUsers] = useState([]); const [users, setUsers] = useState<User[]>([]);
const [user, setUser] = useState(); const [user, setUser] = useState<User>();
const [convs, setConvs] = useState([]); const [convs, setConvs] = useState<Conv[]>([]);
const [channel, setChannel] = useState(''); const [channel, setChannel] = useState('');
@ -53,7 +57,7 @@ const Modal = ({handleClose}) => {
getConv(); getConv();
}, []); }, []);
const handleOptionChange = (selectId, selectedOption) => { const handleOptionChange = (selectId: number, selectedOption: string) => {
console.log("selected Option=", selectedOption) console.log("selected Option=", selectedOption)
setSelectTag((prevTags) => setSelectTag((prevTags) =>
prevTags.map((tag) => prevTags.map((tag) =>
@ -103,12 +107,15 @@ const Modal = ({handleClose}) => {
<Backdrop onClick={handleClose}> <Backdrop onClick={handleClose}>
<motion.div <motion.div
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
className="modal" className="modalSetting"
// variant={dropIn} // variant={dropIn}
initial="hidden" initial="hidden"
animate="visible" animate="visible"
exit="exit" exit="exit"
> >
{/* <p>New Conversation</p> */}
<div className="settingFirstPart2">
{selectTags.map((selectTag) => ( {selectTags.map((selectTag) => (
<div key={selectTag.id}> <div key={selectTag.id}>
<select <select
@ -118,9 +125,9 @@ const Modal = ({handleClose}) => {
<option value="">{ <option value="">{
selectTag.selectedOption ? selectTag.selectedOption : "Select an option" selectTag.selectedOption ? selectTag.selectedOption : "Select an option"
}</option> }</option>
{users.filter((item) => !selectTags.some((tag) => tag.selectedOption === item.name)).map((item, index) => ( {users.filter((item) => !selectTags.some((tag) => tag.selectedOption === item.nickname)).map((item, index) => (
<option key={index} value={item.username}> <option key={index} value={item.username}>
{item.username} {item.nickname}
</option> </option>
))} ))}
</select> </select>
@ -132,10 +139,12 @@ const Modal = ({handleClose}) => {
<div className="div_submit"> <div className="div_submit">
<Link to='#' className="submit" onClick={ saveSelectedOptions}>Submit</Link> <Link to='#' className="submit" onClick={ saveSelectedOptions}>Submit</Link>
<Link to="#" className="submit" onClick={handleClose}>Cancel</Link> <Link to="#" className="submit" onClick={() => handleClose}>Cancel</Link>
</div>
</div> </div>
<div className="settingSecondPart">
{convs.length > 0 && ( {convs.length > 0 && (
<select <select
@ -145,7 +154,7 @@ const Modal = ({handleClose}) => {
> >
<option value="">Select an option</option> <option value="">Select an option</option>
{convs.map((conv) => ( {convs.map((conv) => (
!(!conv.group || conv.private || (conv.banned && conv.banned.includes(user.username)) || (conv.members && conv.members.includes(user.username))) && ( !(!conv.group || conv.private || (conv.banned && user && conv.banned.includes(user.username)) || (conv.members && user && conv.members.includes(user.username))) && (
<option key={conv.id} value={conv.id}> <option key={conv.id} value={conv.id}>
{conv.name} {conv.name}
</option> </option>
@ -153,9 +162,9 @@ const Modal = ({handleClose}) => {
))} ))}
</select> </select>
)} )}
{channel.private ? ( {/* {channel.private ? (
<input className="mdp" placeholder="password" type="text" /> <input className="mdp" placeholder="passdddddword" type="text" />
):("")} ):("")} */}
<div className="div_submit"> <div className="div_submit">
@ -164,6 +173,7 @@ const Modal = ({handleClose}) => {
</div>
</motion.div> </motion.div>
</Backdrop> </Backdrop>
) )

View File

@ -39,8 +39,10 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]); const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]);
const [selectedUser, setSelectedUser] = useState(""); const [selectedUser, setSelectedUser] = useState("");
const [newName, setNewName] = useState(""); const [newName, setNewName] = useState("");
const [time, setTime] = useState("");
const [newPassword, setNewPassword] = useState(""); const [newPassword, setNewPassword] = useState("");
const [privateConv, setPrivateConv] = useState(false); const [privateConv, setPrivateConv] = useState<Boolean>();
const [loading, setLoading] = useState<Boolean>(true);
const dark = () => setPrivateConv(true); const dark = () => setPrivateConv(true);
const light = () => setPrivateConv(false); const light = () => setPrivateConv(false);
const [mute, setMute] = useState(false); const [mute, setMute] = useState(false);
@ -53,9 +55,15 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
console.log("convid =", convId) console.log("convid =", convId)
const getUsers = async ()=>{ const getUsers = async ()=>{
try { try {
const currentConv = await api.post("/convId", {convId: convId});
// console.log("conv private =================== ", )
if (currentConv.data.private)
setPrivateConv(true);
const tmpUsers = await api.get("/users"); const tmpUsers = await api.get("/users");
console.log("users=", tmpUsers.data); console.log("users=", tmpUsers.data);
setUsers(tmpUsers.data); setUsers(tmpUsers.data);
setLoading(false);
} catch(err){ } catch(err){
console.log(err) console.log(err)
} }
@ -63,6 +71,31 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
getUsers(); getUsers();
}, []); }, []);
useEffect(() => {
// Function to run when myVariable changes
const handleVariableChange = () => {
console.log('Variable changed:', privateConv);
if (privateConv === undefined)
{
console.log("return")
return ;
}
try {
if (privateConv)
api.post("/private", {convId: convId})
else
api.post("/public", {convId: convId})
} catch (err){
console.log(err);
}
};
if (!loading)
handleVariableChange();
// return () => {
// handleVariableChange();
// };
}, [privateConv]);
// const [multi, setMulti] = useState(false); // const [multi, setMulti] = useState(false);
// const [selectedOptionArray, setSelectedOptionArray] = useState([]); // const [selectedOptionArray, setSelectedOptionArray] = useState([]);
@ -80,30 +113,30 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
const handleCheckPass = (e: { target: { checked: boolean | ((prevState: boolean) => boolean); }; }) => { const handleCheckPass = (e: { target: { checked: boolean | ((prevState: boolean) => boolean); }; }) => {
setPassword(e.target.checked); setPassword(e.target.checked);
console.log("password??", e.target.checked) console.log("password??", e.target.checked);
} }
const handleCheckPriv = (e: { target: { checked: any; }; }) => { // const handleCheckPriv = (e: { target: { checked: any; }; }) => {
// setPassword(e.target.checked); // // setPassword(e.target.checked);
if (e.target.checked) // if (e.target.checked)
{ // {
console.log("chack true", e.target.checked) // console.log("chack true", e.target.checked)
try{ // try{
api.post("/private", {convId: convId}) // api.post("/private", {convId: convId})
} catch(err) { // } catch(err) {
console.log(err); // console.log(err);
} // }
} // }
else // else
{ // {
console.log("chack false", e.target.checked) // console.log("chack false", e.target.checked)
try{ // try{
api.post("/private", {convId: convId}) // api.post("/private", {convId: convId})
} catch(err) { // } catch(err) {
console.log(err); // console.log(err);
} // }
} // }
} // }
const handleName = async (e: { key: string; })=>{ const handleName = async (e: { key: string; })=>{
if (e.key !== "Enter") if (e.key !== "Enter")
@ -157,11 +190,15 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
handleClose(); handleClose();
}; };
const handleMute = async () => { const handleMute = async (e: { key: string; }) => {
if (!selectedUser.length) console.log(`e in press= ${e.key}`)
if (e.key != "Enter")
return ; return ;
// console.log("value mute = ", e.target.value);
console.log("value mute = ", time);
try{ try{
await api.post("/mute", {convId: convId, username: selectedUser}) await api.post("/mute", {convId: convId, username: selectedUser, time: time})
} catch(err) { } catch(err) {
console.log(err); console.log(err);
} }
@ -177,6 +214,17 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
handleClose(); handleClose();
}; };
const handleKeyPress = async (e: { key: string; })=> {
if (e.key !== "Enter")
return ;
try{
}
catch(err){
}
}
return ( return (
<Backdrop onClick={handleClose}> <Backdrop onClick={handleClose}>
<motion.div <motion.div
@ -198,7 +246,7 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
<p className="checkbox">Password<input type="checkbox" value="password" checked={password} onChange={handleCheckPass}/> </p> <p className="checkbox">Password<input type="checkbox" value="password" checked={password} onChange={handleCheckPass}/> </p>
{password || privateConv ? ( {password ? (
<input <input
onChange={(e) => setNewPassword(e.target.value)} onChange={(e) => setNewPassword(e.target.value)}
onKeyDown={handlePassword} onKeyDown={handlePassword}
@ -208,7 +256,6 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
): ):
("")} ("")}
</div> </div>
<div className="forName"> <div className="forName">
<input <input
@ -254,7 +301,14 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
</div> </div>
{mute ? ( {mute ? (
<input type="text" className="in_howLong" placeholder="How long ?" /> <input
onKeyDown={handleMute}
type="number"
className="in_howLong"
placeholder="How long ?"
value={time}
onChange={(e) => setTime(e.target.value)}
/>
):("")} ):("")}
</motion.div> </motion.div>

View File

@ -1,12 +1,13 @@
import {motion} from "framer-motion" import { AnimatePresence, motion } from "framer-motion"
// import Backdrop from "../Sidebar/Backdrop" // import Backdrop from "../Sidebar/Backdrop"
import {Link} from 'react-router-dom'; import { Link } from 'react-router-dom';
import { UserProfile } from "../../DataBase/DataUserProfile"; // import { UserProfile } from "../../DataBase/DataUserProfile";
import {useState} from 'react'; import { useState } from 'react';
import "../../styles/Profile.css" import "../../styles/Profile.css"
import api from '../../script/axiosApi.tsx'; import api from '../../script/axiosApi.tsx';
import React from "react"; import React from "react";
import RedAlert from "../Alert/RedAlert.tsx";
const dropIn = { const dropIn = {
hidden: { hidden: {
@ -26,37 +27,55 @@ const dropIn = {
// ) // )
// } // }
const ModalEdit = ( handleClose ) => { const ModalEdit = (handleClose) => {
// let new_name = ""; // let new_name = "";
const [nickname, setNickname] = useState(""); const [nickname, setNickname] = useState("");
const [errTaken, setErrTaken] = useState(false);
const closeTaken = () => setErrTaken(false);
const [errTooShort, setErrTooShort] = useState(false);
const closeTooShort = () => setErrTooShort(false);
const handler = e => const handler = e => {
{
setNickname(e.target.value); setNickname(e.target.value);
console.log("testeeeee") console.log("testeeeee")
const postNickname = async ()=>{ const postNickname = async () => {
try{ // try{
await api.post("/nickname", {nickname: nickname}) // await api.post("/nickname", {nickname: nickname})
// setUser(tmpUser.data); // // setUser(tmpUser.data);
// setIsLoading(false) // // setIsLoading(false)
} // }
catch(err){ // catch(err){
console.log(err); // console.log(err);
} // }
}; };
postNickname(); postNickname();
} }
const handlePostNickname = async () => const handlePostNickname = async () => {
{ console.log("nickname=", nickname)
console.log("nickname=" ,nickname) try {
try{ const ret = await api.post("/nickname", { nickname: nickname });
await api.post("/nickname", {nickname: nickname}) // console.log("cest ici = ",ret);
// if (!ret)
console.log("test ret =", ret.data);
if (nickname.length < 3) {
setErrTooShort(true);
}
else if (ret.data) {
console.log("ici error = ", ret.data);
window.location.reload(); window.location.reload();
}
else {
console.log("nickname already set = ", ret.data);
setErrTaken(true);
}
// setUser(tmpUser.data); // setUser(tmpUser.data);
// setIsLoading(false) // setIsLoading(false)
} }
catch(err){ catch (err) {
console.log(err); console.log(err);
} }
} }
@ -73,16 +92,27 @@ const ModalEdit = ( handleClose ) => {
animate="visible" animate="visible"
exit="exit"> exit="exit">
<h2>Type your new name</h2> <h2>Type your new name</h2>
<input className="text" maxLength="10" type="text" value={nickname} onChange={handler} handleClose/> <input className="text" minLength={2} maxLength={10} type="text" value={nickname} onChange={handler} />
<div> <div>
<div className="button" onClick={ () => handlePostNickname()}> <div className="button" onClick={handlePostNickname}>
change change
{/* <Link className="button" to={""}>change</Link> */} {/* <Link className="button" to={""}>change</Link> */}
</div> </div>
<AnimatePresence initial={false} onExitComplete={() => null}>
{
errTaken ? (
<RedAlert handleClose={closeTaken} text="Error: Nickname already taken" />
) : ("")
}
{
errTooShort ? (
<RedAlert handleClose={closeTooShort} text="Error: Nickname it too short" />
) : ("")
}
</AnimatePresence>
</div> </div>
</motion.div> </motion.div>
) )
} }

View File

@ -94,7 +94,7 @@ function WinLoss() {
// <span>Loading...</span> // <span>Loading...</span>
) : ( ) : (
<div className='scroll'> <div className='scroll'>
<h2 className='title'>Match history Win/Loss</h2> <h2 className='title'>Match history {user.win}/{user.loss}</h2>
{history.map((c: Matchlog, index) => { {history.map((c: Matchlog, index) => {
return ( return (
<div key={index} className='elements'> <div key={index} className='elements'>

View File

@ -6,7 +6,7 @@
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */ /* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/06/09 08:18:58 by apommier #+# #+# */ /* Created: 2023/06/09 08:18:58 by apommier #+# #+# */
/* Updated: 2023/06/20 13:41:44 by apommier ### ########.fr */ /* Updated: 2023/06/23 17:12:07 by apommier ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -59,9 +59,8 @@ export default function Friend({currentUser}: UserProps)
console.error('Error fetching profile picture:', error); console.error('Error fetching profile picture:', error);
} }
}; };
fetchProfilePicture(); fetchProfilePicture();
}) }, []);
function getStatus(friend: User) function getStatus(friend: User)
{ {

View File

@ -15,7 +15,7 @@ const UserChat = styled.div `
gap: 5px; gap: 5px;
color: white; color: white;
cursor: pointer; cursor: pointer;
margin-top: 10px;
&:hover{ &:hover{
background-color: #3e3c61; background-color: #3e3c61;
} }
@ -101,13 +101,14 @@ export default function Friend({currentUser}: UserProps)
<img className="pic-user" src={DefaultPicture} alt="Default Profile Picture" /> <img className="pic-user" src={DefaultPicture} alt="Default Profile Picture" />
)} )}
{request ? ( {request ? (
<div className="infoSideBar"> <div className="end">
<span onClick={() => handleButtonClick(currentUser)}>{currentUser.nickname}</span> <span onClick={() => handleButtonClick(currentUser)}>{currentUser.nickname}</span>
<RxCheckCircled onClick={() => Accept(request)} color={'green'}/> <div className="end">
<RxCircleBackslash onClick={() => Refuse(request)} color={'red'}/> <RxCheckCircled className="friendRequest" onClick={() => Accept(request)} color={'green'}/>
<RxCircleBackslash className="friendRequest" onClick={() => Refuse(request)} color={'red'}/>
</div>
</div> </div>
) : ( "" )} ) : ( "" )}
</UserChat> </UserChat>
) )
} }

View File

@ -7,6 +7,7 @@ import styled from "styled-components";
import Friend from './Friend.tsx'; import Friend from './Friend.tsx';
import FriendRequest from './FriendRequest.tsx'; import FriendRequest from './FriendRequest.tsx';
import {IoMdPeople} from 'react-icons/io'
import { ImBlocked } from 'react-icons/im'; import { ImBlocked } from 'react-icons/im';
import { MdOutlineGroupAdd } from 'react-icons/md'; import { MdOutlineGroupAdd } from 'react-icons/md';
import {User} from "../../../interfaces.tsx" import {User} from "../../../interfaces.tsx"
@ -88,26 +89,15 @@ function Social (){
<div> <div>
<div className='navbar'> <div className='navbar'>
{/* <img src={DefaultPic} alt="profile" className="pic"/> */} {/* <img src={DefaultPic} alt="profile" className="pic"/> */}
{profilePicture ? ( <IoMdPeople className="catchat"/>
<img className="pic" src={`data:image/jpeg;base64,${profilePicture}`} />
) : (
<img className="pic" src={DefaultPicture} alt="Default Profile Picture" />
)}
<span> <span>
{isLoading || !user ? ( {isLoading || !user ? (
<h4>Loading...</h4> <h4>Loading...</h4>
) : ( ) : (
<h4>{user.nickname}</h4> <h2>Social</h2>
)} )}
</span> </span>
<div className="end">
<TouchDiv>
<MdOutlineGroupAdd/>
</TouchDiv>
<TouchDiv>
<ImBlocked/>
</TouchDiv>
</div>
</div> </div>
{/* map with fiend request */} {/* map with fiend request */}
@ -119,6 +109,7 @@ function Social (){
{friends.map(c=> ( {friends.map(c=> (
<Friend currentUser={c}/> <Friend currentUser={c}/>
))} ))}
</div> </div>
) )
} }

View File

@ -3,10 +3,10 @@
/* ::: :::::::: */ /* ::: :::::::: */
/* Home.tsx :+: :+: :+: */ /* Home.tsx :+: :+: :+: */
/* +:+ +:+ +:+ */ /* +:+ +:+ +:+ */
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */ /* By: sadjigui <sadjigui@student.42.fr> +#+ +:+ +#+ */
/* +#+#+#+#+#+ +#+ */ /* +#+#+#+#+#+ +#+ */
/* Created: 2023/06/09 08:19:04 by apommier #+# #+# */ /* Created: 2023/06/09 08:19:04 by apommier #+# #+# */
/* Updated: 2023/06/23 15:58:14 by apommier ### ########.fr */ /* Updated: 2023/06/23 22:11:28 by apommier ### ########.fr */
/* */ /* */
/* ************************************************************************** */ /* ************************************************************************** */
@ -20,7 +20,7 @@ import { motion, AnimatePresence } from 'framer-motion'
// import { GrClose } from 'react-icons/gr' // import { GrClose } from 'react-icons/gr'
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
import ModalEdit from "../components/Profile/EditName.tsx"; import ModalEdit from "../components/Profile/EditName.tsx";
import {AiOutlineHistory} from 'react-icons/ai' import {AiOutlineCloseCircle, AiOutlineHistory} from 'react-icons/ai'
import { MdQrCodeScanner, MdOutlinePhotoLibrary } from 'react-icons/md'; import { MdQrCodeScanner, MdOutlinePhotoLibrary } from 'react-icons/md';
import { GiWingedSword, GiCrownedSkull } from 'react-icons/gi'; import { GiWingedSword, GiCrownedSkull } from 'react-icons/gi';
@ -82,43 +82,13 @@ function Profile () {
// } // }
}; };
// const handleUpload = async () => {
// const formData = new FormData();
// formData.append('photo', selectedPhoto);
// try {
// await api.post('/picture', formData);
// console.log('File uploaded successfully');
// window.location.reload();
// } catch (error) {
// console.error('Error uploading file:', error);
// }
// };
// const handleUpload = async (event: React.FormEvent) => {
// event.preventDefault()
// console.log("up photo")
// if (selectedPhoto) {
// console.log("selected photo")
// const formData = new FormData();
// formData.append('photo', selectedPhoto);
// try {
// await api.post('/picture', formData);
// console.log('File uploaded successfully');
// window.location.reload();
// } catch (error) {
// console.error('Error uploading file:', error);
// }
// } else {
// console.log('No file selected');
// }
// };
useEffect(()=> { useEffect(()=> {
const getUser = async ()=>{ const getUser = async ()=>{
console.log(`username= ${username}`) console.log(`username= ${username}`)
// const pic // const pic
let pic let pic;
try{ try{
console.log("before request")
const me = await api.get("/profile") const me = await api.get("/profile")
if (!username) if (!username)
{ {
@ -160,7 +130,7 @@ function Profile () {
{isLoading || !user ? ( {isLoading || !user ? (
<h1>Loading...</h1> <h1>Loading...</h1>
) : ( ) : (
<h1>{user.nickname}</h1> <h1 className='user_name'>{user.nickname}</h1>
)} )}
</span> </span>
@ -202,7 +172,7 @@ function Profile () {
function Home () { function Home () {
const [move, setmove ] = useState(false); const [move, setmove ] = useState(false);
const [user, setUser] = useState([]); const [user, setUser] = useState<User>();
const [successQr, setSuccessQr] = useState(false); const [successQr, setSuccessQr] = useState(false);
const [successSword, setSuccessSword] = useState(false); const [successSword, setSuccessSword] = useState(false);
@ -211,20 +181,31 @@ function Home () {
const closeSword = () => setSuccessSword(false); const closeSword = () => setSuccessSword(false);
const closeCrown = () => setSuccessCrown(false); const closeCrown = () => setSuccessCrown(false);
const { username } = useParams();
useEffect(() => { useEffect(() => {
const fetchSuccess = async () => { const fetchSuccess = async () => {
try { try {
if (!username)
{
const tmpUser = await api.get("/profile"); const tmpUser = await api.get("/profile");
setUser(tmpUser.data); setUser(tmpUser.data);
} }
else
{
const tmpUser = await api.post("/user", {username: username});
setUser(tmpUser.data);
}
// const tmpUser = await api.get("/profile");
// setUser(tmpUser.data);
}
catch (error) catch (error)
{ {
console.log(error); console.log(error);
} }
}; };
fetchSuccess(); fetchSuccess();
}) }, []);
return ( return (
<motion.div className="page" <motion.div className="page"
@ -232,14 +213,13 @@ function Home () {
animate={{opacity: 1}} animate={{opacity: 1}}
exit={{opacity: -1}}> exit={{opacity: -1}}>
<div> <div>
{user.otp_verified ? ( {user && user.otp_verified ? (
<MdQrCodeScanner className='success' onClick={() => setSuccessQr(true)}/> <MdQrCodeScanner className='success' onClick={() => setSuccessQr(true)}/>
):("")} ):("")}
{user.win >= 2 ? ( {user && user.win >= 2 ? (
<GiWingedSword className="success" onClick={() => setSuccessSword(true)}/> <GiWingedSword className="success" onClick={() => setSuccessSword(true)}/>
):("")} ):("")}
{user && user.win >= 5 ? (
{user.win >= 5 ? (
<GiCrownedSkull className="success" onClick={() => setSuccessCrown(true)}/> <GiCrownedSkull className="success" onClick={() => setSuccessCrown(true)}/>
):("")} ):("")}
</div> </div>
@ -256,7 +236,7 @@ function Home () {
className="div_history" className="div_history"
// className="history" // className="history"
onClick={ () => setmove(!move)}> onClick={ () => setmove(!move)}>
<Link to="#" className="history"><AiOutlineHistory/> Match History</Link> <Link to="#" className="history"> {move ? (<AiOutlineCloseCircle/>):(<AiOutlineHistory/>)} Match History</Link>
</motion.div> </motion.div>
<AnimatePresence initial={false} onExitComplete={() => null}> <AnimatePresence initial={false} onExitComplete={() => null}>
{successQr ? ( {successQr ? (

View File

@ -148,7 +148,7 @@ function QrCode () {
<h1>Double Auth Validation</h1> <h1>Double Auth Validation</h1>
<input <input
onKeyDown={handleKeyPress} onKeyDown={handleKeyPress}
type="text" type="number"
className="qr" className="qr"
placeholder="6 Digits Code" placeholder="6 Digits Code"
value={code} value={code}
@ -156,7 +156,7 @@ function QrCode () {
/> />
</> </>
) : ( ) : (
<button onClick={handleDesactivate}>Desactivate 2FA</button> <button className="desactivate" onClick={handleDesactivate}>Desactivate 2FA</button>
)} )}
</> </>

View File

@ -61,7 +61,7 @@ function DrawCanvas(option: number, gameParam: GameProps) {
if(!ctx) if(!ctx)
return ; return ;
const socket = io('http://localhost:4000', { transports: ['polling'] }); const socket = io('http://' + process.env.REACT_APP_SOCKET_URL + ':4000', { transports: ['polling'] });
// useEffect(() => { // useEffect(() => {
// console.log("useeffect?????????????????") // console.log("useeffect?????????????????")
// return () => { // return () => {
@ -170,7 +170,9 @@ socket.on('pong:privateId', async (data) => {
socket.on('pong:gameId', async (data) => { socket.on('pong:gameId', async (data) => {
console.log("gameId received"); console.log("gameId received");
gameId = data; gameId = data.gameId;
console.log("gameid = ", gameId);
console.log("data gameid = ", data);
try { try {
let response = await api.get('/profile'); let response = await api.get('/profile');
@ -190,6 +192,16 @@ socket.on('pong:gameId', async (data) => {
console.log("emit to name"); console.log("emit to name");
socket.emit('pong:name', info); socket.emit('pong:name', info);
if (data.id === myId)
{
console.log("myId= true")
vX = 0.0001;
}
else
{
console.log("myId= false")
vX = -0.0001;
}
} catch (error) { } catch (error) {
console.log(error); console.log(error);
// Handle error here // Handle error here
@ -198,7 +210,11 @@ socket.on('pong:gameId', async (data) => {
}); });
socket.on('pong:name', (data) => { socket.on('pong:name', (data) => {
opName = data; opName = data.name;
// if (data.myId === myId)
// vX = 0.0001;
// else
// vX = -0.0001;
console.log(`opponent Name= ${opName}`) console.log(`opponent Name= ${opName}`)
}); });
@ -222,7 +238,6 @@ socket.on('pong:info', (data) => {
vY = data.vY; vY = data.vY;
}); });
socket.on('pong:paddle', (data) => { socket.on('pong:paddle', (data) => {
console.log("paddle info receive") console.log("paddle info receive")
oPaddleY = (data.paddleY / data.height) * canvas.height oPaddleY = (data.paddleY / data.height) * canvas.height
@ -251,12 +266,27 @@ socket.on('pong:point', (data) => {
// console.log("up point"); // console.log("up point");
myScore = data.point; myScore = data.point;
// } // }
vX = 0; vX = -0.0001;
vY = 0; vY = 0;
ballX = canvas.width / 2; ballX = canvas.width / 2;
ballY = canvas.height / 2; ballY = canvas.height / 2;
}); });
socket.on('pong:hisPoint', (data) => {
// hisScore += 1;
console.log("myPointawdawdawdawd point");
// if (vX != 0)
// {
// console.log("up point");
hisScore = data.point;
// }
vX = -0.0001;
vY = 0;
ballX = canvas.width / 2;
ballY = canvas.height / 2;
// send_forced_info();
});
//======================================================================================================== //========================================================================================================
//======================================================================================================== //========================================================================================================
// Socket EMIT // Socket EMIT
@ -323,6 +353,26 @@ socket.on('pong:point', (data) => {
point: hisScore, point: hisScore,
} }
socket.emit('pong:point', info); socket.emit('pong:point', info);
vX = 0.0001;
}
function send_my_point()
{
if (!gameId || !canvas)
return ;
// console.log("send point");
const info = {
id: myId,
gameId: gameId,
point: myScore,
}
socket.emit('pong:myPoint', info);
myScore++;
vX = 0.0001;
vY = 0;
ballX = canvas.width / 2;
ballY = canvas.height / 2;
send_forced_info();
} }
function send_paddle_info() function send_paddle_info()
@ -459,7 +509,10 @@ async function draw(timestamp: number)
{ {
console.log("turning, running= ", running); console.log("turning, running= ", running);
if (!running) if (!running)
{
window.location.replace("http://" + process.env.REACT_APP_BASE_URL + "/pong")
return ; return ;
}
if (!gameId || !canvas ) if (!gameId || !canvas )
{ {
// console.log("nogameid score= ", myScore); // console.log("nogameid score= ", myScore);
@ -593,16 +646,17 @@ async function draw(timestamp: number)
} }
ballX = canvas.width / 2; ballX = canvas.width / 2;
ballY = canvas.height / 2; ballY = canvas.height / 2;
vX = 0; vX = 0.0001;
vY = 0; vY = 0;
hisScore += 1; hisScore += 1;
send_point(); send_point();
// send_forced_info(); // send_forced_info();
} }
if (ballX > canvas.width) if (ballX > (canvas.width * 1.2) && ballX - vX > canvas.width)
{ {
console.log("ball out win point pls")
send_my_point();
// if (ballX > canvas.width * 2) // if (ballX > canvas.width * 2)
// socket.emit
// console.log("win point") // console.log("win point")
// if (ballY <= paddleY + paddleHeight + ballRadius && ballY >= paddleY - ballRadius) // if (ballY <= paddleY + paddleHeight + ballRadius && ballY >= paddleY - ballRadius)
// { // {
@ -702,9 +756,8 @@ async function draw(timestamp: number)
vX -= 0.0001; vX -= 0.0001;
} }
send_forced_info(); send_forced_info();
// console.log(`vx = ${vX}`);
} }
else if (event.code === "KeyR") else if (event.code === "KeyW")
{ {
if (!superpowerModifier) if (!superpowerModifier)
return ; return ;
@ -717,6 +770,13 @@ async function draw(timestamp: number)
paddleY = canvas.height / 2 - paddleHeight / 2; paddleY = canvas.height / 2 - paddleHeight / 2;
console.log('Cinq secondes se sont écoulées.'); console.log('Cinq secondes se sont écoulées.');
}, 5000); }, 5000);
// setTimeout(() => {
// // code à exécuter après 5 secondes
// paddleHeight = canvas.height * 0.25;
// paddleY = canvas.height / 2 - paddleHeight / 2;
// console.log('Cinq secondes se sont écoulées.');
// }, 5000);
} }
}); });

View File

@ -3,12 +3,15 @@ import { useState, useEffect } from 'react'
import queryString from 'query-string'; import queryString from 'query-string';
import api from "./axiosApi.tsx"; import api from "./axiosApi.tsx";
import axios from 'axios'; import axios from 'axios';
import React from 'react';
import {Matchlog, User} from "../../interfaces.tsx"
function SuccessToken() { function SuccessToken() {
const location = useLocation(); const location = useLocation();
const { data } = queryString.parse(location.search); const { data } = queryString.parse(location.search);
const [code, setCode] = useState(''); const [code, setCode] = useState('');
const [user, setUser] = useState(false); const [user, setUser] = useState<User>();
useEffect(() => { useEffect(() => {
if (!data) { if (!data) {
@ -37,7 +40,7 @@ function SuccessToken() {
getUser(); getUser();
}, [data]); }, [data]);
const handleKeyPress = async (e)=>{ const handleKeyPress = async (e: { key: string; })=>{
// console.log(`e in press= ${e.key}`) // console.log(`e in press= ${e.key}`)
if (e.key !== "Enter") if (e.key !== "Enter")
return ; return ;
@ -90,7 +93,8 @@ function SuccessToken() {
// Render a loading indicator or return null while user is being fetched // Render a loading indicator or return null while user is being fetched
return <h1>Loading...</h1>; return <h1>Loading...</h1>;
} }
if (!data)
return ;
const cleanData = data.slice(1, -1); // Declare cleanData here as well const cleanData = data.slice(1, -1); // Declare cleanData here as well
if (!user.otp_verified) { if (!user.otp_verified) {

View File

@ -5,15 +5,30 @@
background-color: black; background-color: black;
height: 100%; height: 100%;
} }
input.qr::-webkit-outer-spin-button,
input.qr::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input.qr{ input.qr{
width: 20%; width: auto;
border-radius: 5px; border-radius: 5px;
background-color: rgb(0, 0, 0); background-color: rgb(0, 0, 0);
margin : 1%; margin : 1%;
color:white; color:rgb(42, 41, 41);
border-style: solid;
border-width: 1px;
} }
.desactivate {
margin: 40vh;
color: ghostwhite;
outline: 0;
border-radius: 20px;
padding: 20px;
background-image: linear-gradient(90deg, #5843e4, #5a0760);
border: 0;
}
.App-logo { .App-logo {
height: 40vmin; height: 40vmin;
pointer-events: none; pointer-events: none;
@ -48,3 +63,9 @@ input.qr{
transform: rotate(360deg); transform: rotate(360deg);
} }
} }
.friendRequest {
margin-left: 4vh;
stroke-width: 0.5;
font-size: x-large;
}

View File

@ -3,6 +3,7 @@
margin: 50px; margin: 50px;
} }
.rank_elements { .rank_elements {
border-width:1px; border-width:1px;
border-style:solid; border-style:solid;
@ -18,11 +19,23 @@
/* background-color: #5843e4; */ /* background-color: #5843e4; */
/* border-color: white; */ /* border-color: white; */
overflow: scroll; overflow: scroll;
height: 70vh; height: 68vh;
} }
.profilePic{ .profilePic{
margin-left: 10px;
/* margin-top: 10px; */
height: 30px; height: 30px;
width: 30px; width: 30px;
border-radius: 50%; border-radius: 50%;
} }
@media screen and (max-width: 755px){
.game{
display: grid;
height: 20vh;
}
.scroll{
height: 20vh;
}
}

View File

@ -1,6 +1,6 @@
.home{ .home{
background-color: rgb(0, 0, 0); background-color: rgb(0, 0, 0);
height: 90vh; height: 70vh;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
@ -19,7 +19,8 @@ select{
border: 0!important; border: 0!important;
margin: 5px; margin: 5px;
font-size: 18px; font-size: 18px;
border-radius: 6px; padding: 5px;
border-radius: 1000px;
} }
.modal{ .modal{
@ -54,6 +55,7 @@ select{
height: 74vh; height: 74vh;
width: 30%; width: 30%;
overflow: scroll; overflow: scroll;
border-radius: 0px 0px 0px 10px;
/* width: 2rem; */ /* width: 2rem; */
/* height: 4rem; */ /* height: 4rem; */
} }
@ -131,16 +133,17 @@ select{
} }
.messages{ .messages{
background-color: rgb(26, 26, 26); /* background-color: rgb(26, 26, 26); */
/* height: calc(100% - 118px); */ /* height: calc(100% - 118px); */
width: 70%; width: 70%;
/* height: 300px; */ /* height: 300px; */
border-radius: 0px 0px 10px 0px;
overflow: scroll; overflow: scroll;
} }
.input{ .input{
display: flex; display: flex;
height: 50px; height: 6vh;
background-color: white; background-color: white;
color:#060b26; color:#060b26;
border: none; border: none;
@ -202,6 +205,7 @@ p {
text-decoration: none; text-decoration: none;
font-weight:lighter; font-weight:lighter;
margin: 1%; margin: 1%;
height: 25px;
} }
.darkSubmit{ .darkSubmit{
@ -307,11 +311,17 @@ p {
/* flex-direction: column; */ /* flex-direction: column; */
/* align-items: center; */ /* align-items: center; */
background-color: #3e3c61; background-color: #3e3c61;
overflow: scroll;
} }
.settingFirstPart{ .settingFirstPart{
margin-top: 10%; margin-top: 10%;
margin-left: 15%; margin-left: 20%;
}
.settingFirstPart2{
margin-top: 10%;
margin-left: 30%;
} }
.settingSecondPart{ .settingSecondPart{
@ -324,6 +334,7 @@ p {
.checkbox{ .checkbox{
display:flex; display:flex;
flex-direction:row; flex-direction:row;
margin-left: 60px;
} }
input.in{ input.in{
@ -331,17 +342,25 @@ input.in{
margin-left: 0px; margin-left: 0px;
background-color: black; background-color: black;
color: white; color: white;
border-radius: 12px; border-radius: 4px;
width: 70%; width: 70%;
height: 100%;
font-weight:100;
font-size: 20px;
padding: 7px;
} }
input.in_howLong{ input.in_howLong{
margin-top: 14.5%; margin-top: 13%;
margin-left: 0px; margin-left: 0px;
background-color: black; background-color: black;
color: white; color: white;
border-radius: 12px; border-radius: 4px;
width: 15%; width: 10%;
height: 10%;
font-weight:100;
font-size: 20px;
padding: 7px;
} }
.mdp{ .mdp{
@ -351,3 +370,18 @@ input.in_howLong{
width: 20%; width: 20%;
} }
.case{
height: auto;
width: auto;
margin-left: 10px;
}
.catchat{
font-size: 30px;
margin-left: 12px;
}
.block{
font-size: 25px;
margin-left: 12px;
}

View File

@ -62,6 +62,7 @@
.page { .page {
text-align: center; text-align: center;
overflow-y: scroll; overflow-y: scroll;
/* height: 80vh; */
/* height: 50vh; */ /* height: 50vh; */
/* width: 50vh; */ /* width: 50vh; */
/* background-color: black; */ /* background-color: black; */
@ -80,9 +81,9 @@
border-radius: 50%; border-radius: 50%;
border: thick; border: thick;
border-color: red; border-color: red;
margin-left: 20px;
/* border-image: linear-gradient(90deg, #5843e4, #5a0760); */ /* border-image: linear-gradient(90deg, #5843e4, #5a0760); */
/* margin-top: 20px; */
} }
.home{ .home{
@ -96,11 +97,11 @@
} }
.history{ .history{
display: inline-block; display:inline-block;
color: white; color: white;
background-color: #5843e4; background-color: #5843e4;
border-radius: 20px; border-radius: 20px;
padding: 14px; padding: 1.3% 30%;
font-size: 1.7rem; font-size: 1.7rem;
text-decoration: none; text-decoration: none;
font-weight: bold; font-weight: bold;
@ -153,6 +154,13 @@
text-decoration: none; text-decoration: none;
font-weight: bold; font-weight: bold;
} }
.user_name{
/* background-image: linear-gradient(90deg, #5843e4, #5a0760); */
background: -webkit-linear-gradient(60deg, #5843e4, #5a0760);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}
/* canvas { /* canvas {
margin-top: 20px; margin-top: 20px;
border: solid 0px #ccc; border: solid 0px #ccc;

View File

@ -1,20 +1,20 @@
.playButton { .playButton {
background-image: linear-gradient(90deg, #5843e4, #5a0760); background-image: linear-gradient(90deg, #5843e4, #5a0760);
display: flex;
flex-wrap: wrap;
overflow: hidden;
border-radius: 5vh; border-radius: 5vh;
color: white; color: white;
/* display: block; */ display: block;
margin: auto; margin: auto;
margin-top: 30vh; margin-top: 30vh;
padding: 2vh 4vw; padding: 2vh 5vw;
height: 10vh; height: 10vh;
width: 20vw; width: 20vw;
font-size: 250%; font-size: 300%;
text-align: center;
} }
.inside_checkbox{
height : 70%;
width: 70%;
}
.field { .field {
background-color: rgb(249, 249, 249); background-color: rgb(249, 249, 249);
@ -69,6 +69,18 @@
} }
} }
.responsive{
display: flex;
flex-direction: column;
}
/* @media screen and (max-width: 350px){
.responsive{
display:list-item;
flex-direction: column;
}
} */
#myCanvas { #myCanvas {
background-color: rgb(124, 47, 47); background-color: rgb(124, 47, 47);
/* position: absolute; */ /* position: absolute; */

View File

@ -14,19 +14,9 @@ services:
- 8080:8080 - 8080:8080
volumes: volumes:
- ./conf/nginx.conf:/etc/nginx/conf.d/default.conf - ./conf/nginx.conf:/etc/nginx/conf.d/default.conf
# volumes:
# - "./conf:/etc/nginx/templates/"
# ports:
# - 80:80
# volumes:
# - ./conf/nginx.conf:/etc/nginx/conf.d/default.conf
# command: sh -c "envsubst < /etc/nginx/conf.d/default.conf > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
# - ./containers/frontend:/var/www/html
networks: networks:
- pongNetwork - pongNetwork
react_app: react_app:
image: node:latest image: node:latest
container_name: react_app container_name: react_app