Compare commits
No commits in common. "master" and "online" have entirely different histories.
10
.env
10
.env
@ -14,22 +14,22 @@
|
||||
NGINX_ENVSUBST_TEMPLATE_SUFFIX=".conf"
|
||||
|
||||
# BASE_URL=http://localhost
|
||||
BASE_URL=localhost:8080
|
||||
REACT_APP_BASE_URL=localhost:8080
|
||||
REDIRECT_URI=http://localhost:8080/api/auth/login
|
||||
BASE_URL=92.143.191.152
|
||||
REACT_APP_BASE_URL=92.143.191.152
|
||||
REDIRECT_URI=http://92.143.191.152/api/auth/login
|
||||
#postgres var
|
||||
# POSTGRES_HOST=127.0.0.1
|
||||
# DB_TYPE=postgres
|
||||
POSTGRES_HOST=postgresql
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_PASSWORD=postgres
|
||||
POSTGRES_PASSWORD=pass
|
||||
POSTGRES_DATABASE=postgres
|
||||
MODE=DEV
|
||||
|
||||
#port
|
||||
API_PORT=3000
|
||||
# REACT_PORT=3000 (current = 8080)
|
||||
NGINX_PORT=8080
|
||||
NGINX_PORT=80
|
||||
PONG_PORT=4000
|
||||
CHAT_PORT=4001
|
||||
POSTGRES_PORT=5432
|
||||
|
||||
153
README.md
153
README.md
@ -1,153 +0,0 @@
|
||||
# ft_transcendence
|
||||
|
||||
## Description
|
||||
ft_transcendence est le projet final du tronc commun de l'École 42. Il s'agit de créer une application web complète permettant de jouer au Pong en ligne avec des fonctionnalités modernes comme les tournois, le chat en temps réel, et l'authentification.
|
||||
|
||||
## Fonctionnalités principales
|
||||
- 🎮 **Jeu Pong** en temps réel multijoueur
|
||||
- 🏆 **Système de tournois** avec brackets
|
||||
- 💬 **Chat en temps réel** avec channels
|
||||
- 👤 **Profils utilisateurs** et amis
|
||||
- 🔐 **Authentification 2FA** (Google, 42)
|
||||
- 📊 **Statistiques** et historique des parties
|
||||
- 🎨 **Interface moderne** et responsive
|
||||
- 🔒 **Sécurité** web avancée
|
||||
|
||||
## Technologies utilisées
|
||||
|
||||
### Frontend
|
||||
- **Framework** : React/Vue.js/Angular ou Vanilla JS
|
||||
- **Styling** : CSS3, Bootstrap/Tailwind
|
||||
- **WebSockets** : Pour le temps réel
|
||||
|
||||
### Backend
|
||||
- **Framework** : Django/Flask/Node.js
|
||||
- **Base de données** : PostgreSQL
|
||||
- **API** : REST ou GraphQL
|
||||
- **Authentication** : OAuth2, JWT
|
||||
|
||||
### DevOps
|
||||
- **Containerisation** : Docker & Docker Compose
|
||||
- **Reverse Proxy** : Nginx
|
||||
- **SSL/TLS** : Certificats HTTPS
|
||||
- **Base de données** : PostgreSQL en conteneur
|
||||
|
||||
## Architecture
|
||||
```
|
||||
ft_transcendence/
|
||||
├── docker-compose.yml # Orchestration des services
|
||||
├── frontend/ # Application client
|
||||
│ ├── src/
|
||||
│ ├── public/
|
||||
│ └── Dockerfile
|
||||
├── backend/ # API serveur
|
||||
│ ├── api/
|
||||
│ ├── models/
|
||||
│ ├── services/
|
||||
│ └── Dockerfile
|
||||
├── database/ # Configuration PostgreSQL
|
||||
├── nginx/ # Configuration reverse proxy
|
||||
└── ssl/ # Certificats SSL
|
||||
```
|
||||
|
||||
## Modules bonus
|
||||
- **Module Web** : Framework moderne (React/Vue/Angular)
|
||||
- **Module User Management** : Authentification avancée
|
||||
- **Module Gaming** : Variantes de Pong ou autres jeux
|
||||
- **Module AI-Algo** : IA pour jouer contre
|
||||
- **Module Cybersecurity** : Sécurité renforcée
|
||||
- **Module DevOps** : Infrastructure monitoring
|
||||
- **Module Graphics** : Interface 3D avancée
|
||||
|
||||
## Installation et déploiement
|
||||
|
||||
### Prérequis
|
||||
- Docker et Docker Compose
|
||||
- Domaine avec certificat SSL
|
||||
- Clés API (42, Google) pour OAuth
|
||||
|
||||
### Lancement
|
||||
```bash
|
||||
git clone <repository-url>
|
||||
cd ft_transcendence
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
### Configuration
|
||||
1. Configurer les variables d'environnement
|
||||
2. Générer les certificats SSL
|
||||
3. Configurer OAuth applications
|
||||
4. Initialiser la base de données
|
||||
|
||||
## Gameplay
|
||||
|
||||
### Pong multijoueur
|
||||
- Contrôles clavier fluides
|
||||
- Synchronisation en temps réel
|
||||
- Système de score et timer
|
||||
- Reconnexion automatique
|
||||
|
||||
### Tournois
|
||||
- Création de tournois public/privé
|
||||
- Système d'élimination
|
||||
- Classements et récompenses
|
||||
- Notifications en temps réel
|
||||
|
||||
## Sécurité implémentée
|
||||
- 🔒 **HTTPS** obligatoire
|
||||
- 🛡️ **Protection CSRF/XSS**
|
||||
- 🔑 **Authentification 2FA**
|
||||
- 💾 **Hashage sécurisé** des mots de passe
|
||||
- 🚫 **Protection injection SQL**
|
||||
- 🔐 **Validation** côté serveur
|
||||
- 🍪 **Gestion sécurisée** des sessions
|
||||
|
||||
## Fonctionnalités sociales
|
||||
- **Profils utilisateurs** personnalisables
|
||||
- **Système d'amis** avec invitations
|
||||
- **Chat global** et channels privés
|
||||
- **Statut en ligne** des utilisateurs
|
||||
- **Historique des parties**
|
||||
- **Achievements** et badges
|
||||
|
||||
## Performance et scalabilité
|
||||
- **WebSockets** pour le temps réel
|
||||
- **Cache Redis** pour les sessions
|
||||
- **Optimisation** des requêtes DB
|
||||
- **Load balancing** pour la montée en charge
|
||||
- **Monitoring** des performances
|
||||
|
||||
## Tests et qualité
|
||||
- **Tests unitaires** backend
|
||||
- **Tests d'intégration** API
|
||||
- **Tests end-to-end** Selenium
|
||||
- **Sécurité** avec OWASP ZAP
|
||||
- **Performance** avec JMeter
|
||||
|
||||
## Compétences développées
|
||||
- Architecture d'applications web modernes
|
||||
- Développement full-stack
|
||||
- Sécurité web avancée
|
||||
- DevOps et containerisation
|
||||
- Gestion de projet complexe
|
||||
- Programmation temps réel
|
||||
- UI/UX design
|
||||
|
||||
## Contraintes 42
|
||||
- **Single Page Application** obligatoire
|
||||
- **3 frameworks/langages** différents minimum
|
||||
- **Docker** pour tous les services
|
||||
- **Sécurité** de niveau production
|
||||
- **Code maintenable** et documenté
|
||||
|
||||
## Auteur
|
||||
Alexandre Pommier (apommier) - École 42
|
||||
|
||||
## Équipe (si applicable)
|
||||
- Développeur Frontend
|
||||
- Développeur Backend
|
||||
- DevOps Engineer
|
||||
- Security Specialist
|
||||
|
||||
## Licence
|
||||
Projet académique - École 42
|
||||
@ -3,14 +3,14 @@ server {
|
||||
# listen 80 ssl;
|
||||
# listen 443 ssl;
|
||||
# listen ${NGINX_PORT};
|
||||
listen 8080;
|
||||
listen 80;
|
||||
|
||||
location /{
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass http://react_app:8001;
|
||||
proxy_pass http://react_app:8080;
|
||||
}
|
||||
|
||||
location /api {
|
||||
@ -20,18 +20,4 @@ server {
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_pass http://api:3000/api;
|
||||
}
|
||||
|
||||
location /socket {
|
||||
# Forward requests to socket server running on port 4001
|
||||
if ($request_uri ~ ^/socket/4001) {
|
||||
proxy_pass http://chat:4001;
|
||||
break;
|
||||
}
|
||||
|
||||
# Forward requests to socket server running on port 4000
|
||||
if ($request_uri ~ ^/socket/4000) {
|
||||
proxy_pass http://pong:4000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/17 01:00:00 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/21 01:19:01 by apommier ### ########.fr */
|
||||
/* Updated: 2023/06/18 17:45:39 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -27,7 +27,6 @@ import { generateOTP } from './users/2fa';
|
||||
import { VerifyOTP } from './users/2fa';
|
||||
import { ValidateOTP } from './users/2fa';
|
||||
import { privateDecrypt } from 'crypto';
|
||||
import { formatWithOptions } from 'util';
|
||||
|
||||
|
||||
//2fa
|
||||
@ -129,8 +128,6 @@ export class AppController {
|
||||
async newBlocked(@Request() req, @Body() data: any) {
|
||||
// return await this.userService.getFriends(req.user.username);
|
||||
console.log(`user= ${req.user.username}`)
|
||||
if (data.username === req.user.username)
|
||||
return (0);
|
||||
const user = await this.userService.findOne(req.user.username)
|
||||
return await this.userService.addBlocked(user, data.username);
|
||||
}
|
||||
@ -139,8 +136,6 @@ export class AppController {
|
||||
@Post('/invite')
|
||||
async newInvite(@Request() req, @Body() data: any) {
|
||||
console.log(`user= ${req.user.username}`)
|
||||
if (data.username === req.user.username)
|
||||
return (0);
|
||||
const user = await this.userService.findOne(data.username)
|
||||
if (!user)
|
||||
return (0);
|
||||
@ -220,10 +215,7 @@ export class AppController {
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/win')
|
||||
async addWin(@Request() req, @Body() data: any) {
|
||||
console.log("WIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIN: ", req.user.username)
|
||||
const user = await this.userService.findOne(req.user.username);
|
||||
console.log("User", user)
|
||||
// const user2 = await this.userService.findOne(data.opName);
|
||||
user.win++;
|
||||
const Esp = 1 / (1 + Math.pow(10, (data.opRank - user.rank) / this.scaleFactor))
|
||||
const newRank = user.rank + this.kFactor * (1 - Esp);
|
||||
@ -237,16 +229,14 @@ export class AppController {
|
||||
newMatch.opScore = data.opScore;
|
||||
newMatch.opponent = data.opName;
|
||||
newMatch.parent = user;
|
||||
console.log(`newMatch WIIIN = ${newMatch}`);
|
||||
|
||||
await this.userService.saveChild(user, newMatch);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/loss')
|
||||
async addLoss(@Request() req, @Body() data: any) {
|
||||
console.log("LOOOOOOOOOOOOOOOSE: ", req.user.username)
|
||||
const user = await this.userService.findOne(req.user.username);
|
||||
console.log("User", user)
|
||||
user.loss++;
|
||||
|
||||
const Esp = 1 / (1 + Math.pow(10, (data.opRank - user.rank) / this.scaleFactor))
|
||||
@ -261,7 +251,7 @@ export class AppController {
|
||||
newMatch.opScore = data.opScore;
|
||||
newMatch.opponent = data.opName;
|
||||
newMatch.parent = user;
|
||||
console.log(`newMatch Loose= ${newMatch}`);
|
||||
|
||||
await this.userService.saveChild(user, newMatch);
|
||||
}
|
||||
|
||||
@ -280,49 +270,6 @@ export class AppController {
|
||||
return await this.userService.getRanking();
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/partyInvite')
|
||||
async partyInvite(@Request() req, @Body() data: any)
|
||||
{
|
||||
//find data.username and add invite to list
|
||||
console.log("data post priv invite=", data);
|
||||
const user = await this.userService.findOne(data.username);
|
||||
user.partyInvite = user.partyInvite || [];
|
||||
user.partyInvite.push({ username: req.user.username, gameId: data.gameId });
|
||||
console.log("usr === ", user)
|
||||
await this.userService.save(user);
|
||||
// user.partyInvite.push(data);
|
||||
console.log("invite === ", user.partyInvite)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('/partyInvite')
|
||||
async getPartyInvite(@Request() req, @Body() data: any)
|
||||
{
|
||||
//find data.username and add invite to list
|
||||
const user = await this.userService.findOne(req.user.username);
|
||||
user.partyInvite = user.partyInvite || [];
|
||||
// this.userService.save(user);
|
||||
// user.partyInvite.push(data);
|
||||
// console.log("data invite === ", data.username)
|
||||
return user.partyInvite;
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/deleteInvite')
|
||||
async deleteInvite(@Request() req, @Body() data: any)
|
||||
{
|
||||
console.log("delete invite user= ", data.username)
|
||||
const user = await this.userService.findOne(req.user.username);
|
||||
|
||||
|
||||
// user.partyInvite = user.partyInvite.filter(item => Object.values(item)[1] !== req.user.username);
|
||||
console.log("user.partyInvite before", user.partyInvite)
|
||||
user.partyInvite = user.partyInvite.filter((item) => Object.values(item)[1] !== data.username);
|
||||
console.log("user.partyInvite after", user.partyInvite)
|
||||
this.userService.save(user);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/history')
|
||||
async getHistory(@Body() data: any)
|
||||
@ -494,13 +441,6 @@ export class AppController {
|
||||
return await this.chatService.findAll();
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/convId')
|
||||
async getConvById(@Body() data: any) {
|
||||
return await this.chatService.findConv(data.convId);
|
||||
}
|
||||
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/message')
|
||||
async postMessage(@Request() req, @Body() data: any) {
|
||||
@ -541,6 +481,12 @@ export class AppController {
|
||||
// res.json(messages);
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/ban')
|
||||
async banUser(@Body() data: any) {
|
||||
return await this.chatService.banUser(data.convId, data.username)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/name')
|
||||
async setName(@Body() data: any) {
|
||||
@ -549,6 +495,12 @@ export class AppController {
|
||||
return await this.chatService.setName(data.convId, data.name)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/invite')
|
||||
async inviteUser(@Body() data: any) {
|
||||
return await this.chatService.inviteUser(data.convId, data.username)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/password')
|
||||
async setPassword(@Body() data: any) {
|
||||
@ -561,36 +513,12 @@ export class AppController {
|
||||
return await this.chatService.verifyPassword(data.convId, data.password)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/invite')
|
||||
async inviteUser(@Body() data: any) {
|
||||
return await this.chatService.inviteUser(data.convId, data.username)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/ban')
|
||||
async banUser(@Body() data: any) {
|
||||
if (!data.username)
|
||||
return ;
|
||||
return await this.chatService.banUser(data.convId, data.username)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/admin')
|
||||
async setAdmin(@Body() data: any) {
|
||||
if (!data.username)
|
||||
return ;
|
||||
return await this.chatService.setAdmin(data.convId, data.username)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/mute')
|
||||
async muteUser(@Body() data: any) {
|
||||
if (!data.username)
|
||||
return ;
|
||||
return await this.chatService.muteUser(data.convId, data.username)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/isAdmin')
|
||||
async isAdmin(@Request() req, @Body() data: any) {
|
||||
@ -598,6 +526,11 @@ export class AppController {
|
||||
return await this.chatService.isAdmin(data.convId, req.user.username)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/mute')
|
||||
async muteUser(@Body() data: any) {
|
||||
return await this.chatService.muteUser(data.convId, data.username)
|
||||
}
|
||||
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('/private')
|
||||
|
||||
@ -58,7 +58,6 @@ export class loginClass {
|
||||
console.log(`no user, creating one`);
|
||||
user = {
|
||||
id: null,
|
||||
partyInvite: null,
|
||||
password: null,
|
||||
username: userName,
|
||||
nickname: userName,
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/17 01:00:25 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/20 16:47:02 by apommier ### ########.fr */
|
||||
/* Updated: 2023/06/18 13:14:51 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -85,7 +85,6 @@ async banUser(convId: number, username: string) {
|
||||
conv.banned = conv.banned || [];
|
||||
if (conv.banned.find(item => item === username))
|
||||
return (1);
|
||||
conv.members = conv.members.filter((item) => item !== username);
|
||||
conv.banned.push(username);
|
||||
this.save(conv);
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/04/09 14:53:49 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/22 20:42:32 by apommier ### ########.fr */
|
||||
/* Updated: 2023/06/12 14:51:44 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -17,7 +17,7 @@ export const getTypeOrmConfig = (): TypeOrmModuleOptions => ({
|
||||
host: process.env.POSTGRES_HOST || 'postgresql',
|
||||
port: parseInt(process.env.POSTGRES_PORT, 10) || 5432,
|
||||
username: process.env.POSTGRES_USER || 'postgres',
|
||||
password: process.env.POSTGRES_PASSWORD || 'postgres',
|
||||
password: process.env.POSTGRES_PASSWORD || 'pass',
|
||||
database: process.env.POSTGRES_DATABASE || 'postgres',
|
||||
entities: ["dist/**/*.entity.js"],
|
||||
// entities: [join(__dirname, '**', '*.entity.{ts,js}')]
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/17 01:00:20 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/23 15:18:19 by apommier ### ########.fr */
|
||||
/* Updated: 2023/06/17 01:31:29 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
||||
@ -65,12 +65,6 @@ export class User {
|
||||
@Column('text', { array: true, nullable: true })
|
||||
friendRequest: string[];
|
||||
|
||||
@Column({ type: 'jsonb', nullable: true })
|
||||
partyInvite: Record<string, string>[];
|
||||
|
||||
// @Column('text', { array: true, nullable: true })
|
||||
// friendRequest: string[];
|
||||
|
||||
@Column('text', { array: true, nullable: true })
|
||||
friends: string[];
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/17 01:00:07 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/21 01:31:44 by apommier ### ########.fr */
|
||||
/* Updated: 2023/06/17 01:00:08 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -47,7 +47,6 @@ export class UsersService {
|
||||
|
||||
async saveChild(user: User, match: MatchLog): Promise<User> {
|
||||
// user.match = savedChild;
|
||||
user.children.push(match)
|
||||
await this.matchRepository.save(match);
|
||||
return await this.userRepository.save(user);
|
||||
}
|
||||
|
||||
@ -8,20 +8,16 @@ export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewa
|
||||
@WebSocketServer()
|
||||
server: Server;
|
||||
|
||||
|
||||
private clients: Record<string, Socket> = {};
|
||||
// private clientsNames: Record<string, Socket[]> = {};
|
||||
private clientsNames: Map<string, string[]> = new Map();
|
||||
// private games: Map<string, Socket[]> = new Map();// Chat en cours, identifiées par un ID
|
||||
|
||||
|
||||
|
||||
afterInit(server: Server)
|
||||
{
|
||||
console.log('ChatGateway initialized');
|
||||
}
|
||||
|
||||
|
||||
handleConnection(client: Socket, ...args: any[])
|
||||
{
|
||||
console.log(`Client connected: ${client.id}`);
|
||||
@ -96,82 +92,93 @@ export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewa
|
||||
console.log("create")
|
||||
this.clientsNames.set(payload.username, [client.id]); // Create a new array with the new client as the value
|
||||
}
|
||||
// let clientLenght = Object.keys(this.clientsNames[payload.username]).length
|
||||
// const clientArray = this.clientsNames.get(payload.username)
|
||||
// let clientLenght = clientArray.
|
||||
// console.log(`lenght= ${clientLenght}`)
|
||||
|
||||
// this.clientsNames[payload.username][clientLenght] = this.clients[client.id];
|
||||
// console.log(`clients: ${Object.keys(this.clientsNames).length}`)
|
||||
// this.clients[clientId] = client;
|
||||
|
||||
//add a new client with socket and name for key
|
||||
//payload.username
|
||||
}
|
||||
|
||||
// @SubscribeMessage('socket.io')
|
||||
// socketConnect(client: any, payload: any): void {
|
||||
// console.log("/socket.io")
|
||||
// }
|
||||
|
||||
@SubscribeMessage('ban')
|
||||
banUser(client: any, payload: any): void {
|
||||
if (!this.clientsNames.has(payload.username))
|
||||
{
|
||||
console.log("No user found.");
|
||||
return;
|
||||
}
|
||||
const bannedClients = this.clientsNames.get(payload.username);
|
||||
bannedClients.forEach(client => {
|
||||
console.log("Banning client:", client);
|
||||
// Perform ban operation on each client, e.g., emit a 'ban' event
|
||||
console.log("clietn socket=", this.clients[client])
|
||||
this.clients[client].emit('ban', payload);
|
||||
});
|
||||
// console.log("/ban")
|
||||
// console.log("in ban username=", payload.username)
|
||||
// if (!this.clientsNames[payload.username])
|
||||
// {
|
||||
// console.log("no user ??")
|
||||
// return ;
|
||||
// }
|
||||
// this.clientsNames[payload.username].forEach()
|
||||
// console.log("client=", this.clientsNames)
|
||||
// this.clients[payload.username].emit('ban', payload)
|
||||
}
|
||||
// @SubscribeMessage('sendMessage')
|
||||
// handleMessage(user: any, payload: any): void {
|
||||
// console.log(`message recceveid: ${payload}`)
|
||||
// console.log(`message recceveid: ${payload.sender}`)
|
||||
// console.log(`message recceveid: ${payload.convId}`)
|
||||
// console.log(`message recceveid: ${payload.members}`)
|
||||
|
||||
@SubscribeMessage('mute')
|
||||
muteUser(client: any, payload: any): void {
|
||||
if (!this.clientsNames.has(payload.username))
|
||||
{
|
||||
console.log("No user found.");
|
||||
return;
|
||||
}
|
||||
const mutedClients = this.clientsNames.get(payload.username);
|
||||
mutedClients.forEach(client => {
|
||||
console.log("Banning client:", client);
|
||||
// Perform ban operation on each client, e.g., emit a 'ban' event
|
||||
console.log("clietn socket=", this.clients[client])
|
||||
this.clients[client].emit('mute', payload);
|
||||
});
|
||||
console.log("/mute")
|
||||
}
|
||||
// console.log(`client id: ${user.id}`)
|
||||
|
||||
// this.clientsNames.forEach((clientArray, clientName) => {
|
||||
// console.log(`Clients with name ${clientName}:`);
|
||||
|
||||
// // clientArray.forEach((client) => {
|
||||
// this.clientsNames[clientName]
|
||||
// // .forEach(client => {
|
||||
// // // if(client.id != user.id)
|
||||
// // // {
|
||||
// // console.log("send to someone")
|
||||
// // console.log(client); // Perform actions on each client
|
||||
// // // clients.emit('message', payload)
|
||||
// // client.emit('message')
|
||||
// // // }
|
||||
// // });
|
||||
|
||||
// // .forEach((client) => {
|
||||
// // if(client.id != user.id)
|
||||
// // {
|
||||
// // console.log("send to someone")
|
||||
// // console.log(client); // Perform actions on each client
|
||||
// // // clients.emit('message', payload)
|
||||
// // client.emit('message')
|
||||
// // }
|
||||
// });
|
||||
// };
|
||||
|
||||
@SubscribeMessage('sendMessage')
|
||||
handleMessage(client: Socket, payload: any): void {
|
||||
// console.log(`message received: ${payload}`);
|
||||
// console.log(`message sender: ${payload.sender}`);
|
||||
// console.log(`client id: ${client.id}`);
|
||||
// console.log(`conversation ID: ${payload.convId}`);
|
||||
// console.log(`members: ${payload.members}`);
|
||||
console.log(`message sender: ${payload.sender}`);
|
||||
console.log(`client id: ${client.id}`);
|
||||
console.log(`conversation ID: ${payload.convId}`);
|
||||
console.log(`members: ${payload.members}`);
|
||||
|
||||
this.clientsNames.forEach((clientArray, clientName) =>
|
||||
{
|
||||
// console.log(` 5Clients with name ${clientName}:`);
|
||||
console.log(` 5Clients with name ${clientName}:`);
|
||||
if (payload.members.includes(clientName))
|
||||
{
|
||||
clientArray.forEach((targetClient, index) =>
|
||||
{
|
||||
// console.log(`client id: ${client.id}`);
|
||||
// console.log(`target: ${targetClient}`);
|
||||
// console.log(`target id: ${targetClient}`);
|
||||
console.log(`client id: ${client.id}`);
|
||||
console.log(`target: ${targetClient}`);
|
||||
console.log(`target id: ${targetClient}`);
|
||||
if (targetClient && targetClient !== client.id)
|
||||
{
|
||||
// console.log("Sending to someone");
|
||||
// console.log(`index= ${index}`);
|
||||
// console.log(`target: ${targetClient}`); // Perform actions on each target client
|
||||
console.log("Sending to someone");
|
||||
console.log(`index= ${index}`);
|
||||
console.log(`target: ${targetClient}`); // Perform actions on each target client
|
||||
// targetClient.emit('message')
|
||||
// this.clientsNames[clientName].emit('message')
|
||||
// this.clientsNames["apommier"].emit('message')
|
||||
this.clients[targetClient].emit('message', payload)
|
||||
|
||||
// console.log(test)
|
||||
// console.log(test)
|
||||
// this.clientsNames[clientName][index].emit('message');
|
||||
// const socket = this.server.sockets.sockets.get(targetClient.id);
|
||||
// if (socket) {
|
||||
// socket.emit('message', payload);
|
||||
// } else {
|
||||
// console.log(`Socket with ID ${client.id} not found.`);
|
||||
// }
|
||||
// targetClient.emit('message', payload);
|
||||
// targetClient.emit('message', payload);
|
||||
}
|
||||
else {
|
||||
console.log("not sending");
|
||||
@ -186,3 +193,41 @@ muteUser(client: any, payload: any): void {
|
||||
|
||||
|
||||
|
||||
|
||||
// for (let key in this.clientsNames) {
|
||||
// if (payload.members.includes(key)) {
|
||||
// console.log("Key exists in the array");
|
||||
// // if (key !== payload.sender)
|
||||
// // {
|
||||
// for (let key2 in this.clientsNames[key])
|
||||
// {
|
||||
// if (client.id !== this.clientsNames[key][key2])
|
||||
// {
|
||||
// console.log("send to someone")
|
||||
// this.clientsNames[key][key2].emit('message', payload)
|
||||
// }
|
||||
// }
|
||||
// // }
|
||||
// //if member socket different from mine
|
||||
// //send
|
||||
// } else {
|
||||
// console.log("Key does not exist in the array");
|
||||
// }
|
||||
//if key is in member
|
||||
|
||||
// let socket = this.clients[key];
|
||||
// console.log("Clé:", key);
|
||||
// console.log("Socket:", socket);
|
||||
// }
|
||||
// payload.convId // conv user instead ?
|
||||
//find user to send message to
|
||||
//const res = {
|
||||
//convId: payload.convId
|
||||
//sender: payload.sender
|
||||
|
||||
// }
|
||||
//while (user of conv)//how to get conv user
|
||||
// if (user connected)
|
||||
//send res to user
|
||||
// }
|
||||
|
||||
|
||||
@ -1,26 +1,7 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* pong.gateway.ts :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/19 15:18:38 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/23 15:19:12 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
import { SubscribeMessage, WebSocketGateway, OnGatewayInit, WebSocketServer, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
|
||||
import { Server, Socket } from 'socket.io';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
// Connection/Disconnection
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
|
||||
@WebSocketGateway({ cors: true })
|
||||
export class PongGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
|
||||
@WebSocketServer() server: Server;
|
||||
@ -50,82 +31,50 @@ export class PongGateway implements OnGatewayInit, OnGatewayConnection, OnGatewa
|
||||
|
||||
handleDisconnect(client: Socket)
|
||||
{
|
||||
console.log(`Normal disconnected: ${client.id}`);
|
||||
|
||||
this.waitingClients.forEach((item) => {
|
||||
if (item.client === client)
|
||||
this.waitingClients.delete(item);
|
||||
});
|
||||
|
||||
// Delete the socket from the 'games' map
|
||||
this.games.forEach((sockets, gameId) => {
|
||||
const index = sockets.indexOf(client);
|
||||
if (index !== -1)
|
||||
{
|
||||
if (index === 0)
|
||||
{
|
||||
console.log("emit boy1")
|
||||
sockets[1].emit("pong:win")
|
||||
// sockets[0].emit("/win")
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("emit boy2")
|
||||
sockets[0].emit("pong:win")
|
||||
// sockets[1].emit("/win")
|
||||
}
|
||||
this.games.delete(gameId);
|
||||
console.log(`Client disconnected: ${client.id}`);
|
||||
// this.waitingClients.delete(client);
|
||||
this.waitingClients.forEach((waitingClient) => {
|
||||
if (waitingClient.client === client) {
|
||||
this.waitingClients.delete(waitingClient);
|
||||
}})
|
||||
delete this.clients[client.id];
|
||||
}
|
||||
})
|
||||
|
||||
console.log(`Total connected clients: ${Object.keys(this.clients).length}`);
|
||||
}
|
||||
|
||||
// @SubscribeMessage('pong:matchmaking')
|
||||
// addMatchmaking(client: Socket, payload: any): void
|
||||
// {
|
||||
// console.log("matchmaking");
|
||||
// console.log(payload);
|
||||
// // this.waitingClients.add(client);
|
||||
// this.waitingClients.add(client);
|
||||
// console.log("Adding client to waiting list...");
|
||||
// if (this.waitingClients.size >= 2) {
|
||||
// console.log("Creating new game...");
|
||||
// const players = Array.from(this.waitingClients).slice(0, 2);
|
||||
// players.forEach((player) => {
|
||||
// this.waitingClients.delete(player);
|
||||
// });
|
||||
// const gameId = uuidv4();
|
||||
// this.games.set(gameId, players);
|
||||
// players.forEach((player) => {
|
||||
// player.join(gameId);
|
||||
// console.log(`Player ${player.id} joined game ${gameId}`);
|
||||
// });
|
||||
// players.forEach((player) => {
|
||||
// // const playersIds = game.map(socket => socket.id);
|
||||
// player.emit('pong:gameId', gameId);
|
||||
// });
|
||||
// }
|
||||
// // console.log(`from: ${client.id}`);
|
||||
// }
|
||||
@SubscribeMessage('pong:invite')
|
||||
createPrivateGame(client: Socket, payload: any): void {
|
||||
//after invite accepted ?
|
||||
//set the two user in a game ?
|
||||
|
||||
@SubscribeMessage('pong:disconnect')
|
||||
disconnectClient(client: Socket, payload: any): void {
|
||||
console.log("disconnect forced client= ", client.id)
|
||||
|
||||
for (const key in this.clients) {
|
||||
if (this.clients.hasOwnProperty(key) && this.clients[key] === client)
|
||||
delete this.clients[key];
|
||||
}
|
||||
// Delete the socket from the 'waitingClients' set
|
||||
this.waitingClients.forEach((item) => {
|
||||
if (item.client === client)
|
||||
this.waitingClients.delete(item);
|
||||
});
|
||||
|
||||
// Delete the socket from the 'games' map
|
||||
this.games.forEach((sockets, gameId) => {
|
||||
const index = sockets.indexOf(client);
|
||||
if (index !== -1)
|
||||
{
|
||||
if (index === 0)
|
||||
{
|
||||
console.log("emit boy1")
|
||||
sockets[1].emit("pong:win")
|
||||
// sockets[0].emit("/win")
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("emit boy2")
|
||||
sockets[0].emit("pong:win")
|
||||
// sockets[1].emit("/win")
|
||||
}
|
||||
this.games.delete(gameId);
|
||||
delete this.clients[client.id];
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
// Matchmaking
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
|
||||
@SubscribeMessage('pong:matchmaking')
|
||||
addMatchmaking(client: Socket, payload: any): void {
|
||||
@ -142,7 +91,6 @@ addMatchmaking(client: Socket, payload: any): void {
|
||||
waitingClient.option === payload.option && waitingClient.client !== client
|
||||
);
|
||||
|
||||
|
||||
if (matchingClients.length > 0) {
|
||||
console.log("Creating new game...");
|
||||
const players = [matchingClients[0].client, client]; // Add the current client to the players array
|
||||
@ -169,76 +117,43 @@ addMatchmaking(client: Socket, payload: any): void {
|
||||
player.emit('pong:gameId', gameId);
|
||||
});
|
||||
}
|
||||
|
||||
// console.log(`from: ${client.id}`);
|
||||
}
|
||||
|
||||
// @SubscribeMessage('pong:message')
|
||||
// handleMessage(client: Socket, payload: any): void
|
||||
// {
|
||||
// console.log(`from: ${client.id}`);
|
||||
// console.log(payload);
|
||||
|
||||
// const game = this.games.get(payload.gameId);
|
||||
// const playersIds = game.map(socket => socket.id);
|
||||
// // const players = Object.keys(game);
|
||||
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
// Private Match
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
// // if (Object.keys(this.clients).length === 2)
|
||||
// // {
|
||||
// // const clientIds = Object.keys(this.clients);
|
||||
// // console.log(`id of 0= ${clientIds[0]}`);
|
||||
|
||||
// // payload.ballX
|
||||
// // payload.ballY
|
||||
// // payload.
|
||||
|
||||
|
||||
// @SubscribeMessage('pong:invite')
|
||||
// createPrivateGame(client: Socket, payload: any): void {
|
||||
// //after invite accepted ?
|
||||
// //set the two user in a game ?
|
||||
|
||||
// if (clientIds[0] === payload.id)
|
||||
// {
|
||||
// // console.log("client 0 true");
|
||||
// if (payload.ballX <= payload.width / 2)
|
||||
// this.clients[clientIds[1]].emit('pong:info', payload);
|
||||
// }
|
||||
// else if (clientIds[1] === payload.id)
|
||||
// {
|
||||
// if (payload.ballX < payload.width / 2)
|
||||
// this.clients[clientIds[0]].emit('pong:info', payload);
|
||||
// // console.log("client 0 true");
|
||||
// }
|
||||
// // }
|
||||
// console.log("END OF HANDLE");
|
||||
// }
|
||||
|
||||
|
||||
@SubscribeMessage('pong:joinParty')
|
||||
joinPrivateParty(client: Socket, payload: any): void {
|
||||
console.log(" join PrivateParty")
|
||||
|
||||
const game = this.games.get(payload.gameId);
|
||||
if (game)
|
||||
{
|
||||
game.push(client);
|
||||
const playersIds = game.map(socket => socket.id);
|
||||
this.clients[playersIds[0]].emit('pong:gameId', payload.gameId);
|
||||
this.clients[playersIds[1]].emit('pong:gameId', payload.gameId);
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("emit else")
|
||||
client.emit("pong:win")
|
||||
}
|
||||
// console.log("no game ???")
|
||||
|
||||
}
|
||||
|
||||
|
||||
@SubscribeMessage('pong:privateParty')
|
||||
addPrivateParty(client: Socket, payload: any): void {
|
||||
console.log("addPrivateParty")
|
||||
|
||||
const gameId = uuidv4();
|
||||
const players = [client];
|
||||
this.games.set(gameId, players);
|
||||
console.log("game created private")
|
||||
client.emit('pong:privateId', gameId);
|
||||
//create game
|
||||
//emit private gameId to canvas (don't launch canvas)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
// In Game
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
|
||||
|
||||
|
||||
@SubscribeMessage('pong:power')
|
||||
sendPower(client: Socket, payload: any): void
|
||||
@ -276,6 +191,29 @@ addPrivateParty(client: Socket, payload: any): void {
|
||||
console.log("END OF HANDLE");
|
||||
}
|
||||
|
||||
// @SubscribeMessage('pong:forced')
|
||||
// forcedMessage(client: Socket, payload: any): void
|
||||
// {
|
||||
// console.log(`from: ${client.id}`);
|
||||
// console.log(payload);
|
||||
|
||||
// if (Object.keys(this.clients).length === 2)
|
||||
// {
|
||||
// const clientIds = Object.keys(this.clients);
|
||||
// console.log(`id of 0= ${clientIds[0]}`);
|
||||
|
||||
// if (clientIds[0] === payload.id)
|
||||
// {
|
||||
// this.clients[clientIds[1]].emit('pong:info', payload);
|
||||
// }
|
||||
// else if (clientIds[1] === payload.id)
|
||||
// {
|
||||
// this.clients[clientIds[0]].emit('pong:info', payload);
|
||||
// }
|
||||
// }
|
||||
// console.log("END OF HANDLE");
|
||||
// }
|
||||
|
||||
@SubscribeMessage('pong:forced')
|
||||
forcedMessage(client: Socket, payload: any): void
|
||||
{
|
||||
@ -298,6 +236,29 @@ addPrivateParty(client: Socket, payload: any): void {
|
||||
console.log("END OF HANDLE");
|
||||
}
|
||||
|
||||
// @SubscribeMessage('pong:paddle')
|
||||
// handlePaddle(client: Socket, payload: any): void
|
||||
// {
|
||||
// console.log(`from: ${client.id}`);
|
||||
// console.log(payload);
|
||||
|
||||
// if (Object.keys(this.clients).length === 2)
|
||||
// {
|
||||
// const clientIds = Object.keys(this.clients);
|
||||
// console.log(`id of 0= ${clientIds[0]}`);
|
||||
|
||||
// if (clientIds[0] === payload.id)
|
||||
// {
|
||||
// this.clients[clientIds[1]].emit('pong:paddle', payload);
|
||||
// }
|
||||
// else if (clientIds[1] === payload.id)
|
||||
// {
|
||||
// this.clients[clientIds[0]].emit('pong:paddle', payload);
|
||||
// }
|
||||
// }
|
||||
// console.log("END OF HANDLE");
|
||||
// }
|
||||
|
||||
@SubscribeMessage('pong:paddle')
|
||||
handlePaddle(client: Socket, payload: any): void
|
||||
{
|
||||
|
||||
@ -1,5 +1,3 @@
|
||||
REACT_APP_BASE_URL=localhost:8080
|
||||
REACT_APP_API_SECRET=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
|
||||
REACT_APP_CLIENT_UID=u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41
|
||||
# REACT_APP_BASE_URL=92.143.191.152
|
||||
# REACT_APP_BASE_URL=localhost
|
||||
REACT_APP_BASE_URL=92.143.191.152
|
||||
# REACT_APP_BASE_URL=192.168.1.19
|
||||
2
containers/react/assets.d.ts
vendored
2
containers/react/assets.d.ts
vendored
@ -1,2 +0,0 @@
|
||||
declare module '*.jpg';
|
||||
declare module 'styled-components'
|
||||
@ -1,48 +0,0 @@
|
||||
export interface User {
|
||||
id: number;
|
||||
otp_enabled: boolean;
|
||||
otp_verified: boolean;
|
||||
otp_base32: string;
|
||||
nickname: string;
|
||||
username: string;
|
||||
photo: Buffer;
|
||||
password: string;
|
||||
win: number;
|
||||
loss: number;
|
||||
rank: number;
|
||||
status: number;
|
||||
userId: number;
|
||||
friendRequest: string[];
|
||||
partyInvite: Record<string, string>[];
|
||||
friends: string[];
|
||||
blocked: string[];
|
||||
}
|
||||
|
||||
export interface Conv {
|
||||
id: number;
|
||||
members?: string[];
|
||||
name: string
|
||||
group: boolean
|
||||
private: boolean
|
||||
banned?: string[];
|
||||
muted?: string[];
|
||||
admin?: string[];
|
||||
owner?: string;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
id: number;
|
||||
convId: number;
|
||||
sender: string;
|
||||
text: string;
|
||||
createdAt?: Date;
|
||||
}
|
||||
|
||||
export interface Matchlog {
|
||||
id: number;
|
||||
opponent: string;
|
||||
myScore: number;
|
||||
opScore: number;
|
||||
parent: User;
|
||||
}
|
||||
15
containers/react/package-lock.json
generated
15
containers/react/package-lock.json
generated
@ -25,9 +25,6 @@
|
||||
"styled-components": "^5.3.10",
|
||||
"typescript": "^3.2.1",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.3.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@adobe/css-tools": {
|
||||
@ -4538,9 +4535,9 @@
|
||||
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz",
|
||||
"integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg=="
|
||||
"version": "20.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz",
|
||||
"integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q=="
|
||||
},
|
||||
"node_modules/@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
@ -24455,9 +24452,9 @@
|
||||
"integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "20.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.1.tgz",
|
||||
"integrity": "sha512-EhcH/wvidPy1WeML3TtYFGR83UzjxeWRen9V402T8aUGYsCHOmfoisV3ZSg03gAFIbLq8TnWOJ0f4cALtnSEUg=="
|
||||
"version": "20.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.1.4.tgz",
|
||||
"integrity": "sha512-At4pvmIOki8yuwLtd7BNHl3CiWNbtclUbNtScGx4OHfBd4/oWoJC8KRCIxXwkdndzhxOsPXihrsOoydxBjlE9Q=="
|
||||
},
|
||||
"@types/parse-json": {
|
||||
"version": "4.0.0",
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "HOST=0.0.0.0 PORT=8001 react-scripts start",
|
||||
"start": "HOST=0.0.0.0 PORT=8080 react-scripts start",
|
||||
"start:dev": "npm run start --watch",
|
||||
"build": "react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
@ -45,8 +45,5 @@
|
||||
"last 1 firefox version",
|
||||
"last 1 safari version"
|
||||
]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.3.1"
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 49 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 42 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 149 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 59 KiB |
@ -2,7 +2,6 @@ import Backdrop from "../Sidebar/Backdrop.tsx"
|
||||
import { motion } from 'framer-motion'
|
||||
import { AiOutlineCheckCircle } from "react-icons/ai";
|
||||
import '../../styles/Messages.css'
|
||||
import React from "react";
|
||||
|
||||
|
||||
const dropIn = {
|
||||
@ -17,19 +16,14 @@ const dropIn = {
|
||||
},
|
||||
};
|
||||
|
||||
interface AlertProps {
|
||||
handleClose: Function,
|
||||
text: string
|
||||
}
|
||||
|
||||
function GreenAlert ({handleClose, text}: AlertProps){
|
||||
function GreenAlert ({handleClose, text}){
|
||||
|
||||
return(
|
||||
<Backdrop onClick={handleClose}>
|
||||
<Backdrop>
|
||||
<motion.div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="greenAlert"
|
||||
// variant={dropIn}
|
||||
variant={dropIn}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
|
||||
@ -2,7 +2,6 @@ import Backdrop from "../Sidebar/Backdrop.tsx"
|
||||
import { motion } from 'framer-motion'
|
||||
import { BiErrorCircle } from "react-icons/bi";
|
||||
import '../../styles/Messages.css'
|
||||
import React from "react";
|
||||
|
||||
|
||||
const dropIn = {
|
||||
@ -17,18 +16,13 @@ const dropIn = {
|
||||
},
|
||||
};
|
||||
|
||||
interface AlertProps {
|
||||
handleClose: Function,
|
||||
text: string
|
||||
}
|
||||
|
||||
function RedAlert ({handleClose, text}: AlertProps) {
|
||||
function RedAlert ({handleClose, text}) {
|
||||
return(
|
||||
<Backdrop onClick={handleClose}>
|
||||
<Backdrop>
|
||||
<motion.div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="redAlert"
|
||||
// variant={dropIn}
|
||||
variant={dropIn}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
|
||||
@ -2,9 +2,6 @@ import Backdrop from "../Sidebar/Backdrop.tsx"
|
||||
import { motion } from 'framer-motion'
|
||||
import { GrTrophy } from "react-icons/gr";
|
||||
import '../../styles/Messages.css'
|
||||
import React from "react";
|
||||
import { MdQrCodeScanner } from "react-icons/md";
|
||||
import { GiCrownedSkull, GiWingedSword } from "react-icons/gi";
|
||||
|
||||
const dropIn = {
|
||||
hidden: {
|
||||
@ -18,40 +15,19 @@ const dropIn = {
|
||||
},
|
||||
};
|
||||
|
||||
interface AlertProps {
|
||||
handleClose: Function,
|
||||
text: string,
|
||||
icon: number
|
||||
}
|
||||
|
||||
function YellowAlert ({handleClose, text, icon}: AlertProps) {
|
||||
function YellowAlert ({handleClose, text}) {
|
||||
return(
|
||||
<Backdrop onClick={handleClose}>
|
||||
<Backdrop>
|
||||
<motion.div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="yellowAlert"
|
||||
// variant={dropIn}
|
||||
variant={dropIn}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
>
|
||||
|
||||
{icon === 0 ? (
|
||||
<GrTrophy/>
|
||||
):("")}
|
||||
{icon === 1 ? (
|
||||
<MdQrCodeScanner/>
|
||||
):("")}
|
||||
|
||||
{icon === 2 ? (
|
||||
<GiCrownedSkull/>
|
||||
):("")}
|
||||
|
||||
{icon === 3 ? (
|
||||
<GiWingedSword/>
|
||||
):("")}
|
||||
|
||||
<h5>{text}</h5>
|
||||
<p>{text}</p>
|
||||
</motion.div>
|
||||
{setTimeout(handleClose, 3000)}
|
||||
</Backdrop>
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import React from "react";
|
||||
import {Routes, Route} from 'react-router-dom';
|
||||
import Home from "../pages/Home.jsx";
|
||||
import PlayButton from "./Game/PlayButton.tsx";
|
||||
import PlayButton from "../pages/PlayButton.js";
|
||||
import Field from "../pages/Field";
|
||||
import Login42 from "../pages/Login42.js";
|
||||
import Messages from "../pages/Messages.jsx";
|
||||
@ -13,11 +13,11 @@ function AnimatedRoute () {
|
||||
return (
|
||||
<AnimatePresence>
|
||||
<Routes location={location} key={location.pathname}>
|
||||
<Route path="/" element={<Home/>}/>
|
||||
<Route exact path="/" element={<Home/>}/>
|
||||
<Route path="/game" element={<PlayButton />}/>
|
||||
<Route path="/pong/play" element={<Field />}/>
|
||||
<Route path="/login42" element={<Login42 />}/>
|
||||
<Route path="/messages" element={<Messages />}/>
|
||||
<Route exact path="/pong/play" element={<Field />}/>
|
||||
<Route exact path="/login42" element={<Login42 />}/>
|
||||
<Route exact path="/messages" element={<Messages />}/>
|
||||
</Routes>
|
||||
</AnimatePresence>
|
||||
)
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import '../../styles/field.css';
|
||||
// import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from "react-router-dom";
|
||||
@ -14,18 +13,18 @@ function PlayButton() {
|
||||
const handleButtonClick = () => {
|
||||
let path = `play?`;
|
||||
|
||||
const superpowerCheckbox = document.querySelector<HTMLInputElement>('input[value="superpower"]');
|
||||
if (superpowerCheckbox && superpowerCheckbox.checked) {
|
||||
const superpowerCheckbox = document.querySelector('input[value="superpower"]');
|
||||
if (superpowerCheckbox.checked) {
|
||||
path += 'superpower=true&';
|
||||
}
|
||||
|
||||
const obstacleCheckbox = document.querySelector<HTMLInputElement>('input[value="obstacle"]');
|
||||
if (obstacleCheckbox && obstacleCheckbox.checked) {
|
||||
const obstacleCheckbox = document.querySelector('input[value="obstacle"]');
|
||||
if (obstacleCheckbox.checked) {
|
||||
path += 'obstacle=true&';
|
||||
}
|
||||
|
||||
const speedCheckbox = document.querySelector<HTMLInputElement>('input[value="speed"]');
|
||||
if (speedCheckbox && speedCheckbox.checked) {
|
||||
const speedCheckbox = document.querySelector('input[value="speed"]');
|
||||
if (speedCheckbox.checked) {
|
||||
path += 'speed=true&';
|
||||
}
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Rank.tsx :+: :+: :+: */
|
||||
/* Rank.jsx :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/09 08:49:24 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/20 13:06:35 by apommier ### ########.fr */
|
||||
/* Updated: 2023/06/09 08:55:22 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -15,15 +15,8 @@ import React, { useState, useEffect, useRef } from "react";
|
||||
// import {Rank} from '../../DataBase/DataRank.js'
|
||||
import DefaultPicture from '../../assets/profile.jpg'
|
||||
import api from '../../script/axiosApi.tsx';
|
||||
import {Matchlog, User} from "../../../interfaces.tsx"
|
||||
// import { Match } from "@testing-library/react";
|
||||
|
||||
interface RankProps {
|
||||
user: User
|
||||
index: number
|
||||
}
|
||||
|
||||
function Rank({user, index}: RankProps){
|
||||
function Rank({user, index}){
|
||||
|
||||
const [profilePicture, setProfilePicture] = useState('');
|
||||
|
||||
@ -43,12 +36,10 @@ function Rank({user, index}: RankProps){
|
||||
fetchProfilePicture();
|
||||
})
|
||||
|
||||
// console.log(index);
|
||||
return (
|
||||
<div className='rank_elements'>
|
||||
<div>
|
||||
{/* <p>{(index + 1).toString()}</p> */}
|
||||
<p>{(index + 1)}</p>
|
||||
<p>{index + 1}</p>
|
||||
<h4>{user.rank}: {user.nickname}
|
||||
{profilePicture ? (
|
||||
<img className="profilePic" src={`data:image/jpeg;base64,${profilePicture}`} />
|
||||
@ -58,7 +49,7 @@ function Rank({user, index}: RankProps){
|
||||
{/* <img className="profilePic" src={defaultpic}/> */}
|
||||
</h4>
|
||||
</div>
|
||||
{/* <h4 className='content'>{user.opponent}</h4> */}
|
||||
<h4 className='content'>{user.opponent}</h4>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -3,12 +3,11 @@ import React, { useState, useEffect, useRef } from "react";
|
||||
import Rank from './Rank.tsx'
|
||||
import defaultpic from '../../assets/profile.jpg'
|
||||
import api from '../../script/axiosApi.tsx';
|
||||
import {User} from "../../../interfaces.tsx"
|
||||
|
||||
function Ranking(){
|
||||
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [ranking, setRanking] = useState<User[]>([]);
|
||||
const [ranking, setRanking] = useState([]);
|
||||
|
||||
useEffect(()=> {
|
||||
|
||||
@ -42,7 +41,16 @@ function Ranking(){
|
||||
// <h1 className='title'>Ranking</h1>
|
||||
<div className='scroll'>
|
||||
{ranking.map((user, index) => (
|
||||
<Rank user={user} index={index} key={user.username}/>
|
||||
<Rank user={user} index={index}/>
|
||||
// return (
|
||||
// <div className='rank_elements'>
|
||||
// <div>
|
||||
// <p>{index + 1}</p>
|
||||
// <h4>{user.rank}: {user.nickname} <img className="profilePic" src={defaultpic}/></h4>
|
||||
// </div>
|
||||
// <h4 className='content'>{user.opponent}</h4>
|
||||
// </div>
|
||||
// )
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@ -4,14 +4,10 @@ import {Link} from 'react-router-dom';
|
||||
import DefaultPicture from '../assets/profile.jpg'
|
||||
import { motion, AnimatePresence } from 'framer-motion'
|
||||
import Modal from './Sidebar/Modal.tsx';
|
||||
import YellowAlert from './Alert/YellowAlert.tsx';
|
||||
import '../styles/Header.css';
|
||||
|
||||
import api from '../script/axiosApi.tsx';
|
||||
|
||||
import { MdQrCodeScanner } from 'react-icons/md';
|
||||
import { GiWingedSword, GiCrownedSkull } from 'react-icons/gi';
|
||||
|
||||
function Header() {
|
||||
// const [sidebar, setSidebar] = useState(false);
|
||||
// const showSidebar = () => setSidebar(!sidebar);
|
||||
@ -19,8 +15,6 @@ function Header() {
|
||||
const close = () => setModalOpen(false);
|
||||
const open = () => setModalOpen(true);
|
||||
|
||||
const [success, setSuccess] = useState([]);
|
||||
|
||||
const [profilePicture, setProfilePicture] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
@ -29,8 +23,6 @@ function Header() {
|
||||
const user = await api.get("/profile");
|
||||
const pic = await api.post("/getPicture", {username: user.data.username})
|
||||
setProfilePicture(pic.data);
|
||||
// console.log("test ===", user.data)
|
||||
setSuccess(user.data);
|
||||
// console.log(`profile pic222= ${pic.data}`)
|
||||
} catch (error) {
|
||||
console.error('Error fetching profile picture:', error);
|
||||
@ -40,6 +32,10 @@ function Header() {
|
||||
fetchProfilePicture();
|
||||
}, []);
|
||||
|
||||
// console.log(`profile pic= ${profilePicture}`)
|
||||
|
||||
// photo.toString('base64')
|
||||
|
||||
return (
|
||||
<div className='Header'>
|
||||
<motion.div
|
||||
@ -49,7 +45,6 @@ function Header() {
|
||||
</Link>
|
||||
</motion.div>
|
||||
<div className='end'>
|
||||
|
||||
<Link to="/profile" className='menu-bars'>
|
||||
<div>
|
||||
|
||||
@ -67,7 +62,7 @@ function Header() {
|
||||
<AnimatePresence
|
||||
initial={false}
|
||||
onExitComplete={() => null}>
|
||||
{modalOpen && <Modal handleclose={close}/>}
|
||||
{modalOpen && <Modal modalOpen={modalOpen} handleclose={close}/>}
|
||||
</AnimatePresence>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,12 +1,11 @@
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import io, { Socket } from 'socket.io-client';
|
||||
import io from 'socket.io-client';
|
||||
import '../../styles/Messages.css'
|
||||
import styled from "styled-components";
|
||||
import DefaultPic from '../../assets/profile.jpg'
|
||||
import api from '../../script/axiosApi.tsx';
|
||||
import { motion , AnimatePresence} from "framer-motion";
|
||||
import Modal from "./Modal.tsx";
|
||||
import GameModal from "./GameModal.tsx";
|
||||
|
||||
import Message from "./Message.tsx"
|
||||
// import Input from "./Input";
|
||||
@ -18,15 +17,12 @@ import { MdOutlineGroupAdd } from 'react-icons/md';
|
||||
import { GrAdd } from 'react-icons/gr';
|
||||
import { RiListSettingsLine } from 'react-icons/ri'
|
||||
|
||||
// import { Rank } from "../../DataBase/DataRank";
|
||||
import { Rank } from "../../DataBase/DataRank";
|
||||
import GreenAlert from "../Alert/GreenAlert.tsx";
|
||||
import RedAlert from "../Alert/RedAlert.tsx";
|
||||
import YellowAlert from "../Alert/YellowAlert";
|
||||
import ModalSetting from "./ModalSetting.tsx";
|
||||
import PartyInvite from "./PartyInvite.tsx";
|
||||
|
||||
// import {User, Conv, Message} from "../../../interfaces.tsx"
|
||||
import {User, Conv} from "../../../interfaces.tsx"
|
||||
|
||||
const TouchDiv = styled.div`
|
||||
margin-left: 10px;
|
||||
@ -74,31 +70,20 @@ const SideP = styled.p`
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
|
||||
interface MessageProps {
|
||||
id: number;
|
||||
convId: number;
|
||||
sender: string;
|
||||
text: string;
|
||||
createdAt?: Date;
|
||||
}
|
||||
|
||||
function Chats(){
|
||||
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [conversations, setConversation] = useState([]);
|
||||
const [partyInvite, setPartyInvite] = useState([]);
|
||||
const [user, setUser] = useState<User>();
|
||||
const [currentChat, setCurrentChat] = useState<Conv>(); // false is good?
|
||||
const [isAdmin, setIsAdmin] = useState<boolean>(false); // false is good?
|
||||
const [user, setUser] = useState(null);
|
||||
const [currentChat, setCurrentChat] = useState(false); // false is good?
|
||||
const [isAdmin, setIsAdmin] = useState(false); // false is good?
|
||||
// const [currentChat, setCurrentChat] = useState(false); // false is good?
|
||||
const [messages, setMessage] = useState<MessageProps[]>([]);
|
||||
const [messages, setMessage] = useState([]);
|
||||
const [newMessages, setNewMessage] = useState("");
|
||||
const [incomingMessage, setIncomingMessage] = useState<MessageProps>();
|
||||
const [incomingMessage, setIncomingMessage] = useState("");
|
||||
const socket = useRef();
|
||||
|
||||
// let socket: Socket;
|
||||
const socket = useRef<Socket | null>(null);
|
||||
// const socket = Socket<DefaultEventsMap, DefaultEventsMap> | null
|
||||
// socket = useRef( useRef<SocketIOClient.Socket | null>(null));
|
||||
|
||||
|
||||
useEffect(()=> {
|
||||
@ -106,55 +91,29 @@ function Chats(){
|
||||
const getConv = async ()=>{
|
||||
try{
|
||||
const convs = await api.get("/conv")
|
||||
const tmpInvite = await api.get("/partyInvite")
|
||||
const tmpUser = await api.get("/profile")
|
||||
const tmpUsers = await api.get("/users");
|
||||
|
||||
console.log(convs);
|
||||
|
||||
// console.log("invite data use effect= ", tmpInvite.data);
|
||||
setPartyInvite(tmpInvite.data);
|
||||
setUser(tmpUser.data);
|
||||
setConversation(convs.data);
|
||||
setUsers(tmpUsers.data);
|
||||
|
||||
// console.log(`connection....`);
|
||||
socket.current = io('http://' + process.env.REACT_APP_BASE_URL + ':4001', { transports: ['polling'] });
|
||||
// console.log(`connection done`);
|
||||
socket.current = io('http://' + process.env.REACT_APP_BASE_URL + ':4001');
|
||||
console.log(`connection....`);
|
||||
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 ?
|
||||
console.log(`message received data= ${data.sender}`)
|
||||
console.log(`message received data= ${data.convId}`)
|
||||
console.log(`message received data= ${data.sender}`)
|
||||
console.log(`current chat = ${currentChat}`)
|
||||
setIncomingMessage(data);
|
||||
});
|
||||
|
||||
socket.current.on('ban', (data) => {
|
||||
// setIncomingMessage(data);
|
||||
console.log("banned hehe");
|
||||
window.location.reload()
|
||||
});
|
||||
|
||||
socket.current.on('mute', (data) => {
|
||||
console.log("muted hehe");
|
||||
//set mute var to true and do nothing
|
||||
});
|
||||
|
||||
setIsLoading(false)
|
||||
|
||||
}
|
||||
catch(err){
|
||||
console.log("ERRORRRRR")
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
getConv();
|
||||
|
||||
return () => {
|
||||
console.log("Cleanup");
|
||||
if (socket.current)
|
||||
socket.current.disconnect();
|
||||
// cleanup(); // Call the cleanup function to stop the ongoing process or perform necessary cleanup tasks
|
||||
// cleanup();
|
||||
};
|
||||
|
||||
}, [])
|
||||
|
||||
useEffect(()=> {
|
||||
@ -174,12 +133,9 @@ function Chats(){
|
||||
}
|
||||
}
|
||||
// console.log(`result1 = ${currentChat.id !== incomingMessage.convId}`)
|
||||
if (currentChat && incomingMessage && currentChat.id === incomingMessage.convId)
|
||||
if (currentChat !== null && currentChat.id === incomingMessage.convId)
|
||||
{
|
||||
console.log("incoming meaasge=",incomingMessage)
|
||||
// if (user && !user.blocked.find(incomingMessage.sender))
|
||||
// setMessage((prev) => [...prev, incomingMessage, key: incomingMessage.id]);
|
||||
// setMessage((prev) => [...prev, { ...incomingMessage, key: incomingMessage.id }]);
|
||||
|
||||
setMessage((prev) => [...prev, incomingMessage]);
|
||||
}
|
||||
}
|
||||
@ -190,13 +146,10 @@ function Chats(){
|
||||
useEffect(()=> {
|
||||
const getMessage = async ()=>
|
||||
{
|
||||
if (!currentChat)
|
||||
return ;
|
||||
const data = {convId: currentChat.id};
|
||||
|
||||
try {
|
||||
const res = await api.post('/getMessage', data);
|
||||
console.log("message of conv=", res.data)
|
||||
setMessage(res.data);
|
||||
} catch(err) {
|
||||
|
||||
@ -205,36 +158,30 @@ function Chats(){
|
||||
getMessage();
|
||||
}, [currentChat]);
|
||||
|
||||
const handleSubmit = async (e: { preventDefault: () => void; })=>{
|
||||
const handleSubmit = async (e)=>{
|
||||
e.preventDefault();
|
||||
// console.log(`e= ${e.key}`)
|
||||
// console.log(`name= ${user.username}`)
|
||||
// let message;
|
||||
if (!user || !currentChat)
|
||||
return ;
|
||||
const message = {
|
||||
sender: user.username,
|
||||
text: newMessages,
|
||||
convId: currentChat.id,
|
||||
members: null,
|
||||
id: null,
|
||||
members: null
|
||||
};
|
||||
try{
|
||||
const allowed = await api.post('/allowed', {convId: currentChat.id});
|
||||
console.log("convid:", currentChat.id);
|
||||
console.log(`id= ${currentChat.id}`)
|
||||
const allowed = await api.post('/allowed', {convId: message.convId, username: user.username});
|
||||
console.log("allowed= ", allowed.data)
|
||||
if (!allowed.data)
|
||||
{
|
||||
console.log("muted or banned");
|
||||
return ;
|
||||
}
|
||||
console.log("not muted or banned");
|
||||
const res = await api.post('/message', message);
|
||||
const convMember = await api.post('/member', message);
|
||||
message.members = convMember.data.members;
|
||||
message.id = res.data.id
|
||||
console.log(convMember);
|
||||
// console.log(`currentChat= ${currentChat.id}`)
|
||||
|
||||
setMessage([...messages, res.data]);
|
||||
setNewMessage("");
|
||||
if (socket.current)
|
||||
socket.current.emit('sendMessage', message);
|
||||
}
|
||||
catch(err){
|
||||
@ -242,28 +189,27 @@ function Chats(){
|
||||
}
|
||||
}
|
||||
|
||||
const handleKeyPress = async (e: { key: string; })=> {
|
||||
const handleKeyPress = async (e)=>{
|
||||
// console.log(`e in press= ${e.key}`)
|
||||
if (e.key !== "Enter")
|
||||
return ;
|
||||
// console.log(`name= ${user.username}`)
|
||||
if (!user || !currentChat)
|
||||
return ;
|
||||
const message = {
|
||||
sender: user.username,
|
||||
text: newMessages,
|
||||
convId: currentChat.id,
|
||||
members: null,
|
||||
id: null,
|
||||
members: null
|
||||
};
|
||||
try{
|
||||
console.log(`id= ${currentChat.id}`)
|
||||
const res = await api.post('/message', message);
|
||||
const convMember = await api.post('/member', message);
|
||||
message.members = convMember.data.members;
|
||||
message.id = res.data.id
|
||||
console.log(convMember);
|
||||
// console.log(`currentChat= ${currentChat.id}`)
|
||||
|
||||
setMessage([...messages, res.data]);
|
||||
setNewMessage("");
|
||||
if (socket.current)
|
||||
socket.current.emit('sendMessage', message);
|
||||
}
|
||||
catch(err){
|
||||
@ -274,7 +220,7 @@ function Chats(){
|
||||
|
||||
|
||||
const [friend, setFriend] = useState("");
|
||||
// const [modalOpen, setModalOpen] = useState(false);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [addFriend, setAddFriend] = useState(false);
|
||||
const [block, setBlock] = useState(false);
|
||||
|
||||
@ -282,32 +228,8 @@ function Chats(){
|
||||
const [showBlockAlert, setShowBlockAlert] = useState(false);
|
||||
|
||||
const [setting, setSetting] = useState(false);
|
||||
|
||||
const [newGameModalOpen, setNewGameModalOpen] = useState(false);
|
||||
const [newConversationModalOpen, setNewConversationModalOpen] = useState(false);
|
||||
|
||||
const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]);
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
|
||||
|
||||
const openNewGameModal = () => {
|
||||
setNewGameModalOpen(true);
|
||||
};
|
||||
|
||||
const closeNewGameModal = () => {
|
||||
setNewGameModalOpen(false);
|
||||
};
|
||||
|
||||
const openNewConversationModal = () => {
|
||||
setNewConversationModalOpen(true);
|
||||
};
|
||||
|
||||
const closeNewConversationModal = () => {
|
||||
setNewConversationModalOpen(false);
|
||||
};
|
||||
|
||||
// const close = () => setModalOpen(false);
|
||||
// const open = () => setModalOpen(true);
|
||||
const close = () => setModalOpen(false);
|
||||
const open = () => setModalOpen(true);
|
||||
// const closeAddFriend = () => setAddFriend(false);
|
||||
// const closeBlock = () => setBlock(false);
|
||||
const closeSetting = () => setSetting(false);
|
||||
@ -317,7 +239,7 @@ function Chats(){
|
||||
// const closeBlock = () => setBlock(false);
|
||||
|
||||
|
||||
const handleFriend = (event: { target: { value: React.SetStateAction<string>; }; }) => {
|
||||
const handleFriend = (event) => {
|
||||
setFriend(event.target.value);
|
||||
};
|
||||
|
||||
@ -369,15 +291,6 @@ function Chats(){
|
||||
setShowBlockAlert(false);
|
||||
};
|
||||
|
||||
const handleOptionChange = (selectId: number, selectedOption: string) => {
|
||||
console.log("selected Option=", selectedOption)
|
||||
setSelectTag((prevTags) =>
|
||||
prevTags.map((tag) =>
|
||||
tag.id === selectId ? { ...tag, selectedOption } : tag
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
// HTML
|
||||
@ -391,7 +304,7 @@ function Chats(){
|
||||
<div className='navbar'>
|
||||
<img src={DefaultPic} alt="profile" className="pic"/>
|
||||
<span>
|
||||
{isLoading || !user ? (
|
||||
{isLoading ? (
|
||||
<h4>Loading...</h4>
|
||||
) : (
|
||||
<h4>{user.nickname}</h4>
|
||||
@ -443,24 +356,7 @@ function Chats(){
|
||||
</div> */}
|
||||
|
||||
<div className="end">
|
||||
{selectTags.map((selectTag) => (
|
||||
<div key={selectTag.id}>
|
||||
<select
|
||||
value={selectTag.selectedOption}
|
||||
className="lookForFriends"
|
||||
onChange={(a) => handleOptionChange(selectTag.id, a.target.value)}
|
||||
>
|
||||
<option value="">{
|
||||
selectTag.selectedOption ? selectTag.selectedOption : "Select an option"
|
||||
}</option>
|
||||
{users.filter((item) => !selectTags.some((tag) => tag.selectedOption === item.username)).map((item, index) => (
|
||||
<option key={index} value={item.username}>
|
||||
{item.username}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
))}
|
||||
<input className="lookForFriends" type="text" value={friend} onChange={handleFriend} />
|
||||
<TouchDiv>
|
||||
<motion.div onClick={handleAddFriend}>
|
||||
<MdOutlineGroupAdd />
|
||||
@ -497,7 +393,7 @@ function Chats(){
|
||||
initial={false}
|
||||
onExitComplete={() => null}
|
||||
>
|
||||
{setting && <ModalSetting handleClose={closeSetting} convId={currentChat.id.toString()} socket={socket.current}/>}
|
||||
{setting && <ModalSetting handleClose={closeSetting} convId={currentChat.id}/>}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
</TouchDiv>
|
||||
@ -508,37 +404,18 @@ function Chats(){
|
||||
</div>
|
||||
<div className="messages_box">
|
||||
<div className="contact">
|
||||
|
||||
<UserChat>
|
||||
<motion.div className="newMessage" onClick={openNewGameModal}>
|
||||
<GrAdd />
|
||||
<span>New Game</span>
|
||||
</motion.div>
|
||||
{newGameModalOpen && <GameModal handleClose={closeNewGameModal} />}
|
||||
</UserChat>
|
||||
|
||||
<UserChat>
|
||||
<motion.div className="newMessage" onClick={openNewConversationModal}>
|
||||
<motion.div className="newMessage"
|
||||
onClick={() => (modalOpen ? close() : open())}
|
||||
>
|
||||
<GrAdd/>
|
||||
<span>New Conversation</span>
|
||||
</motion.div>
|
||||
{newConversationModalOpen && (
|
||||
<Modal handleClose={closeNewConversationModal} />
|
||||
)}
|
||||
{modalOpen && <Modal modalOpen={modalOpen} handleClose={close}/>}
|
||||
|
||||
</UserChat>
|
||||
|
||||
|
||||
{/* {partyInvite.map((c) => {
|
||||
return (
|
||||
|
||||
)})
|
||||
} */}
|
||||
|
||||
{partyInvite.map( i =>(
|
||||
<PartyInvite currentInvite={i}/>
|
||||
))}
|
||||
|
||||
{conversations.map((c: Conv, index ) => {
|
||||
{conversations.map((c, index ) => {
|
||||
return (
|
||||
<div key={index}
|
||||
onClick={() => setCurrentChat(c)}>
|
||||
@ -546,7 +423,7 @@ function Chats(){
|
||||
<img className="pic-user" src={DefaultPic} alt="User" />
|
||||
<div className="infoSideBar">
|
||||
<span>{c.name}</span>
|
||||
{/* <SideP>Desc?</SideP> */}
|
||||
<SideP>Desc?</SideP>
|
||||
</div>
|
||||
</UserChat>
|
||||
</div>
|
||||
@ -555,12 +432,12 @@ function Chats(){
|
||||
</div>
|
||||
|
||||
{
|
||||
currentChat && user ? (
|
||||
currentChat ? (
|
||||
<>
|
||||
<div className="messages">
|
||||
<div className="scroll">
|
||||
{messages.map(m=>(
|
||||
<Message key={m.id} message= {m} own={m.sender === user.username}/>
|
||||
<Message message = {m} own={m.sender === user.username} user={m}/>
|
||||
))}
|
||||
</div>
|
||||
{/* <Input/> */}
|
||||
|
||||
@ -1,152 +0,0 @@
|
||||
import { motion } from "framer-motion";
|
||||
import Backdrop from "../Sidebar/Backdrop.tsx";
|
||||
import '../../styles/Messages.css';
|
||||
import { useState, useEffect } from "react";
|
||||
import api from "../../script/axiosApi.tsx";
|
||||
import React from "react";
|
||||
import {User} from "../../../interfaces.tsx"
|
||||
// import { useNavigate } from "react-router-dom";
|
||||
|
||||
const dropIn = {
|
||||
hidden: { y: "-100vh", opacity: 0 },
|
||||
visible: {
|
||||
y: "0",
|
||||
opacity: 1,
|
||||
transition: {
|
||||
duration: 0.3,
|
||||
type: "spring",
|
||||
damping: 100,
|
||||
stiffness: 500,
|
||||
},
|
||||
},
|
||||
exit: { y: "100vh", opacity: 0 },
|
||||
};
|
||||
|
||||
interface ModalGame {
|
||||
handleClose: Function,
|
||||
// convId: string
|
||||
}
|
||||
|
||||
const GameModal = ({ handleClose }: ModalGame) => {
|
||||
const [users, setUsers] = useState([]);
|
||||
// const [user, setUser] = useState();
|
||||
const [selectedUser, setSelectedUser] = useState('');
|
||||
// const [convs, setConvs] = useState([]);
|
||||
const [channel, setChannel] = useState('');
|
||||
|
||||
// const history = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async () => {
|
||||
try {
|
||||
const tmpUsers = await api.get("/users");
|
||||
// const tmpUser = await api.get("/profile");
|
||||
// const tmpConvs = await api.get("/convs");
|
||||
setUsers(tmpUsers.data);
|
||||
// setUser(tmpUser.data);
|
||||
// setConvs(tmpConvs.data);
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
fetchData();
|
||||
}, []);
|
||||
|
||||
const handleUserChange = (event: { target: { value: React.SetStateAction<string>; }; }) => {
|
||||
setSelectedUser(event.target.value);
|
||||
};
|
||||
|
||||
// const joinChannel = async () => {
|
||||
// try {
|
||||
// await api.post("/join", { convId: channel });
|
||||
// } catch (err) {
|
||||
// console.log(err);
|
||||
// }
|
||||
// };
|
||||
|
||||
// const handleCheckButtonClick = () => {
|
||||
// // Perform your check action here
|
||||
// console.log("Checking user:", selectedUser);
|
||||
// };
|
||||
|
||||
const handleButtonClick = async () => {
|
||||
// let path = `play?`;
|
||||
let path = `http://` + process.env.REACT_APP_BASE_URL + `/pong/play?`;
|
||||
|
||||
|
||||
const superpowerCheckbox = document.querySelector<HTMLInputElement>('input[value="superpower"]');
|
||||
if (superpowerCheckbox && superpowerCheckbox.checked) {
|
||||
path += 'superpower=true&';
|
||||
}
|
||||
|
||||
const obstacleCheckbox = document.querySelector<HTMLInputElement>('input[value="obstacle"]');
|
||||
if (obstacleCheckbox && obstacleCheckbox.checked) {
|
||||
path += 'obstacle=true&';
|
||||
}
|
||||
|
||||
const speedCheckbox = document.querySelector<HTMLInputElement>('input[value="speed"]');
|
||||
if (speedCheckbox && speedCheckbox.checked) {
|
||||
path += 'speed=true&';
|
||||
}
|
||||
|
||||
if (selectedUser.length > 0)
|
||||
path += 'username=' + selectedUser;//important here
|
||||
|
||||
// Remove the trailing '&' character
|
||||
// path = path.slice(0, -1);
|
||||
// console.log(path)
|
||||
|
||||
// await api.post("/partyInvite", {username: selectedUser, gameId})
|
||||
|
||||
// console.log("path= ", path)
|
||||
// history(path, { replace: true });
|
||||
// window.location.replace(path);
|
||||
window.history.pushState({}, '', path);
|
||||
window.location.reload();
|
||||
|
||||
// history(path);
|
||||
};
|
||||
|
||||
return (
|
||||
<Backdrop onClick={handleClose}>
|
||||
<motion.div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="modal"
|
||||
// variant={dropIn}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
>
|
||||
<div>
|
||||
<select value={selectedUser} onChange={handleUserChange}>
|
||||
<option value="">Select a user</option>
|
||||
{users.map((user: User) => (
|
||||
<option key={user.id} value={user.username}>
|
||||
{user.username}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="notClicked" id="canvas_container">
|
||||
{/* <button onClick={handleButtonClick}>Draw on Canvas</button> */}
|
||||
<div className='checkbox'>
|
||||
<p><input type="checkbox" value="superpower"/> Super Power </p>
|
||||
<p><input type="checkbox" value="obstacle"/> Obstacle </p>
|
||||
<p><input type="checkbox" value="speed"/> Faster and Faster </p>
|
||||
</div>
|
||||
<button className="submit" onClick={handleButtonClick} >Play</button>
|
||||
{/* <button className="submit" onClick={handleClose}>Cancel</button> */}
|
||||
</div>
|
||||
|
||||
{/* <div className="div_submit">
|
||||
<button className="submit" onClick={handleCheckButtonClick}>
|
||||
Invite to play
|
||||
</button>
|
||||
</div> */}
|
||||
</motion.div>
|
||||
</Backdrop>
|
||||
);
|
||||
};
|
||||
|
||||
export default GameModal;
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import { TbSend } from 'react-icons/tb';
|
||||
|
||||
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Message.tsx :+: :+: :+: */
|
||||
/* Message.jsx :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/01 18:24:46 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/20 19:05:10 by apommier ### ########.fr */
|
||||
/* Updated: 2023/06/12 17:05:08 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -17,8 +17,6 @@ import DefaultPicture from '../../assets/profile.jpg'
|
||||
// import { useRef } from "react";
|
||||
// import { useEffect } from "react";
|
||||
import '../../styles/Messages.css'
|
||||
import {User, Conv, Message} from "../../../interfaces.tsx"
|
||||
import React from "react";
|
||||
|
||||
const MeStyleP = styled.p`
|
||||
background-color: #5843e4;
|
||||
@ -28,21 +26,10 @@ const MeStyleP = styled.p`
|
||||
margin-right: 20px;
|
||||
`
|
||||
|
||||
interface MessageMeProps {
|
||||
message: Message;
|
||||
own: boolean;
|
||||
}
|
||||
|
||||
function MessageMe({message, own}: MessageMeProps){
|
||||
function MessageMe({message, own}){
|
||||
|
||||
const [profilePicture, setProfilePicture] = useState('');
|
||||
const [sender, setSender] = useState<User>();
|
||||
const [conv, setConv] = useState<Conv>();
|
||||
|
||||
const [user, setUser] = useState<User>();
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
// console.log("Message eher")
|
||||
const scrollRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
if (scrollRef.current)
|
||||
@ -52,16 +39,9 @@ function MessageMe({message, own}: MessageMeProps){
|
||||
const fetchProfilePicture = async () => {
|
||||
try {
|
||||
// const user = await api.get("/profile");
|
||||
const tmpSender = await api.post("/user", {username: message.sender})
|
||||
const tmpConv = await api.post("/convId", {convId: message.convId})
|
||||
// const tmpSender = await api.post("/user", {username: message.sender})
|
||||
const tmpUser = await api.get("/profile")
|
||||
const pic = await api.post("/getPicture", {username: message.sender})
|
||||
// console.log(`user naem profile pic222= ${currentUser.username}`)
|
||||
// console.log(` profile pic222= ${pic.data}`)
|
||||
setConv(tmpConv.data);
|
||||
setUser(tmpUser.data);
|
||||
setSender(tmpSender.data);
|
||||
setProfilePicture(pic.data);
|
||||
} catch (error) {
|
||||
console.error('Error fetching profile picture:', error);
|
||||
@ -70,52 +50,23 @@ function MessageMe({message, own}: MessageMeProps){
|
||||
fetchProfilePicture();
|
||||
}, [])
|
||||
|
||||
const handleButtonClick = () => {
|
||||
if (!sender)
|
||||
return ;
|
||||
let path = `http://` + process.env.REACT_APP_BASE_URL + `/profile/${sender.username}`;
|
||||
// console.log("path= ", path)
|
||||
// history(path, { replace: true });
|
||||
// window.location.replace(path);
|
||||
window.history.pushState({}, '', path);
|
||||
window.location.reload();
|
||||
};
|
||||
|
||||
if (!user || !sender || !conv)
|
||||
{
|
||||
// console.log("return")
|
||||
return (<></>);
|
||||
}
|
||||
// console.log("result includes=", conv.banned.includes(user.username))
|
||||
// console.log("result includes=", conv.blocked.includes(user.username))
|
||||
if (user.blocked && user.blocked.includes(message.sender))
|
||||
return (<></>);
|
||||
// else if (conv.banned && conv.banned.includes(user.username))
|
||||
// {
|
||||
// console.log("return2")
|
||||
// return (<></>);
|
||||
// }
|
||||
// console.log("noy return")
|
||||
// if (user.blocked.includes(message.sender))/
|
||||
|
||||
return (
|
||||
<div className={own ? "meMessage" : "youMessage"} ref={scrollRef}>
|
||||
<div>
|
||||
{/* <img className="messageInfo" src={DefaultPic} alt="profile" />
|
||||
*/}
|
||||
{profilePicture ? (
|
||||
<img className="messageInfo" onClick={() => handleButtonClick()} src={`data:image/jpeg;base64,${profilePicture}`} />
|
||||
<img className="messageInfo" src={`data:image/jpeg;base64,${profilePicture}`} />
|
||||
) : (
|
||||
<img className="messageInfo" onClick={() => handleButtonClick()} src={DefaultPicture} alt="Default Profile Picture" />
|
||||
<img className="messageInfo" src={DefaultPicture} alt="Default Profile Picture" />
|
||||
)}
|
||||
</div>
|
||||
{/* <div className="usernameMesage">{message.senderNickname}</div> */}
|
||||
{sender ? (
|
||||
<div className="usernameMesage">{sender.nickname}</div>
|
||||
): ""}
|
||||
<div className="usernameMesage">{message.sender}</div>
|
||||
<div className="messageContent">
|
||||
<MeStyleP>{message.text}</MeStyleP>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -14,8 +14,7 @@ const MeStyleP = styled.p`
|
||||
`
|
||||
|
||||
function MessageMe(){
|
||||
// const scrollRef = useRef();
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
const scrollRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
scrollRef.current?.scrollIntoView({ behavior: "smooth"})
|
||||
|
||||
@ -14,7 +14,7 @@ const StyleP = styled.p`
|
||||
`
|
||||
|
||||
function MessageYou(){
|
||||
const scrollRef = useRef<HTMLDivElement>(null);
|
||||
const scrollRef = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
scrollRef.current?.scrollIntoView({ behavior: "smooth"})
|
||||
|
||||
@ -90,7 +90,7 @@ const Modal = ({handleClose}) => {
|
||||
// test
|
||||
await api.post("/conv", data);
|
||||
handleClose();
|
||||
window.location.reload();
|
||||
window.location.reload(false);
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
@ -100,15 +100,17 @@ const Modal = ({handleClose}) => {
|
||||
// let new_name;
|
||||
|
||||
return (
|
||||
<Backdrop onClick={handleClose}>
|
||||
<Backdrop>
|
||||
<motion.div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="modal"
|
||||
// variant={dropIn}
|
||||
variant={dropIn}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
>
|
||||
{/* <p>New Conversation</p> */}
|
||||
|
||||
{selectTags.map((selectTag) => (
|
||||
<div key={selectTag.id}>
|
||||
<select
|
||||
@ -145,7 +147,7 @@ const Modal = ({handleClose}) => {
|
||||
>
|
||||
<option value="">Select an option</option>
|
||||
{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 && conv.banned.includes(channel)) || (conv.members && conv.members.includes(user.username))) && (
|
||||
<option key={conv.id} value={conv.id}>
|
||||
{conv.name}
|
||||
</option>
|
||||
@ -153,16 +155,36 @@ const Modal = ({handleClose}) => {
|
||||
))}
|
||||
</select>
|
||||
)}
|
||||
{channel.private ? (
|
||||
<input className="mdp" placeholder="password" type="text" />
|
||||
):("")}
|
||||
|
||||
|
||||
<div className="div_submit">
|
||||
<Link to='#' className="submit" onClick={ joinChannel }>Join</Link>
|
||||
</div>
|
||||
|
||||
|
||||
{/* {selectTags.map((selectTag) => (
|
||||
<div key={selectTag.id}>
|
||||
<select
|
||||
value={selectTag.selectedOption}
|
||||
onChange={(a) => handleOptionChange(selectTag.id, a.target.value)}
|
||||
>
|
||||
<option value="">{
|
||||
selectTag.selectedOption ? selectTag.selectedOption : "Select an option"
|
||||
}</option>
|
||||
{convs.filter((item) => !selectTags.some((tag) => tag.selectedOption === item.name)).map((item, index) => (
|
||||
<option key={index} value={item.name}>
|
||||
{item.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
))} */}
|
||||
|
||||
|
||||
|
||||
{/* <div>
|
||||
<GrAdd onClick={addNewSelectedTag}/>
|
||||
</div> */}
|
||||
|
||||
|
||||
</motion.div>
|
||||
</Backdrop>
|
||||
|
||||
@ -1,14 +1,11 @@
|
||||
import { motion } from "framer-motion";
|
||||
import Backdrop from "../Sidebar/Backdrop.tsx";
|
||||
// import { Rank } from "../../DataBase/DataRank"
|
||||
import { Rank } from "../../DataBase/DataRank"
|
||||
import '../../styles/Messages.css'
|
||||
import { useState, useEffect } from "react";
|
||||
import { GrAdd } from "react-icons/gr";
|
||||
import { Link } from "react-router-dom";
|
||||
import api from "../../script/axiosApi.tsx";
|
||||
import React from "react";
|
||||
import {User} from "../../../interfaces.tsx"
|
||||
import { Socket } from "socket.io-client";
|
||||
|
||||
|
||||
const dropIn = {
|
||||
@ -27,26 +24,13 @@ const dropIn = {
|
||||
|
||||
};
|
||||
|
||||
interface ModalSettingProps {
|
||||
handleClose: Function,
|
||||
convId: string,
|
||||
socket: Socket | null,
|
||||
}
|
||||
|
||||
const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
|
||||
const ModalSetting = ({handleClose, convId}) => {
|
||||
const [password, setPassword] = useState(false);
|
||||
const [users, setUsers] = useState<User[]>([]);
|
||||
const [users, setUsers] = useState([]);
|
||||
const [selectTags, setSelectTag] = useState([{ id: 1, selectedOption: ''}]);
|
||||
const [selectedUser, setSelectedUser] = useState("");
|
||||
const [selectedUser, setSelectedUser] = useState([]);
|
||||
const [newName, setNewName] = useState("");
|
||||
const [newPassword, setNewPassword] = useState("");
|
||||
const [privateConv, setPrivateConv] = useState(false);
|
||||
const dark = () => setPrivateConv(true);
|
||||
const light = () => setPrivateConv(false);
|
||||
const [mute, setMute] = useState(false);
|
||||
const darkMute = () => setMute(false);
|
||||
const lightMute = () => setMute(true);
|
||||
|
||||
|
||||
useEffect(()=> {
|
||||
|
||||
@ -67,7 +51,7 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
|
||||
// const [selectedOptionArray, setSelectedOptionArray] = useState([]);
|
||||
|
||||
|
||||
const handleOptionChange = (selectId: number, selectedOption: string) => {
|
||||
const handleOptionChange = (selectId, selectedOption) => {
|
||||
console.log("tag= ", selectTags)
|
||||
console.log("option= ", selectedOption)
|
||||
setSelectTag((prevTags) =>
|
||||
@ -78,12 +62,12 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
|
||||
setSelectedUser(selectedOption)
|
||||
};
|
||||
|
||||
const handleCheckPass = (e: { target: { checked: boolean | ((prevState: boolean) => boolean); }; }) => {
|
||||
const handleCheckPass = (e) => {
|
||||
setPassword(e.target.checked);
|
||||
console.log("password??", e.target.checked)
|
||||
}
|
||||
|
||||
const handleCheckPriv = (e: { target: { checked: any; }; }) => {
|
||||
const handleCheckPriv = (e) => {
|
||||
// setPassword(e.target.checked);
|
||||
if (e.target.checked)
|
||||
{
|
||||
@ -105,72 +89,59 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
|
||||
}
|
||||
}
|
||||
|
||||
const handleName = async (e: { key: string; })=>{
|
||||
const handleName = async (e)=>{
|
||||
if (e.key !== "Enter")
|
||||
return ;
|
||||
try{
|
||||
api.post("/name", {convId: convId, name: newName})
|
||||
window.location.reload()
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
handleClose();
|
||||
}
|
||||
|
||||
const handlePassword = async (e: { key: string; })=>{
|
||||
const handlePassword = async (e)=>{
|
||||
if (e.key !== "Enter")
|
||||
return ;
|
||||
try{
|
||||
await api.post("/password", {convId: convId, password: newPassword})
|
||||
api.post("/password", {convId: convId, password: newPassword})
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
handleClose();
|
||||
}
|
||||
|
||||
const handleBan = async () => {
|
||||
const handleBan = () => {
|
||||
// console.log("ban option= ", selectedUser)
|
||||
try{
|
||||
// console.log("user select=", selectedUser.length)
|
||||
if (!selectedUser.length)
|
||||
return ;
|
||||
await api.post("/ban", {convId: convId, username: selectedUser})
|
||||
if (socket)
|
||||
{
|
||||
console.log("emit to ban server")
|
||||
socket.emit("ban", {username: selectedUser})
|
||||
}
|
||||
api.post("/ban", {convId: convId, username: selectedUser})
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleAdmin = async () => {
|
||||
if (!selectedUser.length)
|
||||
return ;
|
||||
const handleAdmin = () => {
|
||||
try{
|
||||
await api.post("/admin", {convId: convId, username: selectedUser})
|
||||
api.post("/admin", {convId: convId, username: selectedUser})
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleMute = async () => {
|
||||
if (!selectedUser.length)
|
||||
return ;
|
||||
const handleMute = () => {
|
||||
try{
|
||||
await api.post("/mute", {convId: convId, username: selectedUser})
|
||||
api.post("/mute", {convId: convId, username: selectedUser})
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
handleClose();
|
||||
};
|
||||
|
||||
const handleInvite = async () => {
|
||||
const handleInvite = () => {
|
||||
try{
|
||||
await api.post("/invite", {convId: convId, username: selectedUser})
|
||||
api.post("/invite", {convId: convId, username: selectedUser})
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
@ -178,10 +149,11 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
|
||||
};
|
||||
|
||||
return (
|
||||
<Backdrop onClick={handleClose}>
|
||||
<Backdrop>
|
||||
<motion.div
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
className="modalSetting"
|
||||
variant={dropIn}
|
||||
initial="hidden"
|
||||
animate="visible"
|
||||
exit="exit"
|
||||
@ -190,19 +162,15 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
|
||||
{/* First selection */}
|
||||
<div className="settingFirstPart">
|
||||
<div>
|
||||
<div>
|
||||
<Link to="#" onClick={light} className={ privateConv ? "submit" : "darkSubmit"}>Public</Link>
|
||||
<Link to="#" onClick={dark} className={ privateConv ? "darkSubmit" : "submit"}>Private</Link>
|
||||
</div>
|
||||
{/* <p className="checkbox">Private<input className="check"type="checkbox" value="private" onChange={handleCheckPriv}/></p> */}
|
||||
<p className="checkbox">Private<input class="check"type="checkbox" value="private" onChange={handleCheckPriv}/></p>
|
||||
<p className="checkbox">Password<input type="checkbox" value="password" checked={password} onChange={handleCheckPass}/> </p>
|
||||
|
||||
|
||||
{password || privateConv ? (
|
||||
{password ? (
|
||||
<input
|
||||
onChange={(e) => setNewPassword(e.target.value)}
|
||||
onKeyDown={handlePassword}
|
||||
type="password"
|
||||
type="text"
|
||||
className="in"
|
||||
placeholder="Password"/>
|
||||
):
|
||||
@ -248,14 +216,11 @@ const ModalSetting = ({handleClose, convId, socket }: ModalSettingProps) => {
|
||||
<div>
|
||||
<Link to="#" onClick={handleInvite} className="submit">Send</Link>
|
||||
<Link to="#" onClick={handleBan} className="submit">Ban</Link>
|
||||
<Link to="#" onClick={mute ? darkMute : lightMute} className={mute ? "darkSubmit": "submit"}>Mute</Link>
|
||||
<Link to="#" onClick={handleMute} className="submit">Mute</Link>
|
||||
<Link to="#" onClick={handleAdmin} className="submit">Admin</Link>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{mute ? (
|
||||
<input type="text" className="in_howLong" placeholder="How long ?" />
|
||||
):("")}
|
||||
|
||||
</motion.div>
|
||||
</Backdrop>
|
||||
|
||||
@ -33,7 +33,6 @@ const ModalEdit = ( handleClose ) => {
|
||||
const handler = e =>
|
||||
{
|
||||
setNickname(e.target.value);
|
||||
console.log("testeeeee")
|
||||
const postNickname = async ()=>{
|
||||
try{
|
||||
await api.post("/nickname", {nickname: nickname})
|
||||
@ -46,22 +45,6 @@ const ModalEdit = ( handleClose ) => {
|
||||
};
|
||||
postNickname();
|
||||
}
|
||||
|
||||
const handlePostNickname = async () =>
|
||||
{
|
||||
console.log("nickname=" ,nickname)
|
||||
try{
|
||||
await api.post("/nickname", {nickname: nickname})
|
||||
window.location.reload();
|
||||
// setUser(tmpUser.data);
|
||||
// setIsLoading(false)
|
||||
}
|
||||
catch(err){
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// function handleClose(){
|
||||
// //do nothing
|
||||
// }
|
||||
@ -73,11 +56,10 @@ const ModalEdit = ( handleClose ) => {
|
||||
animate="visible"
|
||||
exit="exit">
|
||||
<h2>Type your new name</h2>
|
||||
<input className="text" maxLength="10" type="text" value={nickname} onChange={handler} handleClose/>
|
||||
<div>
|
||||
<div className="button" onClick={ () => handlePostNickname()}>
|
||||
change
|
||||
{/* <Link className="button" to={""}>change</Link> */}
|
||||
<input className="text" type="text" value={nickname} onChange={handler} handleClose/>
|
||||
<div onClick={handleClose}>
|
||||
<div onClick={() => {UserProfile.UserName = nickname;}}>
|
||||
<Link className="button" to={""}>change</Link>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from "react";
|
||||
|
||||
|
||||
|
||||
@ -9,9 +8,8 @@ function Logout(){
|
||||
// history(path, { replace: true });
|
||||
// window.location.replace(path);
|
||||
// window.history.pushState({}, '', path);
|
||||
window.history.pushState({}, '', path);
|
||||
window.location.reload();
|
||||
return (<></>)
|
||||
window.history.pushState({}, null, path);
|
||||
window.location.reload(false);
|
||||
}
|
||||
|
||||
export default Logout;
|
||||
@ -4,7 +4,6 @@
|
||||
// import '../DataBase/DataProfileUser.js'
|
||||
// import { DBWinLoss } from '../../DataBase/DummyDBWinLoss.js';
|
||||
import '../../styles/Win_Loss.css'
|
||||
import { User, Matchlog } from "../../../interfaces.tsx"
|
||||
// import { UserProfile } from '../../DataBase/DataUserProfile';
|
||||
// import color from '../../utils/style/color.js';
|
||||
|
||||
@ -52,7 +51,7 @@ import api from '../../script/axiosApi.tsx';
|
||||
|
||||
function WinLoss() {
|
||||
|
||||
const [user, setUser] = useState<User>();
|
||||
const [user, setUser] = useState(null);
|
||||
const [history, setHistory] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
|
||||
@ -89,13 +88,13 @@ function WinLoss() {
|
||||
|
||||
|
||||
<div className='tab'>
|
||||
{isLoading || !history || !user ? (
|
||||
{isLoading ? (
|
||||
<h1>Loading...</h1>
|
||||
// <span>Loading...</span>
|
||||
) : (
|
||||
<div className='scroll'>
|
||||
<h2 className='title'>Match history Win/Loss</h2>
|
||||
{history.map((c: Matchlog, index) => {
|
||||
{history.map((c, index) => {
|
||||
return (
|
||||
<div key={index} className='elements'>
|
||||
<li key={index}>
|
||||
|
||||
@ -1,13 +1,7 @@
|
||||
import React, { MouseEventHandler, ReactNode, HTMLAttributes } from "react";
|
||||
import { motion } from "framer-motion"
|
||||
import "../../styles/Header.css"
|
||||
|
||||
interface backProps {
|
||||
children: ReactNode,
|
||||
onClick: any
|
||||
}
|
||||
|
||||
const Backdrop = ({ children, onClick }: backProps) => {
|
||||
const Backdrop = ({ children, onClick }) => {
|
||||
return (
|
||||
<motion.div className="backdrop"
|
||||
onClick={onClick}
|
||||
|
||||
@ -6,7 +6,6 @@ import * as AiIcons from 'react-icons/ai';
|
||||
|
||||
|
||||
import "../../styles/Header.css"
|
||||
import React from "react";
|
||||
|
||||
const dropIn = {
|
||||
hidden: {
|
||||
@ -20,11 +19,27 @@ const dropIn = {
|
||||
},
|
||||
}
|
||||
|
||||
interface CloseProps {
|
||||
handleclose: Function;
|
||||
}
|
||||
|
||||
const Modal = ({ handleclose }: CloseProps) => {
|
||||
// function showBar (){
|
||||
// return (
|
||||
// {SidebarData.map((item, index) => {
|
||||
// return (
|
||||
// <motion.div
|
||||
// className="nav-menu"
|
||||
// // whileHover={{scale: 1.1}}
|
||||
// >
|
||||
// <li key={index} className={item.cName}>
|
||||
// <Link to={item.path}>
|
||||
// {item.icon}
|
||||
// <span>{item.title}</span>
|
||||
// </Link>
|
||||
// </li>
|
||||
// </motion.div>
|
||||
// )
|
||||
// })}
|
||||
// )
|
||||
// }
|
||||
const Modal = ({ handleclose }) => {
|
||||
return (
|
||||
<Backdrop onClick={handleclose}>
|
||||
<motion.div
|
||||
|
||||
@ -26,7 +26,7 @@ export const SidebarData = [
|
||||
cName: 'nav-text'
|
||||
},
|
||||
{
|
||||
title: 'Friend',
|
||||
title: 'Social',
|
||||
path: '/social',
|
||||
icon: <IoIcons.IoMdPeople />,
|
||||
cName: 'nav-text'
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/09 08:18:58 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/20 13:41:44 by apommier ### ########.fr */
|
||||
/* Updated: 2023/06/18 13:12:26 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -18,7 +18,6 @@ import styled from "styled-components";
|
||||
import { RxCircle } from "react-icons/rx";
|
||||
import { CgFontSpacing } from "react-icons/cg";
|
||||
import React from "react";
|
||||
import {User} from "../../../interfaces.tsx"
|
||||
|
||||
const UserChat = styled.div `
|
||||
padding: 5px;
|
||||
@ -38,12 +37,8 @@ const SideP = styled.p`
|
||||
color: lightgray;
|
||||
margin-left: 15px;
|
||||
`
|
||||
interface UserProps {
|
||||
currentUser: User
|
||||
}
|
||||
|
||||
// export default function Friend({currentUser})
|
||||
export default function Friend({currentUser}: UserProps)
|
||||
export default function Friend({currentUser})
|
||||
{
|
||||
const [profilePicture, setProfilePicture] = useState('');
|
||||
|
||||
@ -63,7 +58,7 @@ export default function Friend({currentUser}: UserProps)
|
||||
fetchProfilePicture();
|
||||
})
|
||||
|
||||
function getStatus(friend: User)
|
||||
function getStatus(friend)
|
||||
{
|
||||
let status = friend.status
|
||||
console.log(`status= ${status}`)
|
||||
@ -78,19 +73,19 @@ export default function Friend({currentUser}: UserProps)
|
||||
return statusColor;
|
||||
}
|
||||
|
||||
const handleSpectate = (user: User) => {
|
||||
const handleSpectate = (user) => {
|
||||
//socket connection and add to party with one with username
|
||||
console.log(`spectate hehe`)
|
||||
console.log(`user= ${user}`)
|
||||
};
|
||||
|
||||
const handleButtonClick = (user: User) => {
|
||||
const handleButtonClick = (user) => {
|
||||
let path = `http://` + process.env.REACT_APP_BASE_URL + `/profile/${user.username}`;
|
||||
console.log("path= ", path)
|
||||
// history(path, { replace: true });
|
||||
// window.location.replace(path);
|
||||
window.history.pushState({}, '', path);
|
||||
window.location.reload();
|
||||
window.history.pushState({}, null, path);
|
||||
window.location.reload(false);
|
||||
};
|
||||
|
||||
return (
|
||||
@ -102,7 +97,7 @@ export default function Friend({currentUser}: UserProps)
|
||||
)}
|
||||
<div className="infoSideBar">
|
||||
<span onClick={() => handleButtonClick(currentUser)}>{currentUser.nickname}</span>
|
||||
<RxCircle color={getStatus(currentUser)} />
|
||||
<RxCircle icon={RxCircle} color={getStatus(currentUser)} />
|
||||
<button onClick={() => handleSpectate(currentUser)} >Invite</button>
|
||||
{getStatus(currentUser) !== 'blue' ? (
|
||||
<></>
|
||||
|
||||
111
containers/react/src/components/Social/Friend.tsx~HEAD
Normal file
111
containers/react/src/components/Social/Friend.tsx~HEAD
Normal file
@ -0,0 +1,111 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Friend.jsx :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/09 08:18:58 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/15 19:05:14 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import api from '../../script/axiosApi.tsx';
|
||||
import DefaultPicture from '../../assets/profile.jpg'
|
||||
import styled from "styled-components";
|
||||
|
||||
import { RxCircle } from "react-icons/rx";
|
||||
import { CgFontSpacing } from "react-icons/cg";
|
||||
|
||||
const UserChat = styled.div `
|
||||
padding: 5px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover{
|
||||
background-color: #3e3c61;
|
||||
}
|
||||
`
|
||||
|
||||
const SideP = styled.p`
|
||||
font-size: 14px;
|
||||
color: lightgray;
|
||||
margin-left: 15px;
|
||||
`
|
||||
|
||||
export default function Friend({currentUser})
|
||||
{
|
||||
const [profilePicture, setProfilePicture] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
const fetchProfilePicture = async () => {
|
||||
try {
|
||||
// const user = await api.get("/profile");
|
||||
const pic = await api.post("/getPicture", {username: currentUser.username})
|
||||
// console.log(`user naem profile pic222= ${currentUser.username}`)
|
||||
// console.log(` profile pic222= ${pic.data}`)
|
||||
setProfilePicture(pic.data);
|
||||
} catch (error) {
|
||||
console.error('Error fetching profile picture:', error);
|
||||
}
|
||||
};
|
||||
|
||||
fetchProfilePicture();
|
||||
})
|
||||
|
||||
function getStatus(friend)
|
||||
{
|
||||
let status = friend.status
|
||||
console.log(`status= ${status}`)
|
||||
let statusColor;
|
||||
|
||||
if (status === 0)
|
||||
statusColor = 'grey';
|
||||
else if (status === 1)
|
||||
statusColor = 'green';
|
||||
else if (status === 2)
|
||||
statusColor = 'blue';
|
||||
return statusColor;
|
||||
}
|
||||
|
||||
const handleSpectate = (user) => {
|
||||
//socket connection and add to party with one with username
|
||||
console.log(`spectate hehe`)
|
||||
console.log(`user= ${user}`)
|
||||
};
|
||||
|
||||
const handleButtonClick = (user) => {
|
||||
let path = `http://` + process.env.REACT_APP_BASE_URL + `/profile/${user.username}`;
|
||||
console.log("path= ", path)
|
||||
// history(path, { replace: true });
|
||||
// window.location.replace(path);
|
||||
window.history.pushState({}, null, path);
|
||||
window.location.reload(false);
|
||||
};
|
||||
|
||||
return (
|
||||
<UserChat>
|
||||
{profilePicture ? (
|
||||
<img className="pic-user" src={`data:image/jpeg;base64,${profilePicture}`} />
|
||||
) : (
|
||||
<img className="pic-user" src={DefaultPicture} alt="Default Profile Picture" />
|
||||
)}
|
||||
<div className="infoSideBar">
|
||||
<span onClick={() => handleButtonClick(currentUser)}>{currentUser.nickname}</span>
|
||||
<RxCircle icon={RxCircle} color={getStatus(currentUser)} />
|
||||
<button onClick={() => handleSpectate(currentUser)} >Invite</button>
|
||||
{getStatus(currentUser) !== 'blue' ? (
|
||||
<></>
|
||||
) : (
|
||||
<button onClick={() => handleSpectate(currentUser)} >Spectate</button>
|
||||
)}
|
||||
</div>
|
||||
</UserChat>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -5,8 +5,6 @@ import DefaultPicture from '../../assets/profile.jpg'
|
||||
import styled from "styled-components";
|
||||
|
||||
import { RxCheckCircled, RxCircleBackslash } from "react-icons/rx";
|
||||
import React from "react";
|
||||
import {User} from "../../../interfaces.tsx"
|
||||
|
||||
const UserChat = styled.div `
|
||||
padding: 5px;
|
||||
@ -27,14 +25,10 @@ const SideP = styled.p`
|
||||
margin-left: 15px;
|
||||
`
|
||||
|
||||
interface UserProps {
|
||||
currentUser: User
|
||||
}
|
||||
|
||||
export default function Friend({currentUser}: UserProps)
|
||||
export default function Friend({currentUser})
|
||||
{
|
||||
const [profilePicture, setProfilePicture] = useState('');
|
||||
const [request, setRequest] = useState<User>(); //user who invite
|
||||
const [request, setRequest] = useState(''); //user who invite
|
||||
const [clickEvent, setClickEvent] = useState(false);
|
||||
// const [user, setUser] = useState(null);
|
||||
|
||||
@ -58,15 +52,15 @@ export default function Friend({currentUser}: UserProps)
|
||||
fetchProfilePicture();
|
||||
}, [clickEvent])
|
||||
|
||||
const handleButtonClick = (user: User) => {
|
||||
const handleButtonClick = (user) => {
|
||||
let path = `http://` + process.env.REACT_APP_BASE_URL + `/profile/${user.username}`;
|
||||
// history(path, { replace: true });
|
||||
// window.location.replace(path);
|
||||
window.history.pushState({}, '', path);
|
||||
window.location.reload();
|
||||
window.history.pushState({}, null, path);
|
||||
window.location.reload(false);
|
||||
};
|
||||
|
||||
const Accept = async (request: User) => {
|
||||
const Accept = async (request) => {
|
||||
try{
|
||||
await api.post("/friend", {username: request.username})
|
||||
setClickEvent(true);
|
||||
@ -77,7 +71,7 @@ export default function Friend({currentUser}: UserProps)
|
||||
console.log(`request = ${request}`)
|
||||
}
|
||||
|
||||
const Refuse = async (request: User) => {
|
||||
const Refuse = async (request) => {
|
||||
try{
|
||||
await api.post("/refuseInvite", {username: request.username})
|
||||
setClickEvent(true);
|
||||
@ -100,13 +94,12 @@ export default function Friend({currentUser}: UserProps)
|
||||
) : (
|
||||
<img className="pic-user" src={DefaultPicture} alt="Default Profile Picture" />
|
||||
)}
|
||||
{request ? (
|
||||
<div className="infoSideBar">
|
||||
<span onClick={() => handleButtonClick(currentUser)}>{currentUser.nickname}</span>
|
||||
<RxCheckCircled onClick={() => Accept(request)} color={'green'}/>
|
||||
<RxCircleBackslash onClick={() => Refuse(request)} color={'red'}/>
|
||||
|
||||
</div>
|
||||
) : ( "" )}
|
||||
</UserChat>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,24 +1,10 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* PartyInvite.tsx :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/19 16:44:29 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/20 23:53:01 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import api from '../../script/axiosApi.tsx';
|
||||
import DefaultPicture from '../../assets/profile.jpg'
|
||||
import styled from "styled-components";
|
||||
|
||||
import {User} from "../../../interfaces.tsx"
|
||||
import { RxCheckCircled, RxCircleBackslash } from "react-icons/rx";
|
||||
import React from "react";
|
||||
|
||||
const UserChat = styled.div `
|
||||
padding: 5px;
|
||||
@ -39,19 +25,10 @@ const SideP = styled.p`
|
||||
margin-left: 15px;
|
||||
`
|
||||
|
||||
interface InviteProps {
|
||||
username: string,
|
||||
gameId: string
|
||||
}
|
||||
|
||||
interface UserProps {
|
||||
currentInvite: {username: string, gameId: string}
|
||||
}
|
||||
|
||||
export default function PartyInvite({currentInvite}: UserProps)
|
||||
export default function Friend({currentUser})
|
||||
{
|
||||
const [profilePicture, setProfilePicture] = useState('');
|
||||
const [request, setRequest] = useState<User>(); //user who invite
|
||||
const [request, setRequest] = useState(''); //user who invite
|
||||
const [clickEvent, setClickEvent] = useState(false);
|
||||
// const [user, setUser] = useState(null);
|
||||
|
||||
@ -60,11 +37,11 @@ export default function PartyInvite({currentInvite}: UserProps)
|
||||
try {
|
||||
// const user = await api.get("/profile");\
|
||||
// const tmpUser = await api.get("/profile")
|
||||
const pic = await api.post("/getPicture", {username: currentInvite.username})
|
||||
const tmpRequest = await api.post("/user", {username: currentInvite.username})
|
||||
const pic = await api.post("/getPicture", {username: currentUser.username})
|
||||
const tmpRequest = await api.post("/user", {username: currentUser.username})
|
||||
// setUser(tmpUser.data);
|
||||
setRequest(tmpRequest.data);
|
||||
// console.log(`user naem profile pic222= ${currentInvite.username}`)
|
||||
// console.log(`user naem profile pic222= ${currentUser.username}`)
|
||||
// console.log(` profile pic222= ${pic.data}`)
|
||||
setProfilePicture(pic.data);
|
||||
} catch (error) {
|
||||
@ -75,25 +52,18 @@ export default function PartyInvite({currentInvite}: UserProps)
|
||||
fetchProfilePicture();
|
||||
}, [clickEvent])
|
||||
|
||||
const handleButtonClick = (user: InviteProps) => {
|
||||
const handleButtonClick = (user) => {
|
||||
let path = `http://` + process.env.REACT_APP_BASE_URL + `/profile/${user.username}`;
|
||||
// history(path, { replace: true });
|
||||
// window.location.replace(path);
|
||||
window.history.pushState({}, '', path);
|
||||
window.location.reload();
|
||||
window.history.pushState({}, null, path);
|
||||
window.location.reload(false);
|
||||
};
|
||||
|
||||
const Accept = async (request: User) => {
|
||||
const Accept = async (request) => {
|
||||
try{
|
||||
//call canvas ??
|
||||
// await api.post("/friend", {username: request.username})
|
||||
await api.post("/deleteInvite", {username: request.username})
|
||||
let path = `http://` + process.env.REACT_APP_BASE_URL + `/pong/play?`
|
||||
path += 'username=' + request.username;
|
||||
path += '&gameId=' + currentInvite.gameId;
|
||||
// setClickEvent(true);
|
||||
window.history.pushState({}, '', path);
|
||||
window.location.reload();
|
||||
await api.post("/friend", {username: request.username})
|
||||
setClickEvent(true);
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
@ -101,10 +71,9 @@ export default function PartyInvite({currentInvite}: UserProps)
|
||||
console.log(`request = ${request}`)
|
||||
}
|
||||
|
||||
const Refuse = async (request: User) => {
|
||||
const Refuse = async (request) => {
|
||||
try{
|
||||
await api.post("/deleteInvite", {username: request.username})
|
||||
// await api.post("/refuseInvite", {username: request.username})
|
||||
await api.post("/refuseInvite", {username: request.username})
|
||||
setClickEvent(true);
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
@ -115,7 +84,6 @@ export default function PartyInvite({currentInvite}: UserProps)
|
||||
|
||||
// Vérifier si le contenu doit être caché
|
||||
if (clickEvent) {
|
||||
console.log("retrun true")
|
||||
return null; // Rendre null pour ne pas afficher le contenu
|
||||
}
|
||||
|
||||
@ -126,13 +94,13 @@ export default function PartyInvite({currentInvite}: UserProps)
|
||||
) : (
|
||||
<img className="pic-user" src={DefaultPicture} alt="Default Profile Picture" />
|
||||
)}
|
||||
{request ? (
|
||||
<div className="infoSideBar">
|
||||
<span onClick={() => handleButtonClick(currentInvite)}>{request.nickname}</span>
|
||||
<span onClick={() => handleButtonClick(currentUser)}>{currentUser.nickname}</span>
|
||||
<RxCheckCircled onClick={() => Accept(request)} color={'green'}/>
|
||||
<RxCircleBackslash onClick={() => Refuse(request)} color={'red'}/>
|
||||
|
||||
</div>
|
||||
) : ( "" )}
|
||||
</UserChat>
|
||||
)
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ import FriendRequest from './FriendRequest.tsx';
|
||||
|
||||
import { ImBlocked } from 'react-icons/im';
|
||||
import { MdOutlineGroupAdd } from 'react-icons/md';
|
||||
import {User} from "../../../interfaces.tsx"
|
||||
|
||||
// import React from "react";
|
||||
|
||||
@ -35,11 +34,12 @@ function Social (){
|
||||
|
||||
const [friends, setFriends] = useState([]);
|
||||
const [invite, setInvite] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [user, setUser] = useState<User>();
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [user, setUser] = useState(null);
|
||||
const [profilePicture, setProfilePicture] = useState('');
|
||||
|
||||
useEffect(()=> {
|
||||
|
||||
const getFriend = async ()=>{
|
||||
try{
|
||||
const tmpFriends = await api.get("/friends")
|
||||
@ -94,7 +94,7 @@ function Social (){
|
||||
<img className="pic" src={DefaultPicture} alt="Default Profile Picture" />
|
||||
)}
|
||||
<span>
|
||||
{isLoading || !user ? (
|
||||
{isLoading ? (
|
||||
<h4>Loading...</h4>
|
||||
) : (
|
||||
<h4>{user.nickname}</h4>
|
||||
|
||||
@ -1,20 +1,13 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useEffect, useLocation } from 'react';
|
||||
// import { useState, useRef } from 'react';
|
||||
import DrawCanvas from './canvas.tsx';
|
||||
import queryString from 'query-string';
|
||||
import '../styles/field.css';
|
||||
|
||||
import { useParams } from "react-router-dom";
|
||||
import React from 'react';
|
||||
|
||||
// import { withRouter } from 'react-router-dom';
|
||||
|
||||
interface GameProps {
|
||||
privateParty: boolean,
|
||||
username?: string
|
||||
gameId?: number
|
||||
}
|
||||
|
||||
function Field()
|
||||
{
|
||||
useEffect(() => {
|
||||
@ -23,7 +16,6 @@ function Field()
|
||||
|
||||
console.log("launch canva hehe")
|
||||
let Modifiers = 0;
|
||||
let info: GameProps;
|
||||
|
||||
if (queryParams.superpower === 'true') {
|
||||
Modifiers += 1;
|
||||
@ -36,37 +28,81 @@ function Field()
|
||||
if (queryParams.speed === 'true') {
|
||||
Modifiers += 4;
|
||||
}
|
||||
// console.log(`modifiers= ${Modifiers}`)
|
||||
// DrawCanvas(Modifiers);
|
||||
// return () => {
|
||||
// console.log("000000000000000000000000000000000")
|
||||
// // socketRef.current.disconnect();
|
||||
// };
|
||||
|
||||
info = {
|
||||
privateParty: false,
|
||||
|
||||
}
|
||||
if (queryParams.username)
|
||||
{
|
||||
console.log("user= ", queryParams.username)
|
||||
info = {
|
||||
privateParty: true,
|
||||
username: queryParams.username as string,
|
||||
gameId: queryParams.gameId as unknown as number
|
||||
}
|
||||
console.log("info of param vefore canvas=", info)
|
||||
}
|
||||
|
||||
const cleanup = DrawCanvas(Modifiers, info);
|
||||
// console.log(`modifiers= ${Modifiers}`)
|
||||
const cleanup = DrawCanvas(Modifiers);
|
||||
|
||||
return () => {
|
||||
console.log("Cleanup");
|
||||
// cleanup(); // Call the cleanup function to stop the ongoing process or perform necessary cleanup tasks
|
||||
if (cleanup)
|
||||
cleanup();
|
||||
cleanup(); // Call the cleanup function to stop the ongoing process or perform necessary cleanup tasks
|
||||
};
|
||||
|
||||
}, []);
|
||||
|
||||
// const [buttonClicked, setButtonClicked] = useState(false);
|
||||
|
||||
// const handleButtonClick = () => {
|
||||
// drawCanvas();
|
||||
// setButtonClicked(true);
|
||||
// };
|
||||
|
||||
return (
|
||||
<div className="field" id="canvas_container">
|
||||
<canvas id="myCanvas"></canvas>
|
||||
{/* <button onClick={handleButtonClick}>Draw on Canvas</button> */}
|
||||
{/* {buttonClicked && <canvas id="myCanvas"></canvas>}
|
||||
{!buttonClicked && <button onClick={handleButtonClick}>Draw on Canvas</button>} */}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Field;
|
||||
// export default withRouter(Field);
|
||||
|
||||
|
||||
// function Field() {
|
||||
// const [buttonClicked, setButtonClicked] = useState(false);
|
||||
|
||||
// const handleButtonClick = () => {
|
||||
// const canvas = document.createElement('canvas');
|
||||
// canvas.id = 'myCanvas';
|
||||
// console.log("button clicked")
|
||||
// document.getElementById('canvas_container').appendChild(canvas);
|
||||
// setButtonClicked(true);
|
||||
// drawCanvas(canvas);
|
||||
// };
|
||||
// setButtonClicked(true);
|
||||
// return (
|
||||
// // <div className="field" id="canvas_container">
|
||||
// <div className={`notClicked ${buttonClicked ? 'clicked' : ''}`} id="canvas_container">
|
||||
// {!buttonClicked && <button className="playButton" onClick={handleButtonClick}>Play</button>}
|
||||
// </div>
|
||||
// );
|
||||
// }
|
||||
|
||||
// export default Field;
|
||||
|
||||
// function draw() {
|
||||
// // Effacer le canvas
|
||||
// ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
|
||||
// // Dessiner la raquette
|
||||
// ctx.fillRect(canvas.width - paddleWidth, paddleY, paddleWidth, paddleHeight);
|
||||
|
||||
// // Appeler la fonction draw à chaque frame
|
||||
// requestAnimationFrame(draw);
|
||||
// }
|
||||
|
||||
// draw(); // Appeler la fonction draw pour la première fois
|
||||
|
||||
// const canvas = document.getElementById('myCanvas');
|
||||
// canvas.width = 500;
|
||||
// canvas.height = 500;
|
||||
// const ctx = canvas.getContext('2d');
|
||||
// ctx.fillRect(50, 50, 1000, 1000);
|
||||
@ -1,5 +1,3 @@
|
||||
import React from "react";
|
||||
|
||||
function Head()
|
||||
{
|
||||
return (
|
||||
@ -9,7 +7,7 @@ function Head()
|
||||
<title>BEST PONG EVER</title>
|
||||
{/* <script src="./script/login.js"></script> */}
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com"></link>
|
||||
{/* <link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="true"></link> */}
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="true"></link>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Rubik+Iso&display=swap" rel="stylesheet"></link>
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
/* ************************************************************************** */
|
||||
/* */
|
||||
/* ::: :::::::: */
|
||||
/* Home.tsx :+: :+: :+: */
|
||||
/* Home.jsx :+: :+: :+: */
|
||||
/* +:+ +:+ +:+ */
|
||||
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||
/* +#+#+#+#+#+ +#+ */
|
||||
/* Created: 2023/06/09 08:19:04 by apommier #+# #+# */
|
||||
/* Updated: 2023/06/23 15:58:14 by apommier ### ########.fr */
|
||||
/* Updated: 2023/06/09 08:19:05 by apommier ### ########.fr */
|
||||
/* */
|
||||
/* ************************************************************************** */
|
||||
|
||||
@ -21,9 +21,6 @@ import { motion, AnimatePresence } from 'framer-motion'
|
||||
import { Link } from "react-router-dom";
|
||||
import ModalEdit from "../components/Profile/EditName.tsx";
|
||||
import {AiOutlineHistory} from 'react-icons/ai'
|
||||
import { MdQrCodeScanner, MdOutlinePhotoLibrary } from 'react-icons/md';
|
||||
import { GiWingedSword, GiCrownedSkull } from 'react-icons/gi';
|
||||
|
||||
// import { Link } from "react-router-dom";
|
||||
// import {UserProfile} from "../DataBase/DataUserProfile";
|
||||
// import axios from "axios";
|
||||
@ -33,10 +30,8 @@ import { IoCloseCircleOutline } from "react-icons/io5";
|
||||
|
||||
// import * as React from 'react';
|
||||
// import { useState, useEffect, useParams} from "react";
|
||||
import React, { useState, useEffect, useRef, ChangeEventHandler } from "react";
|
||||
import React, { useState, useEffect, useRef } from "react";
|
||||
import { useParams } from 'react-router-dom';
|
||||
import {User, Conv} from "../../interfaces.tsx"
|
||||
import YellowAlert from '../components/Alert/YellowAlert.tsx';
|
||||
// axios.get("http://localhost/api")
|
||||
// .then((response) => {
|
||||
// response = response.json()
|
||||
@ -48,70 +43,40 @@ import YellowAlert from '../components/Alert/YellowAlert.tsx';
|
||||
|
||||
|
||||
function Profile () {
|
||||
const [user, setUser] = useState<User>();
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
const [modalOpen, setModalOpen] = useState<boolean>(false);
|
||||
const [mine, setMine] = useState<boolean>(false);
|
||||
const [user, setUser] = useState(null);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [modalOpen, setModalOpen] = useState(false);
|
||||
const [mine, setMine] = useState(false);
|
||||
const close = () => setModalOpen(false);
|
||||
const open = () => setModalOpen(true);
|
||||
|
||||
const { username } = useParams();
|
||||
|
||||
// const [selectedPhoto, setSelectedPhoto] = useState();
|
||||
// const [selectedPhoto, setSelectedPhoto] = useState(null);
|
||||
|
||||
const [selectedPhoto, setSelectedPhoto] = useState(null);
|
||||
const [profilePicture, setProfilePicture] = useState('');
|
||||
|
||||
const handleFileChange = async (event: { target: { files: any; }; }) => {
|
||||
// const files = event.target.files;
|
||||
// if (files && files.length > 0) {
|
||||
const photo = (event.target.files[0]);
|
||||
console.log("file selected")
|
||||
if (photo) {
|
||||
console.log("selected photo")
|
||||
const formData = new FormData();
|
||||
formData.append('photo', photo);
|
||||
try {
|
||||
await api.post('/picture', formData);
|
||||
console.log('File uploaded successfully');
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
console.error('Error uploading file:', error);
|
||||
}
|
||||
}
|
||||
const handleFileChange = (event) => {
|
||||
// const file = event.target.files[0];
|
||||
setSelectedPhoto(event.target.files[0]);
|
||||
// try{
|
||||
// api.post("/picture", {picture: URL.createObjectURL(file)})
|
||||
// }
|
||||
// catch(err){
|
||||
// console.log(err);
|
||||
// }
|
||||
};
|
||||
|
||||
// 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');
|
||||
// }
|
||||
// };
|
||||
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(false);
|
||||
} catch (error) {
|
||||
console.error('Error uploading file:', error);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(()=> {
|
||||
const getUser = async ()=>{
|
||||
@ -157,7 +122,7 @@ function Profile () {
|
||||
<img className="profile-pic" src={DefaultPicture} alt="Default Profile Picture" />
|
||||
)}
|
||||
<span>
|
||||
{isLoading || !user ? (
|
||||
{isLoading ? (
|
||||
<h1>Loading...</h1>
|
||||
) : (
|
||||
<h1>{user.nickname}</h1>
|
||||
@ -168,22 +133,16 @@ function Profile () {
|
||||
|
||||
{mine ? (
|
||||
<div>
|
||||
<motion.div >
|
||||
<Link to="#" className="edit_name" onClick={() => (modalOpen ? close() : open())}>
|
||||
<motion.div onClick={() => (modalOpen ? close() : open())}>
|
||||
<Link to="#" className="edit_name">
|
||||
{modalOpen === true ? <IoCloseCircleOutline/> : <CgEditMarkup/>}
|
||||
</Link>
|
||||
{modalOpen === true ? ("") : (
|
||||
<>
|
||||
<label htmlFor="file-input" className="edit_name"><MdOutlinePhotoLibrary/></label>
|
||||
<input type="file" id="file-input" className="file-input" accept="image/*" onChange={handleFileChange} />
|
||||
</>
|
||||
)}
|
||||
</motion.div>
|
||||
|
||||
{/* <div className="file-upload-container"> */}
|
||||
{/* <button onClick={handleUpload} className="upload-button">Upload</button> */}
|
||||
{/* <button onClick={handleUpload} className="upload-button">Upload</button> */}
|
||||
{/* </div> */}
|
||||
<div>
|
||||
<input type="file" accept="image/*" onChange={handleFileChange} />
|
||||
<button onClick={handleUpload}>Upload</button>
|
||||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<></>
|
||||
@ -202,49 +161,13 @@ function Profile () {
|
||||
|
||||
function Home () {
|
||||
const [move, setmove ] = useState(false);
|
||||
const [user, setUser] = useState([]);
|
||||
|
||||
const [successQr, setSuccessQr] = useState(false);
|
||||
const [successSword, setSuccessSword] = useState(false);
|
||||
const [successCrown, setSuccessCrown] = useState(false);
|
||||
const closeQr = () => setSuccessQr(false);
|
||||
const closeSword = () => setSuccessSword(false);
|
||||
const closeCrown = () => setSuccessCrown(false);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
const fetchSuccess = async () => {
|
||||
try {
|
||||
const tmpUser = await api.get("/profile");
|
||||
setUser(tmpUser.data);
|
||||
}
|
||||
catch (error)
|
||||
{
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
fetchSuccess();
|
||||
})
|
||||
|
||||
return (
|
||||
<motion.div className="page"
|
||||
initial={{opacity: -1}}
|
||||
animate={{opacity: 1}}
|
||||
exit={{opacity: -1}}>
|
||||
<div>
|
||||
{user.otp_verified ? (
|
||||
<MdQrCodeScanner className='success' onClick={() => setSuccessQr(true)}/>
|
||||
):("")}
|
||||
{user.win >= 2 ? (
|
||||
<GiWingedSword className="success" onClick={() => setSuccessSword(true)}/>
|
||||
):("")}
|
||||
|
||||
{user.win >= 5 ? (
|
||||
<GiCrownedSkull className="success" onClick={() => setSuccessCrown(true)}/>
|
||||
):("")}
|
||||
</div>
|
||||
<div className="home">
|
||||
<motion.div animate={{x: move ? -200: 120}}
|
||||
<motion.div animate={{x: move ? -200: 170}}
|
||||
transition={{type: "tween", duration: 0.5}}>
|
||||
<Profile/>
|
||||
</motion.div>
|
||||
@ -258,19 +181,6 @@ function Home () {
|
||||
onClick={ () => setmove(!move)}>
|
||||
<Link to="#" className="history"><AiOutlineHistory/> Match History</Link>
|
||||
</motion.div>
|
||||
<AnimatePresence initial={false} onExitComplete={() => null}>
|
||||
{successQr ? (
|
||||
<YellowAlert handleClose={closeQr} text={"Success: You have the 2fa success!"} icon={1} />
|
||||
) : ("")}
|
||||
|
||||
{successCrown ? (
|
||||
<YellowAlert handleClose={closeCrown} text={"Success: 5 victory ? You won king slayer success!"} icon={2}/>
|
||||
) : ("")}
|
||||
|
||||
{successSword ? (
|
||||
<YellowAlert handleClose={closeSword} text={"Success: 2 victory ? You won the noobi warrior success!"} icon={3}/>
|
||||
) : ("")}
|
||||
</AnimatePresence>
|
||||
</motion.div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
// import GoogleLogin from 'react-google-login';
|
||||
import { useEffect } from 'react';
|
||||
import axios from 'axios';
|
||||
import React from 'react';
|
||||
// import setupLogin from '../script/login42';
|
||||
// import React, { useEffect } from 'react';
|
||||
|
||||
@ -16,15 +15,12 @@ function Login42()
|
||||
|
||||
const data = {
|
||||
grant_type: 'authorization_code',
|
||||
// client_id: 'u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41',
|
||||
// client_secret: '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',
|
||||
client_id: process.env.REACT_APP_CLIENT_UID,
|
||||
client_secret: process.env.REACT_APP_API_SECRET,
|
||||
client_id: 'u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41',
|
||||
client_secret: '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',
|
||||
code: code,
|
||||
redirect_uri: 'http://' + process.env.REACT_APP_BASE_URL + '/login42',
|
||||
};
|
||||
|
||||
|
||||
axios.post('https://api.intra.42.fr/oauth/token', data)
|
||||
.then(response => {
|
||||
// handle success response
|
||||
@ -38,7 +34,7 @@ function Login42()
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>"COUCOU LOGIN" </p>
|
||||
<p>"COUCOU LOGIN$@ jeje" </p>
|
||||
{/* <script src="../script/login42.js"></script> */}
|
||||
</div>
|
||||
);
|
||||
|
||||
@ -6,7 +6,7 @@ import { motion } from 'framer-motion'
|
||||
|
||||
// import {io} from 'socket.io-client'
|
||||
|
||||
function Messages() {
|
||||
function Messages(params) {
|
||||
// const socket = useRef(io("ws://localhost:8900"))
|
||||
|
||||
// useEffect(() => {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import React from 'react';
|
||||
import '../styles/field.css';
|
||||
// import { useHistory } from 'react-router-dom';
|
||||
import { useNavigate } from "react-router-dom";
|
||||
|
||||
@ -29,10 +29,9 @@ const qrCode = new QRCodeStyling({
|
||||
|
||||
function QrCode () {
|
||||
// const url = "https://www.youtube.com";
|
||||
// const ref = useRef(null);
|
||||
const ref = useRef<HTMLDivElement>(null);
|
||||
const ref = useRef(null);
|
||||
const [user, setUser] = useState(false);
|
||||
const [url, setUrl] = useState("");
|
||||
const [url, setUrl] = useState(false);
|
||||
const [secret, setSecret] = useState(false);
|
||||
const [code, setCode] = useState('');
|
||||
const [activated, setActivated] = useState(false);
|
||||
@ -40,8 +39,8 @@ function QrCode () {
|
||||
// const history = useHistory();
|
||||
|
||||
useEffect(() => {
|
||||
if (ref.current)
|
||||
qrCode.append(ref.current);
|
||||
|
||||
const getUser = async ()=>{
|
||||
try{
|
||||
const tmpUser = await api.get("/profile");
|
||||
@ -67,11 +66,13 @@ function QrCode () {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
qrCode.update({data: url});
|
||||
qrCode.update({
|
||||
data: url
|
||||
});
|
||||
}, [url]);
|
||||
|
||||
|
||||
const handleKeyPress = async (e: { key: string; })=>{
|
||||
const handleKeyPress = async (e)=>{
|
||||
// console.log(`e in press= ${e.key}`)
|
||||
if (e.key !== "Enter")
|
||||
return ;
|
||||
@ -86,8 +87,8 @@ function QrCode () {
|
||||
// history.push('/login')
|
||||
|
||||
const path = 'http://' + process.env.REACT_APP_BASE_URL + '/';
|
||||
window.history.pushState({}, '', path);
|
||||
window.location.reload();
|
||||
window.history.pushState({}, null, path);
|
||||
window.location.reload(false);
|
||||
|
||||
}
|
||||
else
|
||||
@ -106,8 +107,8 @@ function QrCode () {
|
||||
try {
|
||||
await api.post("/deleteOtp")
|
||||
// const path = 'http://' + process.env.REACT_APP_BASE_URL + '/';
|
||||
// window.history.pushState({}, '', path);
|
||||
window.location.reload();
|
||||
// window.history.pushState({}, null, path);
|
||||
window.location.reload(false);
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
@ -138,7 +139,6 @@ function QrCode () {
|
||||
<h3>{secret}</h3>
|
||||
<h1>Or Scan The QRCode</h1>
|
||||
<div ref={ref} />
|
||||
{/* <div>{ref}</div> */}
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
@ -8,13 +8,9 @@ import io from 'socket.io-client';
|
||||
// const socket = io('http://86.209.110.20:4000');
|
||||
// const socket = io('http://172.29.113.91:4000');
|
||||
|
||||
interface GameProps {
|
||||
privateParty: boolean,
|
||||
username?: string
|
||||
gameId?: number
|
||||
}
|
||||
function DrawCanvas(option) {
|
||||
|
||||
|
||||
function DrawCanvas(option: number, gameParam: GameProps) {
|
||||
|
||||
console.log(`option= ${option}`);
|
||||
const superpowerModifier = option & 1; // Retrieves the superpower modifier
|
||||
@ -29,39 +25,12 @@ function DrawCanvas(option: number, gameParam: GameProps) {
|
||||
|
||||
// const socketRef = useRef(null);
|
||||
// socketRef.current = io('http://localhost:4000');
|
||||
|
||||
function launchGame()
|
||||
{
|
||||
if (!gameParam.privateParty)
|
||||
{
|
||||
console.log("laucnh matchmaking")
|
||||
matchmaking();
|
||||
}
|
||||
else if (!gameParam.gameId)
|
||||
{
|
||||
console.log("laucnh private")
|
||||
privateParty();
|
||||
}
|
||||
else
|
||||
{
|
||||
console.log("join private")
|
||||
joinPrivateParty();
|
||||
}
|
||||
}
|
||||
|
||||
const socket = io('http://' + process.env.REACT_APP_BASE_URL + ':4000');
|
||||
// const socket = socketRef.current
|
||||
console.log("start function");
|
||||
|
||||
// let canvas: HTMLElement | null;
|
||||
const canvas = document.getElementById('myCanvas') as HTMLCanvasElement | null;;
|
||||
if (!canvas)
|
||||
return ;
|
||||
|
||||
const canvas = document.getElementById('myCanvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
if(!ctx)
|
||||
return ;
|
||||
|
||||
const socket = io('http://localhost:4000', { transports: ['polling'] });
|
||||
// useEffect(() => {
|
||||
// console.log("useeffect?????????????????")
|
||||
// return () => {
|
||||
@ -80,8 +49,8 @@ function DrawCanvas(option: number, gameParam: GameProps) {
|
||||
//socket
|
||||
let myId = 0;
|
||||
let gameId = 0;
|
||||
let opName: string
|
||||
let opRank: number;
|
||||
let opName;
|
||||
let opRank;
|
||||
|
||||
//general canvas
|
||||
let running = true;
|
||||
@ -130,43 +99,46 @@ function DrawCanvas(option: number, gameParam: GameProps) {
|
||||
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
// Socket ON
|
||||
// Socket handler
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
|
||||
socket.on('pong:win', async () => {
|
||||
myScore = maxScore;
|
||||
console.log("instant win opponent disconnect")
|
||||
// const data = {
|
||||
// myScore: myScore,
|
||||
// opScore: hisScore,
|
||||
// opName: opName,
|
||||
// opRank: opRank,
|
||||
// };
|
||||
|
||||
// await api.post('/win', data);
|
||||
console.log("after request1")
|
||||
await api.post('/status', {status: 1});
|
||||
console.log("after request2")
|
||||
//disconnect ?
|
||||
running = false;
|
||||
socket.emit('pong:disconnect', {id: myId});
|
||||
console.log("before reload")
|
||||
// window.location.replace("http://" + process.env.REACT_APP_BASE_URL + "/pong");
|
||||
// window.location.reload();
|
||||
return ;
|
||||
// console.log("send all ?? win");
|
||||
|
||||
});
|
||||
|
||||
socket.on('pong:privateId', async (data) => {
|
||||
console.log("private id = ", data)
|
||||
try{
|
||||
await api.post("/partyInvite", {username: gameParam.username, gameId: data});
|
||||
} catch(err) {
|
||||
console.log(err)
|
||||
function matchmaking()
|
||||
{
|
||||
console.log(`id ion matcj= ${myId}`)
|
||||
const info = {
|
||||
id: myId,
|
||||
option: option,
|
||||
};
|
||||
socket.emit('pong:matchmaking', info);
|
||||
}
|
||||
});
|
||||
|
||||
// socket.on('pong:gameId', (data) => {
|
||||
// console.log("gameId received")
|
||||
// gameId = data;
|
||||
// // api.get('/profile');
|
||||
|
||||
// let myName;
|
||||
|
||||
// api.get('/profile').then((data) => {
|
||||
// // Faire quelque chose avec les données
|
||||
// console.log(data);
|
||||
// myName = data.data.username;
|
||||
// console.log(`myname= ${myName}`);
|
||||
// }).catch((error) => {
|
||||
// console.log(error);
|
||||
// // exit() ;
|
||||
// return;
|
||||
// });
|
||||
|
||||
// const info = {
|
||||
// id: myId,
|
||||
// name: myName,
|
||||
// gameId: gameId,
|
||||
// };
|
||||
// console.log("emit to name")
|
||||
// socket.emit('pong:name', info);
|
||||
// });
|
||||
|
||||
socket.on('pong:gameId', async (data) => {
|
||||
console.log("gameId received");
|
||||
@ -210,7 +182,6 @@ socket.on('pong:clientId', (data) => {
|
||||
console.log("receive id")
|
||||
myId = data;
|
||||
console.log(`id is= ${myId}`)
|
||||
launchGame();
|
||||
});
|
||||
|
||||
socket.on('pong:info', (data) => {
|
||||
@ -243,60 +214,9 @@ socket.on('pong:power', (data) => {
|
||||
// oPaddleY = (data.paddleY / data.height) * canvas.height
|
||||
});
|
||||
|
||||
socket.on('pong:point', (data) => {
|
||||
// hisScore += 1;
|
||||
console.log("gain point");
|
||||
// if (vX != 0)
|
||||
// {
|
||||
// console.log("up point");
|
||||
myScore = data.point;
|
||||
// }
|
||||
vX = 0;
|
||||
vY = 0;
|
||||
ballX = canvas.width / 2;
|
||||
ballY = canvas.height / 2;
|
||||
});
|
||||
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
// Socket EMIT
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
|
||||
function matchmaking()
|
||||
{
|
||||
console.log(`id ion matcj= ${myId}`)
|
||||
const info = {
|
||||
id: myId,
|
||||
option: option,
|
||||
};
|
||||
socket.emit('pong:matchmaking', info);
|
||||
}
|
||||
|
||||
function privateParty()
|
||||
{
|
||||
console.log(`id private party= ${myId}`)
|
||||
const info = {
|
||||
id: myId,
|
||||
option: option,
|
||||
};
|
||||
socket.emit('pong:privateParty', info);
|
||||
}
|
||||
|
||||
function joinPrivateParty()
|
||||
{
|
||||
console.log(`id private party= ${myId}`)
|
||||
const info = {
|
||||
id: myId,
|
||||
gameId: gameParam.gameId,
|
||||
option: option,
|
||||
};
|
||||
socket.emit('pong:joinParty', info);
|
||||
}
|
||||
|
||||
function send_info()
|
||||
{
|
||||
if (!gameId || !canvas)
|
||||
if (gameId === 0)
|
||||
return ;
|
||||
const info = {
|
||||
id: myId,
|
||||
@ -314,7 +234,7 @@ socket.on('pong:point', (data) => {
|
||||
|
||||
function send_point()
|
||||
{
|
||||
if (!gameId || !canvas)
|
||||
if (gameId === 0)
|
||||
return ;
|
||||
console.log("send point");
|
||||
const info = {
|
||||
@ -325,9 +245,23 @@ socket.on('pong:point', (data) => {
|
||||
socket.emit('pong:point', info);
|
||||
}
|
||||
|
||||
socket.on('pong:point', (data) => {
|
||||
// hisScore += 1;
|
||||
console.log("gain point");
|
||||
// if (vX != 0)
|
||||
// {
|
||||
// console.log("up point");
|
||||
myScore = data.point;
|
||||
// }
|
||||
vX = 0;
|
||||
vY = 0;
|
||||
ballX = canvas.width / 2;
|
||||
ballY = canvas.height / 2;
|
||||
});
|
||||
|
||||
function send_paddle_info()
|
||||
{
|
||||
if (!gameId || !canvas)
|
||||
if (gameId === 0)
|
||||
return ;
|
||||
const info = {
|
||||
id: myId,
|
||||
@ -341,8 +275,6 @@ socket.on('pong:point', (data) => {
|
||||
|
||||
function use_power()
|
||||
{
|
||||
if (!canvas)
|
||||
return ;
|
||||
const info = {
|
||||
gameId: gameId,
|
||||
width: canvas.width,
|
||||
@ -354,7 +286,7 @@ socket.on('pong:point', (data) => {
|
||||
|
||||
function send_forced_info()
|
||||
{
|
||||
if (!gameId || !canvas)
|
||||
if (gameId === 0)
|
||||
return ;
|
||||
const info = {
|
||||
gameId: gameId,
|
||||
@ -379,8 +311,6 @@ socket.on('pong:point', (data) => {
|
||||
function drawcenter()
|
||||
{
|
||||
// ctx.restore();
|
||||
if (!ctx || !canvas)
|
||||
return ;
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillRect(canvas.width / 2 - ctx.lineWidth / 2, 0, canvas.width / 300, canvas.height);
|
||||
|
||||
@ -393,13 +323,11 @@ socket.on('pong:point', (data) => {
|
||||
ctx.font = canvas.width * 0.1 + "px Arial";
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
ctx.fillText(myScore.toString(), canvas.width/4, canvas.height/8);
|
||||
ctx.fillText(hisScore.toString(), canvas.width/1.25, canvas.height/8);
|
||||
ctx.fillText(myScore, canvas.width/4, canvas.height/8);
|
||||
ctx.fillText(hisScore, canvas.width/1.25, canvas.height/8);
|
||||
}
|
||||
|
||||
function drawPaddle() {
|
||||
if (!ctx || !canvas)
|
||||
return ;
|
||||
ctx.fillStyle = 'white';
|
||||
ctx.fillRect(paddleX, paddleY, paddleWidth, paddleHeight);
|
||||
ctx.fillRect(canvas.width - paddleX - paddleWidth, oPaddleY, paddleWidth, opPaddleHeight);
|
||||
@ -407,8 +335,6 @@ socket.on('pong:point', (data) => {
|
||||
|
||||
function drawball()
|
||||
{
|
||||
if (!ctx)
|
||||
return ;
|
||||
ctx.beginPath();
|
||||
ctx.arc(ballX, ballY, ballRadius, 0, 2 * Math.PI);
|
||||
// ctx.lineWidth = 2;
|
||||
@ -423,52 +349,29 @@ socket.on('pong:point', (data) => {
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
|
||||
|
||||
matchmaking();
|
||||
// while (!gameId)
|
||||
// ;
|
||||
|
||||
// Define a function to stop the drawing process
|
||||
const stopDrawCanvas = async () => {
|
||||
const stopDrawCanvas = () => {
|
||||
running = false;
|
||||
|
||||
console.log("stopDrawCanvas 1")
|
||||
|
||||
if (gameParam.privateParty && !gameId) //delete invite
|
||||
{
|
||||
console.log("stopDrawCanvas2")
|
||||
try{
|
||||
// const info = {
|
||||
// id: myId,
|
||||
// option: option,
|
||||
// };
|
||||
|
||||
await api.post("deleteInvite", {username: gameParam.username})
|
||||
}
|
||||
catch (err){
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
socket.emit('pong:disconnect', {id: myId});
|
||||
window.location.replace("http://" + process.env.REACT_APP_BASE_URL + "/pong");
|
||||
// window.location.reload();
|
||||
// Perform any necessary cleanup tasks
|
||||
// ...
|
||||
};
|
||||
|
||||
async function draw(timestamp: number)
|
||||
function draw(timestamp)
|
||||
{
|
||||
console.log("turning, running= ", running);
|
||||
console.log("turning");
|
||||
if (!running)
|
||||
return ;
|
||||
if (!gameId || !canvas )
|
||||
if (gameId === 0 )
|
||||
{
|
||||
// console.log("nogameid score= ", myScore);
|
||||
requestAnimationFrame(draw);
|
||||
return ;
|
||||
}
|
||||
if (myScore === maxScore || hisScore === maxScore)
|
||||
{
|
||||
console.log("maxScore!!!!")
|
||||
const data = {
|
||||
myScore: myScore,
|
||||
opScore: hisScore,
|
||||
@ -477,23 +380,17 @@ async function draw(timestamp: number)
|
||||
};
|
||||
if (myScore === maxScore)
|
||||
{
|
||||
await api.post('/win', data);
|
||||
await api.post('/status', {status: 1});
|
||||
//disconnect ?
|
||||
socket.emit('pong:disconnect', {id: myId});
|
||||
|
||||
console.log("send all ?? win");
|
||||
api.post('/win', data);
|
||||
api.post('/status', {status: 1});
|
||||
console.log("send win");
|
||||
}
|
||||
else
|
||||
{
|
||||
await api.post('/loss', data);
|
||||
await api.post('/status', {status: 1});
|
||||
socket.emit('pong:disconnect', {id: myId});
|
||||
//disconnect ?
|
||||
api.post('/loss', data);
|
||||
api.post('/status', {status: 1});
|
||||
console.log("send loose");
|
||||
}
|
||||
window.location.replace("http://" + process.env.REACT_APP_BASE_URL + "/pong");
|
||||
// window.location.reload();
|
||||
return ;
|
||||
}
|
||||
|
||||
@ -502,9 +399,6 @@ async function draw(timestamp: number)
|
||||
ballX += vX * deltaTime * canvas.width;
|
||||
ballY += vY * deltaTime * canvas.height;
|
||||
|
||||
if (!ctx)
|
||||
return ;
|
||||
// requestAnimationFrame(draw);
|
||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||
drawPaddle();
|
||||
drawcenter();
|
||||
@ -541,17 +435,14 @@ async function draw(timestamp: number)
|
||||
}
|
||||
|
||||
|
||||
function updatePaddlePosition(newY: number)
|
||||
function updatePaddlePosition(newY)
|
||||
{
|
||||
|
||||
if (canvas && newY >= 0 && newY <= canvas.height - paddleHeight)
|
||||
if (newY >= 0 && newY <= canvas.height - paddleHeight)
|
||||
paddleY = newY;
|
||||
}
|
||||
|
||||
function is_collision()
|
||||
{
|
||||
if (!canvas)
|
||||
return ;
|
||||
if (ballX <= paddleX + paddleWidth + ballRadius)
|
||||
{
|
||||
if (ballY <= paddleY + paddleHeight + ballRadius && ballY >= paddleY - ballRadius)//touch paddle
|
||||
@ -576,12 +467,15 @@ async function draw(timestamp: number)
|
||||
ballY = ballRadius + 2
|
||||
// send_info();
|
||||
}
|
||||
// else if (ballX + ballRadius + 2 >= canvas.width) //touch right wall
|
||||
// {
|
||||
// vX = -vX;
|
||||
// // send_info();
|
||||
// }
|
||||
}
|
||||
|
||||
function is_out()
|
||||
{
|
||||
if (!canvas)
|
||||
return ;
|
||||
if (ballX < 0)
|
||||
{
|
||||
if (ballY <= paddleY + paddleHeight + ballRadius && ballY >= paddleY - ballRadius)
|
||||
@ -601,9 +495,7 @@ async function draw(timestamp: number)
|
||||
}
|
||||
if (ballX > canvas.width)
|
||||
{
|
||||
// if (ballX > canvas.width * 2)
|
||||
// socket.emit
|
||||
// console.log("win point")
|
||||
console.log("win point")
|
||||
// if (ballY <= paddleY + paddleHeight + ballRadius && ballY >= paddleY - ballRadius)
|
||||
// {
|
||||
// console.log('true hehe');
|
||||
@ -626,10 +518,17 @@ async function draw(timestamp: number)
|
||||
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
// Key/Mouse/Finger Listener
|
||||
// Listener
|
||||
//========================================================================================================
|
||||
//========================================================================================================
|
||||
|
||||
document.addEventListener('resize', event => {
|
||||
// event.height
|
||||
// event.width
|
||||
const { clientWidth, clientHeight } = canvas.parentElement;
|
||||
console.log(`resize detected widht= ${clientWidth} height= ${clientHeight}`)
|
||||
});
|
||||
|
||||
document.addEventListener('mousemove', event => {
|
||||
const mouseY = event.clientY;
|
||||
|
||||
|
||||
@ -68,8 +68,8 @@ function SuccessToken() {
|
||||
window.location.replace("http://" + process.env.REACT_APP_BASE_URL + "/pong");
|
||||
|
||||
// const path = 'http://' + process.env.REACT_APP_BASE_URL + '/';
|
||||
// window.history.pushState({}, '', path);
|
||||
// window.location.reload();
|
||||
// window.history.pushState({}, null, path);
|
||||
// window.location.reload(false);
|
||||
|
||||
}
|
||||
else
|
||||
@ -197,8 +197,8 @@ function SuccessToken() {
|
||||
// // history.push('/login')
|
||||
|
||||
// const path = 'http://' + process.env.REACT_APP_BASE_URL + '/';
|
||||
// window.history.pushState({}, '', path);
|
||||
// window.location.reload();
|
||||
// window.history.pushState({}, null, path);
|
||||
// window.location.reload(false);
|
||||
|
||||
// }
|
||||
// else
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
input.qr{
|
||||
width: 20%;
|
||||
border-radius: 5px;
|
||||
background-color: rgb(0, 0, 0);
|
||||
background-color: rgb(66, 66, 66);
|
||||
margin : 1%;
|
||||
color:white;
|
||||
}
|
||||
|
||||
@ -89,17 +89,6 @@ span {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.success {
|
||||
height: 2%;
|
||||
width: 2%;
|
||||
/* border: solid; */
|
||||
margin-top: 1%;
|
||||
margin: 3vh;
|
||||
/* margin-bottom: -12vh; */
|
||||
/* border-color: black; */
|
||||
/* border-radius: 50%; */
|
||||
}
|
||||
|
||||
.header-pic{
|
||||
text-align: end;
|
||||
/* id: right; */
|
||||
|
||||
@ -32,7 +32,6 @@ select{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
overflow-x: scroll;
|
||||
}
|
||||
|
||||
.scroll{
|
||||
@ -51,8 +50,7 @@ select{
|
||||
.contact{
|
||||
background-color: rgb(46, 46, 46);
|
||||
align-items: left;
|
||||
height: 74vh;
|
||||
width: 30%;
|
||||
height: 30.2rem;
|
||||
overflow: scroll;
|
||||
/* width: 2rem; */
|
||||
/* height: 4rem; */
|
||||
@ -94,8 +92,6 @@ select{
|
||||
}
|
||||
|
||||
.navbar{
|
||||
/* width: clamp(50%, 500px, 20%); */
|
||||
/* height: min(50%, 100px); */
|
||||
display: flex;
|
||||
align-items: center;
|
||||
/* background-color: yellow; */
|
||||
@ -134,7 +130,6 @@ select{
|
||||
background-color: rgb(26, 26, 26);
|
||||
/* height: calc(100% - 118px); */
|
||||
width: 70%;
|
||||
/* height: 300px; */
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
@ -174,17 +169,11 @@ input{
|
||||
|
||||
.messageContent{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
max-width: 80%;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
p {
|
||||
overflow-wrap: break-word;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.meMessage{
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
@ -204,18 +193,6 @@ p {
|
||||
margin: 1%;
|
||||
}
|
||||
|
||||
.darkSubmit{
|
||||
display: inline-block;
|
||||
color: white;
|
||||
background-color: #282155;
|
||||
border-radius: 10px;
|
||||
padding: 5px;
|
||||
font-size: 1.2rem;
|
||||
text-decoration: none;
|
||||
font-weight:lighter;
|
||||
margin: 1%;
|
||||
}
|
||||
|
||||
.div_submit {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
@ -288,12 +265,6 @@ p {
|
||||
background-color: rgba(212, 175, 55, 0.7);
|
||||
font-size: 25px;
|
||||
color: rgba(255, 255, 255, 1);
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.yellowAlert::p {
|
||||
overflow-wrap: break-word;
|
||||
max-width: 1000px;
|
||||
}
|
||||
|
||||
.modalSetting{
|
||||
@ -316,7 +287,7 @@ p {
|
||||
|
||||
.settingSecondPart{
|
||||
margin-top: 10%;
|
||||
margin-left: 5%;
|
||||
margin-left: 10%;
|
||||
|
||||
/* margin-left: 20%; */
|
||||
}
|
||||
@ -334,20 +305,3 @@ input.in{
|
||||
border-radius: 12px;
|
||||
width: 70%;
|
||||
}
|
||||
|
||||
input.in_howLong{
|
||||
margin-top: 14.5%;
|
||||
margin-left: 0px;
|
||||
background-color: black;
|
||||
color: white;
|
||||
border-radius: 12px;
|
||||
width: 15%;
|
||||
}
|
||||
|
||||
.mdp{
|
||||
background-color : black;
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
width: 20%;
|
||||
}
|
||||
|
||||
|
||||
@ -1,75 +1,11 @@
|
||||
/* Container style */
|
||||
.file-upload-container {
|
||||
|
||||
margin-left: 2rem;
|
||||
font-size: 1.7rem;
|
||||
/* background: #5843e4; */
|
||||
/* color:#f5f5f5; */
|
||||
margin: 0 16px;
|
||||
text-decoration: none;
|
||||
padding: 10px 16px;
|
||||
border-radius: 20px;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
/* File input style */
|
||||
.file-input {
|
||||
/* background: #5843e4; */
|
||||
/* color:#f5f5f5; */
|
||||
display: none; /* Hide the default file input */
|
||||
}
|
||||
|
||||
.file-label {
|
||||
padding: 8px 12px;
|
||||
background-color: #f2f2f2;
|
||||
color: #555;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.file-label:hover {
|
||||
background-color: #e0e0e0;
|
||||
}
|
||||
|
||||
/* Button style */
|
||||
.upload-button {
|
||||
padding: 8px 12px;
|
||||
background-color: #5843e4;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.upload-button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
.page {
|
||||
text-align: center;
|
||||
overflow-y: scroll;
|
||||
/* height: 50vh; */
|
||||
/* width: 50vh; */
|
||||
/* background-color: black; */
|
||||
}
|
||||
|
||||
.profile {
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
flex-direction: row;
|
||||
color: white;
|
||||
}
|
||||
@ -82,7 +18,7 @@
|
||||
border-color: red;
|
||||
/* border-image: linear-gradient(90deg, #5843e4, #5a0760); */
|
||||
|
||||
/* margin-top: 20px; */
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.home{
|
||||
@ -109,7 +45,7 @@
|
||||
.div_history {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
/* margin-top: -80px; */
|
||||
margin-top: -80px;
|
||||
}
|
||||
|
||||
.edit_name {
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
/* display: flex; */
|
||||
/* flex-direction: column; */
|
||||
/* background-color: red; */
|
||||
height: 60vh;
|
||||
height: 70vh;
|
||||
/* padding: 15px; */
|
||||
/* overflow: scroll; */
|
||||
|
||||
|
||||
@ -1,21 +1,16 @@
|
||||
.playButton {
|
||||
background-image: linear-gradient(90deg, #5843e4, #5a0760);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
background-image: linear-gradient(90deg, #5843e4, #5a0760);;
|
||||
border-radius: 5vh;
|
||||
color: white;
|
||||
/* display: block; */
|
||||
display: block;
|
||||
margin: auto;
|
||||
margin-top: 30vh;
|
||||
padding: 2vh 4vw;
|
||||
padding: 2vh 5vw;
|
||||
height: 10vh;
|
||||
width: 20vw;
|
||||
font-size: 250%;
|
||||
text-align: center;
|
||||
font-size: 300%;
|
||||
}
|
||||
|
||||
|
||||
.field {
|
||||
background-color: rgb(249, 249, 249);
|
||||
/* border-radius: 5vh; */
|
||||
@ -45,29 +40,6 @@
|
||||
/* padding-top: 25; */
|
||||
/* padding-top: 177.77% */
|
||||
}
|
||||
@media screen and (max-width: 900px){
|
||||
.playButton{
|
||||
font-size: 200%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 700px){
|
||||
.playButton{
|
||||
font-size: 150%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 530px){
|
||||
.playButton{
|
||||
font-size: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 350px){
|
||||
.playButton{
|
||||
font-size: 50%;
|
||||
}
|
||||
}
|
||||
|
||||
#myCanvas {
|
||||
background-color: rgb(124, 47, 47);
|
||||
|
||||
@ -77,6 +77,11 @@ input{
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
label{
|
||||
}
|
||||
|
||||
.login {
|
||||
}
|
||||
|
||||
.loginForm {
|
||||
align-items: center;
|
||||
|
||||
@ -1,111 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Visit https://aka.ms/tsconfig to read more about this file */
|
||||
"jsx": "react",
|
||||
"noEmit": true,
|
||||
"allowImportingTsExtensions": true,
|
||||
/* Projects */
|
||||
// "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */
|
||||
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
|
||||
// "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */
|
||||
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */
|
||||
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
|
||||
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
|
||||
|
||||
/* Language and Environment */
|
||||
"target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
|
||||
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
|
||||
// "jsx": "preserve", /* Specify what JSX code is generated. */
|
||||
// "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
|
||||
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */
|
||||
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
|
||||
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */
|
||||
// "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */
|
||||
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
|
||||
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
|
||||
// "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */
|
||||
|
||||
/* Modules */
|
||||
"module": "commonjs", /* Specify what module code is generated. */
|
||||
// "rootDir": "./", /* Specify the root folder within your source files. */
|
||||
// "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */
|
||||
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
|
||||
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
|
||||
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
|
||||
// "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */
|
||||
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
// "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */
|
||||
// "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */
|
||||
// "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */
|
||||
// "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */
|
||||
// "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */
|
||||
// "resolveJsonModule": true, /* Enable importing .json files. */
|
||||
// "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */
|
||||
// "noResolve": true, /* Disallow 'import's, 'require's or '<reference>'s from expanding the number of files TypeScript should add to a project. */
|
||||
|
||||
/* JavaScript Support */
|
||||
// "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
|
||||
// "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */
|
||||
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */
|
||||
|
||||
/* Emit */
|
||||
// "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
|
||||
// "declarationMap": true, /* Create sourcemaps for d.ts files. */
|
||||
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
|
||||
// "sourceMap": true, /* Create source map files for emitted JavaScript files. */
|
||||
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
|
||||
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */
|
||||
// "outDir": "./", /* Specify an output folder for all emitted files. */
|
||||
// "removeComments": true, /* Disable emitting comments. */
|
||||
// "noEmit": true, /* Disable emitting files from a compilation. */
|
||||
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
|
||||
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */
|
||||
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
|
||||
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
|
||||
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
|
||||
// "newLine": "crlf", /* Set the newline character for emitting files. */
|
||||
// "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */
|
||||
// "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */
|
||||
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
|
||||
// "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */
|
||||
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
|
||||
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
|
||||
|
||||
/* Interop Constraints */
|
||||
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
|
||||
// "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
|
||||
"esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
|
||||
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
|
||||
"forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */
|
||||
|
||||
/* Type Checking */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */
|
||||
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
|
||||
// "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */
|
||||
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
|
||||
// "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */
|
||||
// "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */
|
||||
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
|
||||
// "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */
|
||||
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */
|
||||
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
|
||||
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
|
||||
// "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */
|
||||
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
|
||||
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */
|
||||
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
|
||||
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
|
||||
|
||||
/* Completeness */
|
||||
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
|
||||
"skipLibCheck": true /* Skip type checking all .d.ts files. */
|
||||
}
|
||||
}
|
||||
2
containers/test
Normal file
2
containers/test
Normal file
@ -0,0 +1,2 @@
|
||||
cc toi
|
||||
cc 2
|
||||
@ -11,7 +11,7 @@ services:
|
||||
|
||||
# command: sh -c "envsubst < /etc/nginx/conf.d/default.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'"
|
||||
ports:
|
||||
- 8080:8080
|
||||
- 80:80
|
||||
volumes:
|
||||
- ./conf/nginx.conf:/etc/nginx/conf.d/default.conf
|
||||
# volumes:
|
||||
@ -34,7 +34,7 @@ services:
|
||||
# depends_on:
|
||||
# - nginx
|
||||
ports:
|
||||
- 8001:8001
|
||||
- 8080:8080
|
||||
volumes:
|
||||
- ./containers/react:/app
|
||||
# - ./containers/react:/app
|
||||
|
||||
Loading…
Reference in New Issue
Block a user