new sadjigui
9
Makefile
@ -6,13 +6,13 @@
|
|||||||
# By: apommier <apommier@student.42.fr> +#+ +:+ +#+ #
|
# By: apommier <apommier@student.42.fr> +#+ +:+ +#+ #
|
||||||
# +#+#+#+#+#+ +#+ #
|
# +#+#+#+#+#+ +#+ #
|
||||||
# Created: 2023/03/19 09:29:27 by apommier #+# #+# #
|
# Created: 2023/03/19 09:29:27 by apommier #+# #+# #
|
||||||
# Updated: 2023/03/19 11:22:00 by apommier ### ########.fr #
|
# Updated: 2023/04/04 18:14:43 by apommier ### ########.fr #
|
||||||
# #
|
# #
|
||||||
# **************************************************************************** #
|
# **************************************************************************** #
|
||||||
|
|
||||||
all:
|
all:
|
||||||
# -mkdir -p /home/apommier/data/wordpress
|
# -mkdir -p /home/apommier/data/wordpress
|
||||||
# -mkdir -p /home/apommier/data/mariadb
|
-mkdir -p /home/apommier/data/pgsql
|
||||||
docker-compose -f docker-compose.yml up --build
|
docker-compose -f docker-compose.yml up --build
|
||||||
|
|
||||||
fclean: down
|
fclean: down
|
||||||
@ -22,6 +22,9 @@ fclean: down
|
|||||||
-docker rmi -f $$(docker images -qa)
|
-docker rmi -f $$(docker images -qa)
|
||||||
-docker volume rm $$(docker volume ls -q)
|
-docker volume rm $$(docker volume ls -q)
|
||||||
-docker network rm $$(docker network ls -q)
|
-docker network rm $$(docker network ls -q)
|
||||||
|
|
||||||
|
volume:
|
||||||
|
-docker volume rm $$(docker volume ls -q)
|
||||||
up:
|
up:
|
||||||
docker-compose -f ./docker-compose.yml up
|
docker-compose -f ./docker-compose.yml up
|
||||||
|
|
||||||
|
|||||||
25
backend/.eslintrc.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module.exports = {
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
project: 'tsconfig.json',
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||||
|
extends: [
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:prettier/recommended',
|
||||||
|
],
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
jest: true,
|
||||||
|
},
|
||||||
|
ignorePatterns: ['.eslintrc.js'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/interface-name-prefix': 'off',
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
},
|
||||||
|
};
|
||||||
35
backend/.gitignore
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# compiled output
|
||||||
|
/dist
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
/coverage
|
||||||
|
/.nyc_output
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
4
backend/.prettierrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all"
|
||||||
|
}
|
||||||
73
backend/README.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<p align="center">
|
||||||
|
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
|
||||||
|
[circleci-url]: https://circleci.com/gh/nestjs/nest
|
||||||
|
|
||||||
|
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
||||||
|
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
||||||
|
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
|
||||||
|
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
|
||||||
|
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
|
||||||
|
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
|
||||||
|
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
||||||
|
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
||||||
|
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
|
||||||
|
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
|
||||||
|
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
|
||||||
|
</p>
|
||||||
|
<!--[](https://opencollective.com/nest#backer)
|
||||||
|
[](https://opencollective.com/nest#sponsor)-->
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running the app
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# development
|
||||||
|
$ npm run start
|
||||||
|
|
||||||
|
# watch mode
|
||||||
|
$ npm run start:dev
|
||||||
|
|
||||||
|
# production mode
|
||||||
|
$ npm run start:prod
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# unit tests
|
||||||
|
$ npm run test
|
||||||
|
|
||||||
|
# e2e tests
|
||||||
|
$ npm run test:e2e
|
||||||
|
|
||||||
|
# test coverage
|
||||||
|
$ npm run test:cov
|
||||||
|
```
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
|
||||||
|
|
||||||
|
## Stay in touch
|
||||||
|
|
||||||
|
- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
|
||||||
|
- Website - [https://nestjs.com](https://nestjs.com/)
|
||||||
|
- Twitter - [@nestframework](https://twitter.com/nestframework)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Nest is [MIT licensed](LICENSE).
|
||||||
8
backend/nest-cli.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/nest-cli",
|
||||||
|
"collection": "@nestjs/schematics",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"compilerOptions": {
|
||||||
|
"deleteOutDir": true
|
||||||
|
}
|
||||||
|
}
|
||||||
6740
backend/package-lock.json
generated
@ -1,16 +1,77 @@
|
|||||||
{
|
{
|
||||||
"name": "dockernodejspong",
|
"name": "pong",
|
||||||
"version": "1.0.0",
|
"version": "0.0.1",
|
||||||
"description": "Web server to run an online pong",
|
"description": "",
|
||||||
"author": "apommier",
|
"author": "",
|
||||||
"main": "server.js",
|
"private": true,
|
||||||
|
"license": "UNLICENSED",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "node server.js"
|
"build": "nest build",
|
||||||
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||||
|
"start": "nest start",
|
||||||
|
"start:dev": "nest start --watch",
|
||||||
|
"start:debug": "nest start --debug --watch",
|
||||||
|
"start:prod": "node dist/main",
|
||||||
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||||
|
"test": "jest",
|
||||||
|
"test:watch": "jest --watch",
|
||||||
|
"test:cov": "jest --coverage",
|
||||||
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
|
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "^1.20.2",
|
"@nestjs/axios": "^2.0.0",
|
||||||
"express": "^4.18.2"
|
"@nestjs/common": "^9.0.0",
|
||||||
|
"@nestjs/core": "^9.0.0",
|
||||||
|
"@nestjs/platform-express": "^9.0.0",
|
||||||
|
"@nestjs/typeorm": "^9.0.1",
|
||||||
|
"axios": "^1.3.5",
|
||||||
|
"dotenv": "^16.0.3",
|
||||||
|
"pg": "^8.10.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rxjs": "^7.2.0",
|
||||||
|
"typeorm": "^0.3.15",
|
||||||
|
"webpack": "^5.79.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {},
|
"devDependencies": {
|
||||||
"license": "ISC"
|
"@nestjs/cli": "^9.0.0",
|
||||||
|
"@nestjs/schematics": "^9.0.0",
|
||||||
|
"@nestjs/testing": "^9.0.0",
|
||||||
|
"@types/express": "^4.17.13",
|
||||||
|
"@types/jest": "29.5.0",
|
||||||
|
"@types/node": "18.15.11",
|
||||||
|
"@types/supertest": "^2.0.11",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||||
|
"@typescript-eslint/parser": "^5.0.0",
|
||||||
|
"eslint": "^8.0.1",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
|
"jest": "29.5.0",
|
||||||
|
"nodemon": "^2.0.22",
|
||||||
|
"prettier": "^2.3.2",
|
||||||
|
"source-map-support": "^0.5.20",
|
||||||
|
"supertest": "^6.1.3",
|
||||||
|
"ts-jest": "29.0.5",
|
||||||
|
"ts-loader": "^9.2.3",
|
||||||
|
"ts-node": "^10.9.1",
|
||||||
|
"tsconfig-paths": "4.2.0",
|
||||||
|
"typescript": "^4.7.4"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"js",
|
||||||
|
"json",
|
||||||
|
"ts"
|
||||||
|
],
|
||||||
|
"rootDir": "src",
|
||||||
|
"testRegex": ".*\\.spec\\.ts$",
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
|
},
|
||||||
|
"collectCoverageFrom": [
|
||||||
|
"**/*.(t|j)s"
|
||||||
|
],
|
||||||
|
"coverageDirectory": "../coverage",
|
||||||
|
"testEnvironment": "node"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +0,0 @@
|
|||||||
const express = require('express');
|
|
||||||
const bodyParser = require('body-parser');
|
|
||||||
const app = express();
|
|
||||||
// app.use(express.json());
|
|
||||||
|
|
||||||
app.use(bodyParser.urlencoded({ extended: false }));
|
|
||||||
app.use(bodyParser.json());
|
|
||||||
|
|
||||||
app.get('/api/test', (req, res) => {
|
|
||||||
res.send('Hello World!')
|
|
||||||
})
|
|
||||||
|
|
||||||
app.post('/api/login', (req, res) => {
|
|
||||||
|
|
||||||
// const formData = req.body;
|
|
||||||
// console.log(formData);
|
|
||||||
console.log('get request');
|
|
||||||
console.log(req.body);
|
|
||||||
res.status(201).json(req.body);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.listen(5000, () => console.log('Server is up and running'));
|
|
||||||
22
backend/src/app.controller.spec.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { AppController } from './app.controller';
|
||||||
|
import { AppService } from './app.service';
|
||||||
|
|
||||||
|
describe('AppController', () => {
|
||||||
|
let appController: AppController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const app: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [AppController],
|
||||||
|
providers: [AppService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
appController = app.get<AppController>(AppController);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('root', () => {
|
||||||
|
it('should return "Hello World!"', () => {
|
||||||
|
expect(appController.getHello()).toBe('Hello World!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
61
backend/src/app.controller.ts
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { Body, Controller, Get, Param, Post, Query, InternalServerErrorException } from '@nestjs/common';
|
||||||
|
// import { AppService } from './app.service.js';
|
||||||
|
import { UsersService } from './app.service';
|
||||||
|
import { User } from './model/item.entity';
|
||||||
|
// import { HttpService } from '@nestjs/common';
|
||||||
|
// import { HttpService } from '@nestjs/axios'
|
||||||
|
import axios from 'axios';
|
||||||
|
import { AxiosResponse } from 'axios';
|
||||||
|
|
||||||
|
|
||||||
|
@Controller()
|
||||||
|
export class AppController2 {
|
||||||
|
constructor(private readonly usersService: UsersService) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
getHello(): string {
|
||||||
|
return this.usersService.getHello();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Controller('api')
|
||||||
|
export class AppController
|
||||||
|
{
|
||||||
|
constructor(private readonly usersService: UsersService) {}
|
||||||
|
|
||||||
|
@Post('token')
|
||||||
|
async getToken(@Body('code') code: string): Promise<any>
|
||||||
|
{
|
||||||
|
const http = axios;
|
||||||
|
console.log(`here is the code= ${code}`);
|
||||||
|
const data = {
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
client_id: 'u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41',
|
||||||
|
client_secret: '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',
|
||||||
|
code: code,
|
||||||
|
redirect_uri: 'http://localhost:8080/login42',
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
const response: AxiosResponse = await http.post('https://api.intra.42.fr/oauth/token', data);
|
||||||
|
// console.log(`response= ${response}`);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
catch (error)
|
||||||
|
{
|
||||||
|
console.error(error);
|
||||||
|
throw new InternalServerErrorException('Failed to get access token');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('login')
|
||||||
|
async create(@Body() user: User)
|
||||||
|
{
|
||||||
|
return this.usersService.create(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Get('user/:id')
|
||||||
|
async getUser(@Param('id') id: number)
|
||||||
|
{
|
||||||
|
return this.usersService.findOne(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
30
backend/src/app.module.ts
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
// import { Module } from '@nestjs/common';
|
||||||
|
// import { AppController } from './app.controller';
|
||||||
|
// import { AppService } from './app.service';
|
||||||
|
|
||||||
|
// @Module({
|
||||||
|
// imports: [],
|
||||||
|
// controllers: [AppController],
|
||||||
|
// providers: [AppService],
|
||||||
|
// })
|
||||||
|
// export class AppModule {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { AppController } from './app.controller';
|
||||||
|
import { AppService, UsersService } from './app.service';
|
||||||
|
import { User } from './model/item.entity';
|
||||||
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { getTypeOrmConfig } from './config/config.service';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [
|
||||||
|
TypeOrmModule.forRoot(getTypeOrmConfig()),
|
||||||
|
TypeOrmModule.forFeature([User]),
|
||||||
|
// TypeOrmModule.forFeature([UserRepository]),
|
||||||
|
],
|
||||||
|
controllers: [AppController],
|
||||||
|
providers: [AppService, UsersService],
|
||||||
|
})
|
||||||
|
export class AppModule { }
|
||||||
46
backend/src/app.service.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
|
import { Repository } from 'typeorm';
|
||||||
|
import { User } from './model/item.entity';
|
||||||
|
// import { User } from './entity/user.entity';
|
||||||
|
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppService {
|
||||||
|
getHello(): string {
|
||||||
|
return 'Hello World!';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class UsersService {
|
||||||
|
constructor(
|
||||||
|
@InjectRepository(User) private userRepository: Repository<User>,
|
||||||
|
) {}
|
||||||
|
// constructor(
|
||||||
|
// @InjectRepository(User)
|
||||||
|
// private usersRepository: Repository<User>,
|
||||||
|
// ) {}
|
||||||
|
// constructor(
|
||||||
|
// @InjectRepository(User)
|
||||||
|
// private usersRepository: Repository<User>,
|
||||||
|
// ) {}
|
||||||
|
// constructor(private usersRepository: Repository<User>) {}
|
||||||
|
|
||||||
|
getHello(): string {
|
||||||
|
return 'Hello World!';
|
||||||
|
}
|
||||||
|
|
||||||
|
async create(user: User): Promise<User> {
|
||||||
|
return await this.userRepository.save(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
async findAll(): Promise<User[]> {
|
||||||
|
return await this.userRepository.find();
|
||||||
|
}
|
||||||
|
|
||||||
|
async findOne(id: number): Promise<User> {
|
||||||
|
return await this.userRepository.findOneBy({id: id});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
26
backend/src/config/config.service.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
/* ************************************************************************** */
|
||||||
|
/* */
|
||||||
|
/* ::: :::::::: */
|
||||||
|
/* config.service.ts :+: :+: :+: */
|
||||||
|
/* +:+ +:+ +:+ */
|
||||||
|
/* By: apommier <apommier@student.42.fr> +#+ +:+ +#+ */
|
||||||
|
/* +#+#+#+#+#+ +#+ */
|
||||||
|
/* Created: 2023/04/09 14:53:49 by apommier #+# #+# */
|
||||||
|
/* Updated: 2023/04/09 14:55:40 by apommier ### ########.fr */
|
||||||
|
/* */
|
||||||
|
/* ************************************************************************** */
|
||||||
|
|
||||||
|
import { TypeOrmModuleOptions } from '@nestjs/typeorm';
|
||||||
|
export const getTypeOrmConfig = (): TypeOrmModuleOptions => ({
|
||||||
|
type: 'postgres',
|
||||||
|
host: 'postgresql',
|
||||||
|
port: 5432,
|
||||||
|
username: 'postgres',
|
||||||
|
password: 'pass',
|
||||||
|
database: 'postgres',
|
||||||
|
entities: ['**/*.entity{.ts,.js}'],
|
||||||
|
migrationsTableName: 'migration',
|
||||||
|
migrations: ['src/migration/*.ts'],
|
||||||
|
ssl: process.env.MODE !== 'DEV',
|
||||||
|
synchronize: true,
|
||||||
|
});
|
||||||
17
backend/src/main.ts
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { NestFactory } from '@nestjs/core';
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
|
||||||
|
async function bootstrap() {
|
||||||
|
const app = await NestFactory.create(AppModule, {
|
||||||
|
cors: {
|
||||||
|
origin: '*',
|
||||||
|
methods: '*',
|
||||||
|
// preflightContinue: false,
|
||||||
|
// optionsSuccessStatus: 204,
|
||||||
|
// credentials: true,
|
||||||
|
allowedHeaders: '*',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
await app.listen(3000);
|
||||||
|
}
|
||||||
|
bootstrap();
|
||||||
83
backend/src/model/base.entity.ts
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// // import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
|
||||||
|
// import {Entity, PrimaryGeneratedColumn, Column} from 'typeorm';
|
||||||
|
|
||||||
|
// @Entity()
|
||||||
|
// export class User {
|
||||||
|
// @PrimaryGeneratedColumn()
|
||||||
|
// id: number;
|
||||||
|
|
||||||
|
// @Column()
|
||||||
|
// nickName: string;
|
||||||
|
|
||||||
|
// @Column()
|
||||||
|
// Password: string;
|
||||||
|
|
||||||
|
// @Column()
|
||||||
|
// email: string;
|
||||||
|
|
||||||
|
// @Column()
|
||||||
|
// password: string;
|
||||||
|
|
||||||
|
// @Column()
|
||||||
|
// win: number;
|
||||||
|
|
||||||
|
// @Column()
|
||||||
|
// loose: number;
|
||||||
|
|
||||||
|
// // friend
|
||||||
|
// // joined chat
|
||||||
|
// // jsp
|
||||||
|
// // prout
|
||||||
|
// }
|
||||||
|
|
||||||
|
// base.entity.ts
|
||||||
|
// @PrimaryGeneratedColumn('uuid')
|
||||||
|
// id: string;
|
||||||
|
|
||||||
|
// @Column({ type: 'boolean', default: true })
|
||||||
|
// isActive: boolean;
|
||||||
|
|
||||||
|
// @Column({ type: 'boolean', default: false })
|
||||||
|
// isArchived: boolean;
|
||||||
|
|
||||||
|
// @CreateDateColumn({ type: 'timestamptz', default: () => 'CURRENT_TIMESTAMP' })
|
||||||
|
// createDateTime: Date;
|
||||||
|
|
||||||
|
// @Column({ type: 'varchar', length: 300 })
|
||||||
|
// createdBy: string;
|
||||||
|
|
||||||
|
// @UpdateDateColumn({ type: 'timestamptz', default: () => 'CURRENT_TIMESTAMP' })
|
||||||
|
// lastChangedDateTime: Date;
|
||||||
|
|
||||||
|
// @Column({ type: 'varchar', length: 300 })
|
||||||
|
// lastChangedBy: string;
|
||||||
|
|
||||||
|
// @Column({ type: 'varchar', length: 300, nullable: true })
|
||||||
|
// internalComment: string | null;
|
||||||
|
import { PrimaryGeneratedColumn, Column, UpdateDateColumn, CreateDateColumn } from 'typeorm';
|
||||||
|
|
||||||
|
export abstract class BaseEntity {
|
||||||
|
@PrimaryGeneratedColumn()
|
||||||
|
id: number;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
nickname: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
password: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
email: string;
|
||||||
|
|
||||||
|
// @Column({ nullable: true })
|
||||||
|
// password: string;
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
win: number;
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
loose: number;
|
||||||
|
|
||||||
|
@Column({ default: 0 })
|
||||||
|
rank: number;
|
||||||
|
}
|
||||||
13
backend/src/model/item.entity.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// item.entity.ts
|
||||||
|
import { Entity, Column } from 'typeorm';
|
||||||
|
import { BaseEntity } from './base.entity';
|
||||||
|
|
||||||
|
@Entity({ name: 'User' })
|
||||||
|
export class User extends BaseEntity {
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', length: 300 , nullable: true})
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column({ type: 'varchar', length: 300 , nullable: true})
|
||||||
|
description: string;
|
||||||
|
}
|
||||||
24
backend/test/app.e2e-spec.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { INestApplication } from '@nestjs/common';
|
||||||
|
import * as request from 'supertest';
|
||||||
|
import { AppModule } from './../src/app.module';
|
||||||
|
|
||||||
|
describe('AppController (e2e)', () => {
|
||||||
|
let app: INestApplication;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const moduleFixture: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AppModule],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
app = moduleFixture.createNestApplication();
|
||||||
|
await app.init();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/ (GET)', () => {
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.get('/')
|
||||||
|
.expect(200)
|
||||||
|
.expect('Hello World!');
|
||||||
|
});
|
||||||
|
});
|
||||||
9
backend/test/jest-e2e.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"moduleFileExtensions": ["js", "json", "ts"],
|
||||||
|
"rootDir": ".",
|
||||||
|
"testEnvironment": "node",
|
||||||
|
"testRegex": ".e2e-spec.ts$",
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
|
}
|
||||||
|
}
|
||||||
4
backend/tsconfig.build.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||||
|
}
|
||||||
21
backend/tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"declaration": true,
|
||||||
|
"removeComments": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"target": "es2017",
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"incremental": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strictNullChecks": false,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"strictBindCallApply": false,
|
||||||
|
"forceConsistentCasingInFileNames": false,
|
||||||
|
"noFallthroughCasesInSwitch": false
|
||||||
|
}
|
||||||
|
}
|
||||||
25
chat/.eslintrc.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
module.exports = {
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
project: 'tsconfig.json',
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
sourceType: 'module',
|
||||||
|
},
|
||||||
|
plugins: ['@typescript-eslint/eslint-plugin'],
|
||||||
|
extends: [
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:prettier/recommended',
|
||||||
|
],
|
||||||
|
root: true,
|
||||||
|
env: {
|
||||||
|
node: true,
|
||||||
|
jest: true,
|
||||||
|
},
|
||||||
|
ignorePatterns: ['.eslintrc.js'],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/interface-name-prefix': 'off',
|
||||||
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
|
'@typescript-eslint/explicit-module-boundary-types': 'off',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
},
|
||||||
|
};
|
||||||
35
chat/.gitignore
vendored
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
# compiled output
|
||||||
|
/dist
|
||||||
|
/node_modules
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Tests
|
||||||
|
/coverage
|
||||||
|
/.nyc_output
|
||||||
|
|
||||||
|
# IDEs and editors
|
||||||
|
/.idea
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.c9/
|
||||||
|
*.launch
|
||||||
|
.settings/
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# IDE - VSCode
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/settings.json
|
||||||
|
!.vscode/tasks.json
|
||||||
|
!.vscode/launch.json
|
||||||
|
!.vscode/extensions.json
|
||||||
4
chat/.prettierrc
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all"
|
||||||
|
}
|
||||||
73
chat/README.md
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<p align="center">
|
||||||
|
<a href="http://nestjs.com/" target="blank"><img src="https://nestjs.com/img/logo-small.svg" width="200" alt="Nest Logo" /></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456
|
||||||
|
[circleci-url]: https://circleci.com/gh/nestjs/nest
|
||||||
|
|
||||||
|
<p align="center">A progressive <a href="http://nodejs.org" target="_blank">Node.js</a> framework for building efficient and scalable server-side applications.</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/v/@nestjs/core.svg" alt="NPM Version" /></a>
|
||||||
|
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/l/@nestjs/core.svg" alt="Package License" /></a>
|
||||||
|
<a href="https://www.npmjs.com/~nestjscore" target="_blank"><img src="https://img.shields.io/npm/dm/@nestjs/common.svg" alt="NPM Downloads" /></a>
|
||||||
|
<a href="https://circleci.com/gh/nestjs/nest" target="_blank"><img src="https://img.shields.io/circleci/build/github/nestjs/nest/master" alt="CircleCI" /></a>
|
||||||
|
<a href="https://coveralls.io/github/nestjs/nest?branch=master" target="_blank"><img src="https://coveralls.io/repos/github/nestjs/nest/badge.svg?branch=master#9" alt="Coverage" /></a>
|
||||||
|
<a href="https://discord.gg/G7Qnnhy" target="_blank"><img src="https://img.shields.io/badge/discord-online-brightgreen.svg" alt="Discord"/></a>
|
||||||
|
<a href="https://opencollective.com/nest#backer" target="_blank"><img src="https://opencollective.com/nest/backers/badge.svg" alt="Backers on Open Collective" /></a>
|
||||||
|
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://opencollective.com/nest/sponsors/badge.svg" alt="Sponsors on Open Collective" /></a>
|
||||||
|
<a href="https://paypal.me/kamilmysliwiec" target="_blank"><img src="https://img.shields.io/badge/Donate-PayPal-ff3f59.svg"/></a>
|
||||||
|
<a href="https://opencollective.com/nest#sponsor" target="_blank"><img src="https://img.shields.io/badge/Support%20us-Open%20Collective-41B883.svg" alt="Support us"></a>
|
||||||
|
<a href="https://twitter.com/nestframework" target="_blank"><img src="https://img.shields.io/twitter/follow/nestframework.svg?style=social&label=Follow"></a>
|
||||||
|
</p>
|
||||||
|
<!--[](https://opencollective.com/nest#backer)
|
||||||
|
[](https://opencollective.com/nest#sponsor)-->
|
||||||
|
|
||||||
|
## Description
|
||||||
|
|
||||||
|
[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Running the app
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# development
|
||||||
|
$ npm run start
|
||||||
|
|
||||||
|
# watch mode
|
||||||
|
$ npm run start:dev
|
||||||
|
|
||||||
|
# production mode
|
||||||
|
$ npm run start:prod
|
||||||
|
```
|
||||||
|
|
||||||
|
## Test
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# unit tests
|
||||||
|
$ npm run test
|
||||||
|
|
||||||
|
# e2e tests
|
||||||
|
$ npm run test:e2e
|
||||||
|
|
||||||
|
# test coverage
|
||||||
|
$ npm run test:cov
|
||||||
|
```
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support).
|
||||||
|
|
||||||
|
## Stay in touch
|
||||||
|
|
||||||
|
- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com)
|
||||||
|
- Website - [https://nestjs.com](https://nestjs.com/)
|
||||||
|
- Twitter - [@nestframework](https://twitter.com/nestframework)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Nest is [MIT licensed](LICENSE).
|
||||||
8
chat/nest-cli.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/nest-cli",
|
||||||
|
"collection": "@nestjs/schematics",
|
||||||
|
"sourceRoot": "src",
|
||||||
|
"compilerOptions": {
|
||||||
|
"deleteOutDir": true
|
||||||
|
}
|
||||||
|
}
|
||||||
8346
chat/package-lock.json
generated
Normal file
72
chat/package.json
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
{
|
||||||
|
"name": "chat",
|
||||||
|
"version": "0.0.1",
|
||||||
|
"description": "",
|
||||||
|
"author": "",
|
||||||
|
"private": true,
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"scripts": {
|
||||||
|
"build": "nest build",
|
||||||
|
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
||||||
|
"start": "nest start",
|
||||||
|
"start:dev": "nest start --watch",
|
||||||
|
"start:debug": "nest start --debug --watch",
|
||||||
|
"start:prod": "node dist/main",
|
||||||
|
"lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
|
||||||
|
"test": "jest",
|
||||||
|
"test:watch": "jest --watch",
|
||||||
|
"test:cov": "jest --coverage",
|
||||||
|
"test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
|
||||||
|
"test:e2e": "jest --config ./test/jest-e2e.json"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@nestjs/common": "^9.0.0",
|
||||||
|
"@nestjs/core": "^9.0.0",
|
||||||
|
"@nestjs/platform-express": "^9.0.0",
|
||||||
|
"@nestjs/websockets": "^9.4.0",
|
||||||
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rxjs": "^7.2.0",
|
||||||
|
"socket.io": "^4.6.1",
|
||||||
|
"uuid": "^9.0.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@nestjs/cli": "^9.0.0",
|
||||||
|
"@nestjs/schematics": "^9.0.0",
|
||||||
|
"@nestjs/testing": "^9.0.0",
|
||||||
|
"@types/express": "^4.17.13",
|
||||||
|
"@types/jest": "29.5.0",
|
||||||
|
"@types/node": "18.15.11",
|
||||||
|
"@types/supertest": "^2.0.11",
|
||||||
|
"@typescript-eslint/eslint-plugin": "^5.0.0",
|
||||||
|
"@typescript-eslint/parser": "^5.0.0",
|
||||||
|
"eslint": "^8.0.1",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-prettier": "^4.0.0",
|
||||||
|
"jest": "29.5.0",
|
||||||
|
"prettier": "^2.3.2",
|
||||||
|
"source-map-support": "^0.5.20",
|
||||||
|
"supertest": "^6.1.3",
|
||||||
|
"ts-jest": "29.0.5",
|
||||||
|
"ts-loader": "^9.2.3",
|
||||||
|
"ts-node": "^10.0.0",
|
||||||
|
"tsconfig-paths": "4.2.0",
|
||||||
|
"typescript": "^4.7.4"
|
||||||
|
},
|
||||||
|
"jest": {
|
||||||
|
"moduleFileExtensions": [
|
||||||
|
"js",
|
||||||
|
"json",
|
||||||
|
"ts"
|
||||||
|
],
|
||||||
|
"rootDir": "src",
|
||||||
|
"testRegex": ".*\\.spec\\.ts$",
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
|
},
|
||||||
|
"collectCoverageFrom": [
|
||||||
|
"**/*.(t|j)s"
|
||||||
|
],
|
||||||
|
"coverageDirectory": "../coverage",
|
||||||
|
"testEnvironment": "node"
|
||||||
|
}
|
||||||
|
}
|
||||||
22
chat/src/app.controller.spec.ts
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { AppController } from './app.controller';
|
||||||
|
import { AppService } from './app.service';
|
||||||
|
|
||||||
|
describe('AppController', () => {
|
||||||
|
let appController: AppController;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const app: TestingModule = await Test.createTestingModule({
|
||||||
|
controllers: [AppController],
|
||||||
|
providers: [AppService],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
appController = app.get<AppController>(AppController);
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('root', () => {
|
||||||
|
it('should return "Hello World!"', () => {
|
||||||
|
expect(appController.getHello()).toBe('Hello World!');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
12
chat/src/app.controller.ts
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Controller, Get } from '@nestjs/common';
|
||||||
|
import { AppService } from './app.service';
|
||||||
|
|
||||||
|
@Controller()
|
||||||
|
export class AppController {
|
||||||
|
constructor(private readonly appService: AppService) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
getHello(): string {
|
||||||
|
return this.appService.getHello();
|
||||||
|
}
|
||||||
|
}
|
||||||
11
chat/src/app.module.ts
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { AppController } from './app.controller';
|
||||||
|
import { AppService } from './app.service';
|
||||||
|
import { ChatGateway } from './chat/chat.gateway';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [],
|
||||||
|
controllers: [AppController],
|
||||||
|
providers: [AppService, ChatGateway],
|
||||||
|
})
|
||||||
|
export class AppModule {}
|
||||||
8
chat/src/app.service.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class AppService {
|
||||||
|
getHello(): string {
|
||||||
|
return 'Hello World!';
|
||||||
|
}
|
||||||
|
}
|
||||||
19
chat/src/chat/chat.gateway.spec.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { ChatGateway } from './chat.gateway';
|
||||||
|
|
||||||
|
describe('ChatGateway', () => {
|
||||||
|
let gateway: ChatGateway;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const module: TestingModule = await Test.createTestingModule({
|
||||||
|
providers: [ChatGateway],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
gateway = module.get<ChatGateway>(ChatGateway);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be defined', () => {
|
||||||
|
expect(gateway).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
4
|
||||||
45
chat/src/chat/chat.gateway.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import { SubscribeMessage, WebSocketGateway, OnGatewayInit, WebSocketServer, OnGatewayConnection, OnGatewayDisconnect } from '@nestjs/websockets';
|
||||||
|
import { Server, Socket } from 'socket.io';
|
||||||
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
|
@WebSocketGateway({ cors: true })
|
||||||
|
export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
|
||||||
|
|
||||||
|
|
||||||
|
private clients: Record<string, Socket> = {};
|
||||||
|
|
||||||
|
afterInit(server: Server)
|
||||||
|
{
|
||||||
|
console.log('ChatGateway initialized');
|
||||||
|
}
|
||||||
|
|
||||||
|
handleConnection(client: Socket, ...args: any[])
|
||||||
|
{
|
||||||
|
console.log(`Client connected: ${client.id}`);
|
||||||
|
|
||||||
|
const clientId = uuidv4();
|
||||||
|
this.clients[clientId] = client;
|
||||||
|
client.emit('chat:clientId', clientId);
|
||||||
|
|
||||||
|
console.log(`Total connected clients: ${Object.keys(this.clients).length}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleDisconnect(client: Socket)
|
||||||
|
{
|
||||||
|
console.log(`Client disconnected: ${client.id}`);
|
||||||
|
|
||||||
|
const disconnectedClientId = Object.keys(this.clients).find(clientId => this.clients[clientId] === client);
|
||||||
|
if (disconnectedClientId)
|
||||||
|
{
|
||||||
|
delete this.clients[disconnectedClientId];
|
||||||
|
console.log(`Client disconnected: ${disconnectedClientId}`);
|
||||||
|
console.log(`Total connected clients: ${Object.keys(this.clients).length}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SubscribeMessage('message')
|
||||||
|
handleMessage(client: any, payload: any): string {
|
||||||
|
return 'Hello world!';
|
||||||
|
}
|
||||||
|
}
|
||||||
36
chat/src/main.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import { NestFactory } from '@nestjs/core';
|
||||||
|
import { AppModule } from './app.module';
|
||||||
|
import * as socketio from 'socket.io';
|
||||||
|
|
||||||
|
async function bootstrap() {
|
||||||
|
const app = await NestFactory.create(AppModule, {
|
||||||
|
cors:
|
||||||
|
{
|
||||||
|
origin: '*',
|
||||||
|
methods: '*',
|
||||||
|
allowedHeaders: '*',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const httpServer = app.getHttpServer();
|
||||||
|
const io = new socketio.Server(httpServer);
|
||||||
|
|
||||||
|
io.on('connection', (socket) => {
|
||||||
|
console.log('Client connected:', socket.id);
|
||||||
|
|
||||||
|
// Gestion des événements personnalisés ici
|
||||||
|
socket.on('customEvent', (data) => {
|
||||||
|
console.log('Custom event received:', data);
|
||||||
|
|
||||||
|
// Exemple de réponse à un événement personnalisé
|
||||||
|
socket.emit('customEventResponse', { message: 'Event processed.' });
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('disconnect', () => {
|
||||||
|
console.log('Client disconnected:', socket.id);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await app.listen(4001);
|
||||||
|
}
|
||||||
|
bootstrap();
|
||||||
24
chat/test/app.e2e-spec.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { Test, TestingModule } from '@nestjs/testing';
|
||||||
|
import { INestApplication } from '@nestjs/common';
|
||||||
|
import * as request from 'supertest';
|
||||||
|
import { AppModule } from './../src/app.module';
|
||||||
|
|
||||||
|
describe('AppController (e2e)', () => {
|
||||||
|
let app: INestApplication;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
const moduleFixture: TestingModule = await Test.createTestingModule({
|
||||||
|
imports: [AppModule],
|
||||||
|
}).compile();
|
||||||
|
|
||||||
|
app = moduleFixture.createNestApplication();
|
||||||
|
await app.init();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('/ (GET)', () => {
|
||||||
|
return request(app.getHttpServer())
|
||||||
|
.get('/')
|
||||||
|
.expect(200)
|
||||||
|
.expect('Hello World!');
|
||||||
|
});
|
||||||
|
});
|
||||||
9
chat/test/jest-e2e.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"moduleFileExtensions": ["js", "json", "ts"],
|
||||||
|
"rootDir": ".",
|
||||||
|
"testEnvironment": "node",
|
||||||
|
"testRegex": ".e2e-spec.ts$",
|
||||||
|
"transform": {
|
||||||
|
"^.+\\.(t|j)s$": "ts-jest"
|
||||||
|
}
|
||||||
|
}
|
||||||
4
chat/tsconfig.build.json
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
|
||||||
|
}
|
||||||
21
chat/tsconfig.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"declaration": true,
|
||||||
|
"removeComments": true,
|
||||||
|
"emitDecoratorMetadata": true,
|
||||||
|
"experimentalDecorators": true,
|
||||||
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"target": "es2017",
|
||||||
|
"sourceMap": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"incremental": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strictNullChecks": false,
|
||||||
|
"noImplicitAny": false,
|
||||||
|
"strictBindCallApply": false,
|
||||||
|
"forceConsistentCasingInFileNames": false,
|
||||||
|
"noFallthroughCasesInSwitch": false
|
||||||
|
}
|
||||||
|
}
|
||||||
1
conf/init.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
ALTER USER postgres WITH PASSWORD 'pass';
|
||||||
@ -1,65 +1,25 @@
|
|||||||
# server {
|
|
||||||
# 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://backend:5000;
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
|
|
||||||
server {
|
server {
|
||||||
# listen 443 ssl;
|
# listen 443 ssl;
|
||||||
# listen 80 ssl;
|
# listen 80 ssl;
|
||||||
# listen 443 ssl;
|
# listen 443 ssl;
|
||||||
listen 80;
|
listen 80;
|
||||||
|
|
||||||
# server_name homemadePong.42.fr;
|
|
||||||
|
|
||||||
# ssl_protocols TLSv1.3;
|
location /{
|
||||||
# ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
|
|
||||||
# ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;
|
|
||||||
|
|
||||||
# root /var/www/html;
|
|
||||||
# index index.html;
|
|
||||||
|
|
||||||
# autoindex on;
|
|
||||||
location / {
|
|
||||||
root /var/www/html;
|
|
||||||
index index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
location /api/login {
|
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
|
||||||
proxy_pass http://backend:5000;
|
proxy_pass http://react_app:8080;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
location /api {
|
||||||
|
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://localhost:5000
|
proxy_pass http://backend:3000/api;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# server {
|
|
||||||
# listen 80;
|
|
||||||
# server_name localhost;
|
|
||||||
|
|
||||||
# }
|
|
||||||
|
|
||||||
# upstream loadbalancer {
|
|
||||||
# server backend:5000;
|
|
||||||
# }
|
|
||||||
|
|
||||||
# server {
|
|
||||||
# listen 80;
|
|
||||||
# server_name localhost;
|
|
||||||
# location / {
|
|
||||||
# proxy_pass http://loadbalancer;
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
|
|||||||
@ -3,57 +3,95 @@ version: "3.3"
|
|||||||
services:
|
services:
|
||||||
|
|
||||||
nginx:
|
nginx:
|
||||||
build:
|
image: nginx:alpine
|
||||||
context : ./
|
|
||||||
dockerfile: ./dockerfiles/Dockerfile.nginx
|
|
||||||
container_name: nginx
|
container_name: nginx
|
||||||
#image: nginx:homemade
|
env_file: .env
|
||||||
depends_on:
|
depends_on:
|
||||||
- backend
|
- backend
|
||||||
# - backend
|
|
||||||
ports:
|
ports:
|
||||||
- 80:80
|
- 80:80
|
||||||
# - 443:443
|
|
||||||
volumes:
|
volumes:
|
||||||
|
- ./conf/nginx.conf:/etc/nginx/conf.d/default.conf
|
||||||
- ./frontend:/var/www/html
|
- ./frontend:/var/www/html
|
||||||
restart: unless-stopped
|
|
||||||
networks:
|
networks:
|
||||||
- pongNetwork
|
- pongNetwork
|
||||||
|
|
||||||
# backend:
|
react_app:
|
||||||
|
image: node:latest
|
||||||
|
container_name: react_app
|
||||||
|
working_dir: /app
|
||||||
|
# depends_on:
|
||||||
|
# - nginx
|
||||||
|
ports:
|
||||||
|
- 8080:8080
|
||||||
|
volumes:
|
||||||
|
- ./frontend:/app
|
||||||
|
networks:
|
||||||
|
- pongNetwork
|
||||||
|
entrypoint: ["sh", "-c" , "npm install && npm run start:dev"]
|
||||||
|
|
||||||
|
|
||||||
backend:
|
backend:
|
||||||
|
# image: node:latest
|
||||||
build:
|
build:
|
||||||
context : ./
|
context : ./
|
||||||
dockerfile: ./dockerfiles/Dockerfile.backEnd
|
dockerfile: ./dockerfiles/Dockerfile.backEnd
|
||||||
container_name: backend
|
container_name: backend
|
||||||
ports:
|
ports:
|
||||||
- 5000:5000
|
- 3000:3000
|
||||||
#image: wordpress:homemade
|
|
||||||
env_file: .env
|
env_file: .env
|
||||||
volumes:
|
|
||||||
- ./frontend:/var/www/html
|
|
||||||
# volumes:
|
|
||||||
# - ./backend:/home/node/app
|
|
||||||
depends_on:
|
depends_on:
|
||||||
- postgresql
|
- postgresql
|
||||||
networks:
|
networks:
|
||||||
- pongNetwork
|
- pongNetwork
|
||||||
# restart: unless-stopped
|
# working_dir: /app
|
||||||
|
# volumes:
|
||||||
|
# - ./backend:/app
|
||||||
|
# entrypoint: ["sh", "-c" , "npm install && ls && ls dist && npm run build && npm run start"]
|
||||||
|
# entrypoint: ["/bin/sh", "-c" , "npm install && npm run start:dev "]
|
||||||
|
|
||||||
|
|
||||||
postgresql:
|
postgresql:
|
||||||
build: #./dockerfiles/Dockerfile.PostgreSQL
|
image: postgres:14.1-alpine
|
||||||
context : ./
|
restart: unless-stopped
|
||||||
dockerfile: ./dockerfiles/Dockerfile.PostgreSQL
|
|
||||||
container_name: postgresql
|
container_name: postgresql
|
||||||
#image: mariadb:homemade
|
environment:
|
||||||
|
- POSTGRES_USER=postgres
|
||||||
|
- POSTGRES_PASSWORD=postgres
|
||||||
ports:
|
ports:
|
||||||
- 3306:3306
|
- 5432:5432
|
||||||
env_file: .env
|
volumes:
|
||||||
#volumes:
|
- db:/var/lib/postgresql/data
|
||||||
# - dbdata:/var/lib/mysql
|
- ./conf/init.sql:/docker-entrypoint-initdb.d/create_tables.sql
|
||||||
networks:
|
networks:
|
||||||
- pongNetwork
|
- pongNetwork
|
||||||
restart: unless-stopped
|
|
||||||
|
pong:
|
||||||
|
image: node:latest
|
||||||
|
container_name: pong
|
||||||
|
working_dir: /app
|
||||||
|
ports:
|
||||||
|
- 4000:4000
|
||||||
|
env_file: .env
|
||||||
|
networks:
|
||||||
|
- pongNetwork
|
||||||
|
volumes:
|
||||||
|
- ./pong:/app
|
||||||
|
entrypoint: ["sh", "-c" , "npm install && npm run start:dev"]
|
||||||
|
|
||||||
|
# chat:
|
||||||
|
# image: node:latest
|
||||||
|
# container_name: chat
|
||||||
|
# working_dir: /app
|
||||||
|
# ports:
|
||||||
|
# - 4001:4001
|
||||||
|
# env_file: .env
|
||||||
|
# networks:
|
||||||
|
# - pongNetwork
|
||||||
|
# volumes:
|
||||||
|
# - ./chat:/app
|
||||||
|
# entrypoint: ["sh", "-c" , "npm install && npm run start:dev"]
|
||||||
|
|
||||||
|
|
||||||
networks:
|
networks:
|
||||||
pongNetwork:
|
pongNetwork:
|
||||||
@ -72,19 +110,11 @@ volumes:
|
|||||||
type: none
|
type: none
|
||||||
o: 'bind'
|
o: 'bind'
|
||||||
device: '/home/apommier/data/mariadb'
|
device: '/home/apommier/data/mariadb'
|
||||||
|
back:
|
||||||
# version: "3.3"
|
driver: local
|
||||||
# services:
|
driver_opts:
|
||||||
# backend:
|
type: none
|
||||||
# build:
|
o: 'bind'
|
||||||
# context: ./dockerfiles
|
device: '/backend'
|
||||||
# dockerfile: Dockerfile.backEnd
|
db:
|
||||||
# ports:
|
driver: local
|
||||||
# - "5000:5000"
|
|
||||||
# nginx:
|
|
||||||
# restart: always
|
|
||||||
# build:
|
|
||||||
# context: ./dockerfiles
|
|
||||||
# dockerfile: Dockerfile.nginx
|
|
||||||
# ports:
|
|
||||||
# - "80:80"
|
|
||||||
2
dockerfiles/.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules/
|
||||||
|
dist/
|
||||||
@ -6,8 +6,14 @@
|
|||||||
# By: apommier <apommier@student.42.fr> +#+ +:+ +#+ #
|
# By: apommier <apommier@student.42.fr> +#+ +:+ +#+ #
|
||||||
# +#+#+#+#+#+ +#+ #
|
# +#+#+#+#+#+ +#+ #
|
||||||
# Created: 2023/03/19 09:28:30 by apommier #+# #+# #
|
# Created: 2023/03/19 09:28:30 by apommier #+# #+# #
|
||||||
# Updated: 2023/03/19 11:24:21 by apommier ### ########.fr #
|
# Updated: 2023/04/12 23:40:10 by apommier ### ########.fr #
|
||||||
# #
|
# #
|
||||||
# **************************************************************************** #
|
# **************************************************************************** #
|
||||||
|
|
||||||
FROM postgres:latest
|
FROM postgres:alpine
|
||||||
|
COPY conf/init.sql /docker-entrypoint-initdb.d/
|
||||||
|
# COPY database/init.sh /docker-entrypoint-initdb.d//init-user-db.sh
|
||||||
|
|
||||||
|
# RUN sed -i 's/bind-address/bind-address = 0.0.0.0 #/i' /etc/mysql/mariadb.conf.d/50-server.cnf
|
||||||
|
EXPOSE 5432
|
||||||
|
CMD ["postgres"]
|
||||||
@ -6,29 +6,23 @@
|
|||||||
# By: apommier <apommier@student.42.fr> +#+ +:+ +#+ #
|
# By: apommier <apommier@student.42.fr> +#+ +:+ +#+ #
|
||||||
# +#+#+#+#+#+ +#+ #
|
# +#+#+#+#+#+ +#+ #
|
||||||
# Created: 2023/03/19 09:28:33 by apommier #+# #+# #
|
# Created: 2023/03/19 09:28:33 by apommier #+# #+# #
|
||||||
# Updated: 2023/03/22 12:14:35 by apommier ### ########.fr #
|
# Updated: 2023/04/17 05:22:39 by apommier ### ########.fr #
|
||||||
# #
|
# #
|
||||||
# **************************************************************************** #
|
# **************************************************************************** #
|
||||||
|
|
||||||
# FROM node:latest
|
|
||||||
# # RUN npm install
|
|
||||||
# # RUN apt install -y npm
|
|
||||||
# # RUN npm install express --save
|
|
||||||
# EXPOSE 8080
|
|
||||||
# WORKDIR /home/node/app
|
|
||||||
# COPY /backend/package*.json ./
|
|
||||||
# # RUN ls
|
|
||||||
# RUN npm install
|
|
||||||
# # RUN npm install express && npm install
|
|
||||||
# CMD [ "node", "server.js" ]
|
|
||||||
|
|
||||||
FROM node:alpine
|
|
||||||
FROM node:latest
|
FROM node:latest
|
||||||
WORKDIR /usr/src/app
|
|
||||||
|
WORKDIR /app
|
||||||
COPY /backend/package*.json ./
|
COPY /backend/package*.json ./
|
||||||
RUN npm install
|
RUN npm install
|
||||||
#npm install body-parser
|
|
||||||
COPY /backend/ .
|
COPY ./.env .
|
||||||
EXPOSE 5000
|
COPY /backend/tsconfig*.json ./
|
||||||
# CMD ["npm", "start"]
|
COPY /backend/src ./src
|
||||||
CMD ["node", "server.js"]
|
|
||||||
|
EXPOSE 3000
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
RUN rm -rf ./src
|
||||||
|
|
||||||
|
CMD ["npm", "run", "start"]
|
||||||
@ -6,12 +6,14 @@
|
|||||||
# By: apommier <apommier@student.42.fr> +#+ +:+ +#+ #
|
# By: apommier <apommier@student.42.fr> +#+ +:+ +#+ #
|
||||||
# +#+#+#+#+#+ +#+ #
|
# +#+#+#+#+#+ +#+ #
|
||||||
# Created: 2023/03/19 09:28:32 by apommier #+# #+# #
|
# Created: 2023/03/19 09:28:32 by apommier #+# #+# #
|
||||||
# Updated: 2023/03/21 11:08:16 by apommier ### ########.fr #
|
# Updated: 2023/04/07 13:38:20 by apommier ### ########.fr #
|
||||||
# #
|
# #
|
||||||
# **************************************************************************** #
|
# **************************************************************************** #
|
||||||
|
|
||||||
FROM nginx:latest
|
FROM nginx:latest
|
||||||
|
|
||||||
|
RUN apt-get update -y
|
||||||
|
RUN apt-get install -y postgresql-client
|
||||||
# RUN apt update -y
|
# RUN apt update -y
|
||||||
# RUN apt-get install -y openssl
|
# RUN apt-get install -y openssl
|
||||||
|
|
||||||
|
|||||||
20
dockerfiles/Dockerfile.react
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# Utilisez l'image de base de Node.js version 14
|
||||||
|
FROM node:latest
|
||||||
|
|
||||||
|
# Définissez le répertoire de travail à /app
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copiez le fichier package.json et package-lock.json à l'intérieur de l'image
|
||||||
|
COPY /frontend/pong/my-app/package*.json ./
|
||||||
|
|
||||||
|
# Installez les dépendances de l'application
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copiez le reste des fichiers de l'application dans l'image
|
||||||
|
COPY /frontend/pong/my-app/ .
|
||||||
|
|
||||||
|
# Exposez le port 3000 pour accéder à l'application dans le navigateur
|
||||||
|
EXPOSE 8080
|
||||||
|
|
||||||
|
# Démarrez l'application avec la commande "npm start"
|
||||||
|
CMD ["npm", "run", "start"]
|
||||||
@ -1,179 +0,0 @@
|
|||||||
body {
|
|
||||||
margin: 0%;
|
|
||||||
background-color: rgb(47, 47, 47);
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
text-align: center;
|
|
||||||
position: absolute;
|
|
||||||
bottom: 0;
|
|
||||||
width: 100%;
|
|
||||||
background-color: rgb(0, 0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* #footer {
|
|
||||||
position:absolute;
|
|
||||||
bottom:0; /* on le colle en bas */
|
|
||||||
/* width:100%;
|
|
||||||
height:100px; */
|
|
||||||
|
|
||||||
|
|
||||||
.pp {
|
|
||||||
height: 10vh;
|
|
||||||
width: 10vh;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loginHere{
|
|
||||||
/* justify-content: center; */
|
|
||||||
font-size: 5vh;
|
|
||||||
font-family: 'Rubik Iso';
|
|
||||||
text-align: center;
|
|
||||||
margin-top: 10vh;
|
|
||||||
/* border: 5px solid rgb(255, 255, 255); */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
::placeholder {
|
|
||||||
font-size: 3vh;
|
|
||||||
text-align: center;
|
|
||||||
align-items: center;
|
|
||||||
margin:auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submit{
|
|
||||||
height: 5vh;
|
|
||||||
border-radius: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.submit:hover {
|
|
||||||
background-color: blueviolet;
|
|
||||||
}
|
|
||||||
|
|
||||||
input{
|
|
||||||
height: 5vh;
|
|
||||||
border-radius: 100vh;
|
|
||||||
}
|
|
||||||
|
|
||||||
.pp:hover {
|
|
||||||
border: 5px solid rgb(255, 255, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
.userTxt:hover {
|
|
||||||
color:blueviolet;;
|
|
||||||
}
|
|
||||||
|
|
||||||
.userTxt {
|
|
||||||
margin-right: 5%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.username {
|
|
||||||
display: flex;
|
|
||||||
font-size: 4vh;
|
|
||||||
max-width: 33%;
|
|
||||||
color: aqua;
|
|
||||||
/* text-align: right; */
|
|
||||||
/* width: 10%; */
|
|
||||||
justify-content: right;
|
|
||||||
/* align-self: flex-end; */
|
|
||||||
/* margin-left: auto; */
|
|
||||||
/* text-align: right; */
|
|
||||||
}
|
|
||||||
|
|
||||||
label{
|
|
||||||
/* border: 5px solid rgb(255, 255, 255); */
|
|
||||||
/* width: 15vw; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.login {
|
|
||||||
/* text-align: center; */
|
|
||||||
/* justify-content: center; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.loginForm {
|
|
||||||
/* margin-top: 20vh; */
|
|
||||||
align-items: center;
|
|
||||||
height: 50vh;
|
|
||||||
/* text-align: center; */
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
/* border: 5px solid rgb(255, 255, 255); */
|
|
||||||
justify-content: space-around;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* .menu:hover {
|
|
||||||
color:blueviolet;
|
|
||||||
} */
|
|
||||||
|
|
||||||
.menu {
|
|
||||||
color: aqua;
|
|
||||||
font-size: 4vh;
|
|
||||||
/* margin-left: %; */
|
|
||||||
/* padding-left: 2vw; */
|
|
||||||
/* margin-left: 20px; */
|
|
||||||
/* max-width: 33%; */
|
|
||||||
/* margin-right: auto; */
|
|
||||||
/* align-self: flex-start; */
|
|
||||||
/* justify-content: start; */
|
|
||||||
/* text-align: left; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.pong{
|
|
||||||
font-family:'Rubik Iso';
|
|
||||||
}
|
|
||||||
|
|
||||||
.box {
|
|
||||||
/* border: 2px solid white; */
|
|
||||||
width: 33%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.center {
|
|
||||||
/* text-align: center; */
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.headerName {
|
|
||||||
/* margin: auto; */
|
|
||||||
display:flex;
|
|
||||||
max-width: 33%;
|
|
||||||
/* align-items: center; */
|
|
||||||
height: 100%;
|
|
||||||
font-size: 50px;
|
|
||||||
/* text-align: center; */
|
|
||||||
/* align-self: center; */
|
|
||||||
/* margin: auto; */
|
|
||||||
/* border: 2px solid white; */
|
|
||||||
/* height: 100px; */
|
|
||||||
color:blueviolet;
|
|
||||||
/* align-items: center; */
|
|
||||||
/* text-align-last:center; */
|
|
||||||
font-size: 12vh;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header {
|
|
||||||
display: flex;
|
|
||||||
/* border: 2px solid white; */
|
|
||||||
/* border: 5px solid white; */
|
|
||||||
margin: 0;
|
|
||||||
height: 15vh;
|
|
||||||
/* justify-content: space-between; */
|
|
||||||
align-items: center;
|
|
||||||
/* justify-content: center; */
|
|
||||||
/* margin: 0%; */
|
|
||||||
/* padding: 0% ; */
|
|
||||||
/* border: 0cap; */
|
|
||||||
/* width: 100%; */
|
|
||||||
/* margin-top: 0%; */
|
|
||||||
/* padding-top: 0%; */
|
|
||||||
background-color: rgb(0, 0, 0);
|
|
||||||
/* background-attachment: fixed */
|
|
||||||
/* color: white; */
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
color:blueviolet
|
|
||||||
/* background-color: rgb(153, 32, 32) !important; */
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 28 KiB |
@ -1,4 +0,0 @@
|
|||||||
[ZoneTransfer]
|
|
||||||
ZoneId=3
|
|
||||||
ReferrerUrl=https://www.google.com/
|
|
||||||
HostUrl=https://img.ev.mu/images/articles/600x/775102.jpg
|
|
||||||
@ -1,56 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="fr">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<link href="./css/header.css" rel="stylesheet">
|
|
||||||
<title>BEST PONG EVER</title>
|
|
||||||
<script src="./js/login.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="header">
|
|
||||||
<div class="box menu"> <p class="userTxt">Menu</p> </div>
|
|
||||||
<div class="box headerName">
|
|
||||||
<p class="center pong">PONG</p>
|
|
||||||
<!-- <p class="box headerName">PONG</p> -->
|
|
||||||
</div>
|
|
||||||
<div class="box username">
|
|
||||||
<p class="userTxt">UserName</p>
|
|
||||||
<img class="pp center" src="./img/pp.jpg" alt="profile picture">
|
|
||||||
</div>
|
|
||||||
<!-- <h1 class="headerName">PONG</h1> -->
|
|
||||||
<!-- <p class="username">username</p> -->
|
|
||||||
</div>
|
|
||||||
<div class ="login">
|
|
||||||
|
|
||||||
<form id="loginForm" method="post" name="login" action="/api/login" class ="loginForm">
|
|
||||||
<p class="loginHere">Login Here</p>
|
|
||||||
<!-- <input type="text" name="prenom"> -->
|
|
||||||
<!-- <label>Login</label> : -->
|
|
||||||
<input type="text" name="login" placeholder="login">
|
|
||||||
<!-- <label>Password</label> : -->
|
|
||||||
<input type="text" name="password" placeholder="password">
|
|
||||||
<!-- <input class="submit" type="button" value="LOGIN" onclick="login()"> -->
|
|
||||||
<button class="submit" onclick="login()">LOGIN</button>
|
|
||||||
<!-- <script>
|
|
||||||
function login()
|
|
||||||
{
|
|
||||||
alert("Le bouton a été cliqué !");
|
|
||||||
var formulaire = document.getElementById("loginForm");
|
|
||||||
formulaire.submit();
|
|
||||||
}
|
|
||||||
</script> -->
|
|
||||||
|
|
||||||
<!-- <p>Texte à l'intérieur du formulaire</p> -->
|
|
||||||
</form>
|
|
||||||
<!-- <p>Texte après le formulaire</p>-->
|
|
||||||
</div>
|
|
||||||
<!-- <p>Je suis content de vous accuawdawdeillir sur ma première page web.</p> -->
|
|
||||||
<footer>
|
|
||||||
<p>@apommier | apommier@student.42.fr</p>
|
|
||||||
</footer>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Rubik+Iso&display=swap" rel="stylesheet">
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
function login()
|
|
||||||
{
|
|
||||||
alert("Le bouton a été cliqué !");
|
|
||||||
var formulaire = document.getElementById("loginForm");
|
|
||||||
formulaire.submit();
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
import './Style/App.css';
|
|
||||||
import Header from './components/Header';
|
|
||||||
import {BrowserRouter as Router, Routes, Route} from 'react-router-dom';
|
|
||||||
import Home from './pages/Home';
|
|
||||||
import Game from './pages/Game';
|
|
||||||
import Footer from './components/Footer';
|
|
||||||
import Messages from './pages/Messages';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<Router>
|
|
||||||
<Header/>
|
|
||||||
<div>
|
|
||||||
<Routes>
|
|
||||||
<Route path="/" exact element={<Home/>}/>
|
|
||||||
<Route path="/products" element={<Game/>}/>
|
|
||||||
<Route path="/messages" element={<Messages/>}/>
|
|
||||||
</Routes>
|
|
||||||
</div>
|
|
||||||
</Router>
|
|
||||||
<Footer/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
import { render, screen } from '@testing-library/react';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
test('renders learn react link', () => {
|
|
||||||
render(<App />);
|
|
||||||
const linkElement = screen.getByText(/learn react/i);
|
|
||||||
expect(linkElement).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
@ -1,10 +0,0 @@
|
|||||||
import DefaultPic from '../assets/profile.jpg';
|
|
||||||
|
|
||||||
const UserProfile = [
|
|
||||||
{
|
|
||||||
Pic: DefaultPic,
|
|
||||||
UserName: "Dipper Ratman",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
|
|
||||||
export default UserProfile
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
export const DBWinLoss = [
|
|
||||||
{
|
|
||||||
title: 'Victory',
|
|
||||||
score: '10 - 6',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Defeat',
|
|
||||||
score: '9 - 10',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Victory',
|
|
||||||
score: '10 - 0',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Victory',
|
|
||||||
score: '10 - 9',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Defeat',
|
|
||||||
score: '3 - 10',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Deafet',
|
|
||||||
score: '9 - 10',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Victory',
|
|
||||||
score: '10 - 9',
|
|
||||||
},
|
|
||||||
]
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
.Header {
|
|
||||||
background-color: #060b26;
|
|
||||||
height: 80px;
|
|
||||||
display: flex;
|
|
||||||
/* justify-content: start; */
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-bars {
|
|
||||||
margin-left: 2rem;
|
|
||||||
font-size: 2rem;
|
|
||||||
background: none;
|
|
||||||
color:#f5f5f5
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu{
|
|
||||||
background-color: #060b26;
|
|
||||||
width: 250px;
|
|
||||||
height: 100vh;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: -100%;
|
|
||||||
transition: 850ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu.active {
|
|
||||||
left: 0;
|
|
||||||
transition: 350ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-text {
|
|
||||||
display: flex;
|
|
||||||
/* justify-content: start; */
|
|
||||||
align-items: center;
|
|
||||||
padding: 8px 0px 8px 16px;
|
|
||||||
list-style: none;
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-text a {
|
|
||||||
text-decoration: none;
|
|
||||||
color: #f5f5f5;
|
|
||||||
font-size: 18px;
|
|
||||||
width: 95%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 0 16px;
|
|
||||||
border-radius: 4px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-text a:hover {
|
|
||||||
background-color: #1a83ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-menu-items {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Header-toggle {
|
|
||||||
background-color: #060b26;
|
|
||||||
width: 100%;
|
|
||||||
height: 80px;
|
|
||||||
display: flex;
|
|
||||||
/* justify-content: start; */
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
span {
|
|
||||||
margin-left: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.Header-pic {
|
|
||||||
height: 50px;
|
|
||||||
width: 50px;
|
|
||||||
border-radius: 50%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-pic{
|
|
||||||
text-align: end;
|
|
||||||
/* id: right; */
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
height: 0.1px;
|
|
||||||
color: #060b26;
|
|
||||||
}
|
|
||||||
|
|
||||||
.end{
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
margin-right: 2rem;
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
.profile {
|
|
||||||
flex-direction: row;
|
|
||||||
}
|
|
||||||
|
|
||||||
.profile-pic {
|
|
||||||
height: 250px;
|
|
||||||
width: 250px;
|
|
||||||
border-radius: 50%;
|
|
||||||
border-image-width: thick;
|
|
||||||
border-color: black;
|
|
||||||
margin-top: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
canvas {
|
|
||||||
margin-top: 20px;
|
|
||||||
border: solid 0px #ccc;
|
|
||||||
background-color: #000;
|
|
||||||
border-radius: 3%;
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
// import './Header.scss';
|
|
||||||
|
|
||||||
function Footer() {
|
|
||||||
return (
|
|
||||||
<footer className="footer">
|
|
||||||
<p>© 2023 Paris France</p>
|
|
||||||
</footer>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Footer;
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
import React, {useState} from 'react';
|
|
||||||
import {AiOutlineMenuUnfold} from 'react-icons/ai';
|
|
||||||
import * as AiIcons from 'react-icons/ai';
|
|
||||||
import {Link} from 'react-router-dom';
|
|
||||||
import { SidebarData } from './SidebarData';
|
|
||||||
import DefaultPicture from '../assets/profile.jpg'
|
|
||||||
// import {BiLogOutCircle} from 'react-icons/bi';
|
|
||||||
import '../Style/Header.css';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function Header() {
|
|
||||||
const [sidebar, setSidebar] = useState(false);
|
|
||||||
const showSidebar = () => setSidebar(!sidebar);
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<div className='Header'>
|
|
||||||
<Link to="#" className='menu-bars'>
|
|
||||||
<AiOutlineMenuUnfold onClick={showSidebar}/>
|
|
||||||
</Link>
|
|
||||||
<div className='end'>
|
|
||||||
<Link to="/" className='menu-bars'>
|
|
||||||
<img className='Header-pic' src={DefaultPicture} alt='profile'/>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<nav className={sidebar ? 'nav-menu active' : 'nav-menu'}>
|
|
||||||
<ul className='nav-menu-items' onClick={showSidebar}>
|
|
||||||
<li className='Header-toggle'>
|
|
||||||
<Link to="#" className='menu-bars'>
|
|
||||||
<AiIcons.AiOutlineClose />
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
{SidebarData.map((item, index) => {
|
|
||||||
return (
|
|
||||||
<li key={index} className={item.cName}>
|
|
||||||
<Link to={item.path}>
|
|
||||||
{item.icon}
|
|
||||||
<span>{item.title}</span>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Header
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import * as FaIcons from 'react-icons/fa';
|
|
||||||
import * as AiIcons from 'react-icons/ai';
|
|
||||||
import * as IoIcons from 'react-icons/io';
|
|
||||||
import {BiLogOutCircle} from 'react-icons/bi';
|
|
||||||
import {IoSettingsSharp} from 'react-icons/io5'
|
|
||||||
|
|
||||||
|
|
||||||
export const SidebarData = [
|
|
||||||
{
|
|
||||||
title: 'Dipper Ratman',
|
|
||||||
path: '/',
|
|
||||||
icon: <AiIcons.AiFillHome />,
|
|
||||||
cName: 'nav-text'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Game',
|
|
||||||
path: '/products',
|
|
||||||
icon: <FaIcons.FaGamepad/>,
|
|
||||||
cName: 'nav-text'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Messages',
|
|
||||||
path: '/messages',
|
|
||||||
icon: <FaIcons.FaEnvelopeOpenText/>,
|
|
||||||
cName: 'nav-text'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Social',
|
|
||||||
path: '/team',
|
|
||||||
icon: <IoIcons.IoMdPeople />,
|
|
||||||
cName: 'nav-text'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Settings',
|
|
||||||
path: '/team',
|
|
||||||
icon: <IoSettingsSharp />,
|
|
||||||
cName: 'nav-text'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: 'Log out',
|
|
||||||
path: '/team',
|
|
||||||
icon: <BiLogOutCircle />,
|
|
||||||
cName: 'nav-text'
|
|
||||||
},
|
|
||||||
]
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
// import PropTypes from "prop-types"
|
|
||||||
import styled from 'styled-components';
|
|
||||||
import '../DataBase/DummyDBWinLoss.js'
|
|
||||||
import { DBWinLoss } from '../DataBase/DummyDBWinLoss.js';
|
|
||||||
// import color from '../../utils/style/color.js';
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const CardWrapper = styled.div`
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
padding: 15px;
|
|
||||||
background-color: black;
|
|
||||||
// border-radius: 30px;
|
|
||||||
// width: 350px;
|
|
||||||
// transition: 200ms;
|
|
||||||
margin-top: 50px;
|
|
||||||
&:hover {
|
|
||||||
cursor: pointer;
|
|
||||||
box-shadow: 2px 2px 10px #b6b6b6;
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const CardLabel1 = styled.span`
|
|
||||||
color: #5843e4;
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: bold;
|
|
||||||
margin-bottom: 25px;
|
|
||||||
`
|
|
||||||
const CardLabel2 = styled.span`
|
|
||||||
color: #5843e4;
|
|
||||||
font-size: 22px;
|
|
||||||
font-weight: bold;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
`
|
|
||||||
|
|
||||||
// const CardImage = styled.img`
|
|
||||||
// heigh: 80px;
|
|
||||||
// width: 80px;
|
|
||||||
// border-radius: 50%;
|
|
||||||
// `
|
|
||||||
|
|
||||||
function WinLoss() {
|
|
||||||
return (
|
|
||||||
<CardWrapper>
|
|
||||||
<CardLabel1>Match history Win/Loss</CardLabel1>
|
|
||||||
{/* <CardImage src={picture} alt="freelance" height={80} width={80} /> */}
|
|
||||||
{DBWinLoss.map((item, index) => {
|
|
||||||
return (
|
|
||||||
<li key={index}>
|
|
||||||
<CardLabel2>{item.title}</CardLabel2>
|
|
||||||
<CardLabel2>{item.score}</CardLabel2>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</CardWrapper>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Card.propTypes = {
|
|
||||||
// label: PropTypes.string,
|
|
||||||
// title: PropTypes.string.isRequired,
|
|
||||||
// picture: PropTypes.string,
|
|
||||||
// }
|
|
||||||
|
|
||||||
export default WinLoss
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import ReactDOM from 'react-dom/client';
|
|
||||||
import './Style/index.css';
|
|
||||||
import App from './App';
|
|
||||||
|
|
||||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
|
||||||
root.render(
|
|
||||||
<React.StrictMode>
|
|
||||||
<div>
|
|
||||||
<App />
|
|
||||||
</div>
|
|
||||||
</React.StrictMode>
|
|
||||||
);
|
|
||||||
|
|
||||||
// If you want to start measuring performance in your app, pass a function
|
|
||||||
// to log results (for example: reportWebVitals(console.log))
|
|
||||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
|
||||||
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
|
|
||||||
function Game (){
|
|
||||||
return (
|
|
||||||
<div className=''>
|
|
||||||
<h1>Launching Game</h1>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Game
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
import '../Style/Profile.css'
|
|
||||||
import '../Style/App.css'
|
|
||||||
import DefaultPicture from "../assets/profile.jpg";
|
|
||||||
import WinLoss from "../components/Win_Loss";
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function Home () {
|
|
||||||
return (
|
|
||||||
<div className="App">
|
|
||||||
<div className="profile">
|
|
||||||
<img className="profile-pic" src={DefaultPicture} alt="Profile pic" />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="profile">
|
|
||||||
{/* <canvas id="canvas" height="610" width="500">
|
|
||||||
<h1 font-color="white"> Welcome to the Home Page!</h1>
|
|
||||||
</canvas> */}
|
|
||||||
<WinLoss/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Home
|
|
||||||
@ -1,22 +1,24 @@
|
|||||||
{
|
{
|
||||||
"name": "the_last",
|
"name": "my-app",
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@testing-library/jest-dom": "^5.16.5",
|
"@testing-library/jest-dom": "^5.16.5",
|
||||||
"@testing-library/react": "^13.4.0",
|
"@testing-library/react": "^13.4.0",
|
||||||
"@testing-library/user-event": "^13.5.0",
|
"@testing-library/user-event": "^13.5.0",
|
||||||
|
"axios": "^1.3.5",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-icons": "^4.8.0",
|
"react-icons": "^4.8.0",
|
||||||
"react-router-dom": "^6.10.0",
|
"react-router-dom": "^6.10.0",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
"socket.io-client": "^4.6.1",
|
"socket.io-client": "^4.6.1",
|
||||||
"styled-components": "^5.3.9",
|
"styled-components": "^5.3.10",
|
||||||
"web-vitals": "^2.1.4"
|
"web-vitals": "^2.1.4"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "react-scripts start",
|
"start": "HOST=0.0.0.0 PORT=8080 react-scripts start",
|
||||||
|
"start:dev": "npm run start --watch",
|
||||||
"build": "react-scripts build",
|
"build": "react-scripts build",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"eject": "react-scripts eject"
|
"eject": "react-scripts eject"
|
||||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
|
Before Width: | Height: | Size: 9.4 KiB After Width: | Height: | Size: 9.4 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
25
frontend/src/components/App.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import logo from '../logo.svg';
|
||||||
|
import '../styles/App.css';
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div className="App">
|
||||||
|
<header className="App-header">
|
||||||
|
<img src={logo} className="App-logo" alt="logo" />
|
||||||
|
<p>
|
||||||
|
Edit <code>src/App.js</code> and save to reload.
|
||||||
|
</p>
|
||||||
|
<a
|
||||||
|
className="App-link"
|
||||||
|
href="https://reactjs.org"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
|
Learn React
|
||||||
|
</a>
|
||||||
|
</header>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
20
frontend/src/components/Chat.js
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
||||||
|
import Home from './components/Home';
|
||||||
|
import ChatPage from './components/ChatPage';
|
||||||
|
import socketIO from 'socket.io-client';
|
||||||
|
|
||||||
|
const socket = socketIO.connect('http://localhost:4000');
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<BrowserRouter>
|
||||||
|
<div>
|
||||||
|
<Routes>
|
||||||
|
<Route path="/" element={<Home socket={socket} />}></Route>
|
||||||
|
<Route path="/chat" element={<ChatPage socket={socket} />}></Route>
|
||||||
|
</Routes>
|
||||||
|
</div>
|
||||||
|
</BrowserRouter>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
72
frontend/src/components/Field.js
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useState, useRef } from 'react';
|
||||||
|
import { drawCanvas } from './canvas.js';
|
||||||
|
import '../styles/field.css';
|
||||||
|
|
||||||
|
function Field()
|
||||||
|
{
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("launch canva hehe")
|
||||||
|
drawCanvas();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
|
||||||
|
// 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);
|
||||||
12
frontend/src/components/Footer.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import '../styles/old.css';
|
||||||
|
|
||||||
|
function Footer()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<footer>
|
||||||
|
<p>@apommier | apommier@student.42.fr</p>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Footer;
|
||||||
16
frontend/src/components/Head.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
function Head()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<meta charSet="utf-8"></meta>
|
||||||
|
<link href="./css/header.css" rel="stylesheet"></link>
|
||||||
|
<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 href="https://fonts.googleapis.com/css2?family=Rubik+Iso&display=swap" rel="stylesheet"></link>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Head;
|
||||||
23
frontend/src/components/Header.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import '../styles/App.css';
|
||||||
|
import '../styles/old.css';
|
||||||
|
import logo from '../logo.svg';
|
||||||
|
|
||||||
|
function Header()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<div className="header">
|
||||||
|
<a href="http://localhost" className="box menu"> <p className="userTxt">Menu</p> </a>
|
||||||
|
<div className="box headerName">
|
||||||
|
<a href="https://api.intra.42.fr/oauth/authorize?client_id=u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41&redirect_uri=http%3A%2F%2Flocalhost%3A8080%2Flogin42&response_type=code"
|
||||||
|
className="center pong">PONG</a>
|
||||||
|
</div>
|
||||||
|
<a href="http://localhost/pong" className="box username">
|
||||||
|
<p className="userTxt">Play</p>
|
||||||
|
{/* <img className="pp center" src="../../public/logo192.png" alt="profile picture"> */}
|
||||||
|
<img src={logo} className="pp center" alt="logo" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Header;
|
||||||
19
frontend/src/components/Home.js
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import '../styles/old.css';
|
||||||
|
import { login } from '../script/login.js'
|
||||||
|
|
||||||
|
function Home()
|
||||||
|
{
|
||||||
|
return (
|
||||||
|
<div className ="login">
|
||||||
|
<form id="loginForm" method="post" name="login" action="http://localhost/api/login" className ="loginForm">
|
||||||
|
<p className="loginHere">Login Here</p>
|
||||||
|
<input type="text" name="nickname" placeholder="login"></input>
|
||||||
|
<input type="text" name="password" placeholder="password"></input>
|
||||||
|
<button className="submit" onClick={login}>LOGIN</button>
|
||||||
|
</form>
|
||||||
|
{/* <button></button> */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Home;
|
||||||
43
frontend/src/components/Login42.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
// import GoogleLogin from 'react-google-login';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import axios from 'axios';
|
||||||
|
// import setupLogin from '../script/login42';
|
||||||
|
// import React, { useEffect } from 'react';
|
||||||
|
|
||||||
|
function Login42()
|
||||||
|
{
|
||||||
|
useEffect(() => {
|
||||||
|
console.log("you said yes to connect with 42");
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
// console.log(`url is= ${url}`);
|
||||||
|
const code = url.searchParams.get('code');
|
||||||
|
console.log(`code is= ${code}`);
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
grant_type: 'authorization_code',
|
||||||
|
client_id: 'u-s4t2ud-6d29dfa49ba7146577ffd8bf595ae8d9e5aaa3e0a9615df18777171ebf836a41',
|
||||||
|
client_secret: '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',
|
||||||
|
code: code,
|
||||||
|
redirect_uri: 'http://localhost:8080/login42',
|
||||||
|
};
|
||||||
|
|
||||||
|
axios.post('https://api.intra.42.fr/oauth/token', data)
|
||||||
|
.then(response => {
|
||||||
|
// handle success response
|
||||||
|
console.log(response);
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
// handle error response
|
||||||
|
console.error(error);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>"COUCOU LOGIN$@ jeje" </p>
|
||||||
|
{/* <script src="../script/login42.js"></script> */}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Login42;
|
||||||
@ -1,7 +1,7 @@
|
|||||||
import React, { useEffect, useRef, useState } from "react";
|
import React, { useEffect, useRef, useState } from "react";
|
||||||
import Sidebar from '../components/Messages/Sidebar'
|
import Sidebar from '../components/Messages/Sidebar'
|
||||||
import Chat from "../components/Messages/Chat"
|
import Chat from "../components/Messages/Chat"
|
||||||
import '../Style/Messages.css'
|
import '../styles/Messages.css'
|
||||||
import {io} from 'socket.io-client'
|
import {io} from 'socket.io-client'
|
||||||
|
|
||||||
function Messages(params) {
|
function Messages(params) {
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import React from "react"
|
import React from "react"
|
||||||
import styled from "styled-components"
|
import styled from "styled-components"
|
||||||
import '../../Style/Messages.css'
|
import '../../styles/Messages.css'
|
||||||
import DefaultPic from '../../assets/profile.jpg';
|
import DefaultPic from '../../assets/profile.jpg';
|
||||||
import { ImBlocked } from 'react-icons/im';
|
import { ImBlocked } from 'react-icons/im';
|
||||||
import { MdOutlineGroupAdd } from 'react-icons/md';
|
import { MdOutlineGroupAdd } from 'react-icons/md';
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import '../../Style/Messages.css'
|
import '../../styles/Messages.css'
|
||||||
import styled from "styled-components";
|
import styled from "styled-components";
|
||||||
import DefaultPic from '../../assets/profile.jpg'
|
import DefaultPic from '../../assets/profile.jpg'
|
||||||
|
|
||||||
@ -2,7 +2,7 @@ import MessageYou from "./MessageYou"
|
|||||||
import MessageMe from "./MessageMe"
|
import MessageMe from "./MessageMe"
|
||||||
// import { useRef } from "react";
|
// import { useRef } from "react";
|
||||||
// import { useEffect } from "react";
|
// import { useEffect } from "react";
|
||||||
import '../../Style/Messages.css'
|
import '../../styles/Messages.css'
|
||||||
|
|
||||||
function Conversation(){
|
function Conversation(){
|
||||||
// const scrollRef = useRef();
|
// const scrollRef = useRef();
|
||||||
@ -1,5 +1,5 @@
|
|||||||
import { TbSend } from 'react-icons/tb';
|
import { TbSend } from 'react-icons/tb';
|
||||||
|
import '../../styles/Messages.css'
|
||||||
|
|
||||||
function Input(){
|
function Input(){
|
||||||
return (
|
return (
|
||||||
@ -3,9 +3,9 @@ import styled from "styled-components"
|
|||||||
import DefaultPic from '../../assets/profile.jpg'
|
import DefaultPic from '../../assets/profile.jpg'
|
||||||
import { useRef } from "react";
|
import { useRef } from "react";
|
||||||
import { useEffect } from "react";
|
import { useEffect } from "react";
|
||||||
import '../../Style/Messages.css'
|
import '../../styles/Messages.css'
|
||||||
|
|
||||||
const MeStyleP = styled.p`
|
const MestylesP = styled.p`
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
padding 10px 20px;
|
padding 10px 20px;
|
||||||
border-radius 10px 0px 10px 10px;
|
border-radius 10px 0px 10px 10px;
|
||||||
@ -25,7 +25,7 @@ function MessageMe(){
|
|||||||
<img className="messageInfo" src={DefaultPic} alt="profile" />
|
<img className="messageInfo" src={DefaultPic} alt="profile" />
|
||||||
</div>
|
</div>
|
||||||
<div className="messageContent">
|
<div className="messageContent">
|
||||||
<MeStyleP>bonjours ca va</MeStyleP>
|
<MestylesP>bonjours ca va</MestylesP>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -3,9 +3,9 @@ import styled from "styled-components"
|
|||||||
import DefaultPic from '../../assets/profile.jpg'
|
import DefaultPic from '../../assets/profile.jpg'
|
||||||
import { useRef } from "react"
|
import { useRef } from "react"
|
||||||
import { useEffect } from "react"
|
import { useEffect } from "react"
|
||||||
import '../../Style/Messages.css'
|
import '../../styles/Messages.css'
|
||||||
|
|
||||||
const StyleP = styled.p`
|
const StylesP = styled.p`
|
||||||
background-color: white;
|
background-color: white;
|
||||||
padding 10px 20px;
|
padding 10px 20px;
|
||||||
border-radius 0px 10px 10px 10px;
|
border-radius 0px 10px 10px 10px;
|
||||||
@ -25,7 +25,7 @@ function MessageYou(){
|
|||||||
<img className="messageInfo" src={DefaultPic} alt="profile" />
|
<img className="messageInfo" src={DefaultPic} alt="profile" />
|
||||||
</div>
|
</div>
|
||||||
<div className="messageContent">
|
<div className="messageContent">
|
||||||
<StyleP>bonjours ca va</StyleP>
|
<StylesP>bonjours ca va</StylesP>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
@ -1,7 +1,7 @@
|
|||||||
// import UserProfile from '../../DataBase/DataProfileUser'
|
// import UserProfile from '../../DataBase/DataProfileUser'
|
||||||
import DefaultPic from '../../assets/profile.jpg';
|
import DefaultPic from '../../assets/profile.jpg';
|
||||||
// import Data from '../../DataBase/DataProfileUser';
|
// import Data from '../../DataBase/DataProfileUser';
|
||||||
import '../../Style/Messages.css'
|
import '../../styles/Messages.css'
|
||||||
|
|
||||||
function Navbar(){
|
function Navbar(){
|
||||||
return (
|
return (
|
||||||
23
frontend/src/components/PlayButton.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
import '../styles/field.css';
|
||||||
|
// import { useHistory } from 'react-router-dom';
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
function PlayButton() {
|
||||||
|
|
||||||
|
const history = useNavigate();
|
||||||
|
|
||||||
|
const handleButtonClick = () => {
|
||||||
|
let path = `play`;
|
||||||
|
history(path);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="notClicked" id="canvas_container">
|
||||||
|
<button onClick={handleButtonClick} className="playButton">Play</button>
|
||||||
|
{/* !buttonClicked && <button onClick={handleButtonClick}>Draw on Canvas</button> */}
|
||||||
|
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PlayButton;
|
||||||
433
frontend/src/components/canvas.js
Normal file
@ -0,0 +1,433 @@
|
|||||||
|
// import io from 'socket.io-client';
|
||||||
|
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import io from 'socket.io-client';
|
||||||
|
// const socket = io('http://192.168.1.14:4000');
|
||||||
|
// const socket = io('http://86.209.110.20:4000');
|
||||||
|
// const socket = io('http://172.29.113.91:4000');
|
||||||
|
|
||||||
|
export function drawCanvas() {
|
||||||
|
const socket = io('http://localhost:4000');
|
||||||
|
// const socket = io()
|
||||||
|
console.log("start function");
|
||||||
|
const canvas = document.getElementById('myCanvas');
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
// Var Declaration
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
|
||||||
|
//socket
|
||||||
|
let myId = 0;
|
||||||
|
let gameId = 0;
|
||||||
|
|
||||||
|
//general canvas
|
||||||
|
const scale = window.devicePixelRatio;
|
||||||
|
canvas.width = canvas.offsetWidth;
|
||||||
|
canvas.height = canvas.offsetHeight;
|
||||||
|
|
||||||
|
//paddle var
|
||||||
|
const paddleWidth = canvas.width * 0.01;
|
||||||
|
let paddleHeight = canvas.height * 0.25;
|
||||||
|
let paddleY = canvas.height / 2 - (paddleHeight / 2);
|
||||||
|
let paddleX = canvas.width / 40;
|
||||||
|
let paddleSpeed = canvas.height / 40;
|
||||||
|
|
||||||
|
//opponent var
|
||||||
|
let oPaddleY = paddleY;
|
||||||
|
|
||||||
|
//mouse and touch
|
||||||
|
let lastMouseY = 0;
|
||||||
|
let lastTouchY = 0;
|
||||||
|
|
||||||
|
//ball var
|
||||||
|
let ballX = canvas.width / 2;
|
||||||
|
let ballY = canvas.height / 2;
|
||||||
|
|
||||||
|
//ball display
|
||||||
|
let ballRadius = canvas.width * 0.01;
|
||||||
|
let circleRadius = ballRadius * 3;
|
||||||
|
ctx.lineWidth = (canvas.width / 300);
|
||||||
|
|
||||||
|
//ball vector
|
||||||
|
let vX = 0;
|
||||||
|
let vY = 0;
|
||||||
|
|
||||||
|
//score
|
||||||
|
let myScore = 0;
|
||||||
|
let hisScore = 0;
|
||||||
|
|
||||||
|
let lastUpdateTime = performance.now();
|
||||||
|
|
||||||
|
let maxAngle = 50;
|
||||||
|
let maxBounceAngle = (maxAngle * Math.PI) / 180;
|
||||||
|
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
// Socket handler
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
|
||||||
|
function matchmaking()
|
||||||
|
{
|
||||||
|
console.log(`id ion matcj= ${myId}`)
|
||||||
|
const info = {
|
||||||
|
id: myId,
|
||||||
|
};
|
||||||
|
socket.emit('pong:matchmaking', info);
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on('pong:gameId', (data) => {
|
||||||
|
gameId = data;
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('connect', () => {
|
||||||
|
console.log('Connected to NestJS server');
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('pong:clientId', (data) => {
|
||||||
|
console.log("receive id")
|
||||||
|
myId = data;
|
||||||
|
console.log(`id is= ${myId}`)
|
||||||
|
});
|
||||||
|
|
||||||
|
socket.on('pong:info', (data) => {
|
||||||
|
oPaddleY = (data.paddleY / data.height) * canvas.height//canvas.height - data.ballY;
|
||||||
|
ballX = canvas.width - (data.ballX * (canvas.width / data.width));//- data.ballX;
|
||||||
|
ballY = ((data.ballY / data.height) * canvas.height)//canvas.height - data.ballY;
|
||||||
|
|
||||||
|
vX = -data.vX;
|
||||||
|
vY = data.vY;
|
||||||
|
});
|
||||||
|
|
||||||
|
function send_info()
|
||||||
|
{
|
||||||
|
if (gameId === 0)
|
||||||
|
return ;
|
||||||
|
const info = {
|
||||||
|
id: myId,
|
||||||
|
width: canvas.width,
|
||||||
|
height: canvas.height,
|
||||||
|
paddleY: paddleY,
|
||||||
|
vX: vX,
|
||||||
|
vY: vY,
|
||||||
|
ballX: ballX,
|
||||||
|
ballY: ballY,
|
||||||
|
gameId: gameId,
|
||||||
|
};
|
||||||
|
socket.emit('pong:message', info);
|
||||||
|
}
|
||||||
|
|
||||||
|
socket.on('pong:paddle', (data) => {
|
||||||
|
console.log("paddle info receive")
|
||||||
|
oPaddleY = (data.paddleY / data.height) * canvas.height
|
||||||
|
});
|
||||||
|
|
||||||
|
function send_point()
|
||||||
|
{
|
||||||
|
if (gameId === 0)
|
||||||
|
return ;
|
||||||
|
console.log("send point");
|
||||||
|
const info = {
|
||||||
|
id: myId,
|
||||||
|
gameId: gameId,
|
||||||
|
point: hisScore,
|
||||||
|
}
|
||||||
|
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 === 0)
|
||||||
|
return ;
|
||||||
|
const info = {
|
||||||
|
id: myId,
|
||||||
|
paddleY: paddleY,
|
||||||
|
// width: canvas.width,
|
||||||
|
height: canvas.height,
|
||||||
|
gameId: gameId,
|
||||||
|
};
|
||||||
|
socket.emit('pong:paddle', info);
|
||||||
|
}
|
||||||
|
|
||||||
|
function send_forced_info()
|
||||||
|
{
|
||||||
|
if (gameId === 0)
|
||||||
|
return ;
|
||||||
|
const info = {
|
||||||
|
gameId: gameId,
|
||||||
|
width: canvas.width,
|
||||||
|
height: canvas.height,
|
||||||
|
id: myId,
|
||||||
|
paddleY: paddleY,
|
||||||
|
vX: vX,
|
||||||
|
vY: vY,
|
||||||
|
ballX: ballX,
|
||||||
|
ballY: ballY,
|
||||||
|
};
|
||||||
|
socket.emit('pong:forced', info);
|
||||||
|
}
|
||||||
|
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
// Drawer
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
|
||||||
|
function drawcenter()
|
||||||
|
{
|
||||||
|
// ctx.restore();
|
||||||
|
ctx.fillStyle = 'white';
|
||||||
|
ctx.fillRect(canvas.width / 2 - ctx.lineWidth / 2, 0, canvas.width / 300, canvas.height);
|
||||||
|
|
||||||
|
ctx.beginPath();
|
||||||
|
// ctx.lineWidth = 5;
|
||||||
|
ctx.arc(canvas.width / 2, canvas.height / 2, circleRadius, 0, 2 * Math.PI);
|
||||||
|
ctx.strokeStyle = 'white'; // couleur de dessin
|
||||||
|
ctx.stroke(); // dessin du contour
|
||||||
|
|
||||||
|
ctx.font = canvas.width * 0.1 + "px Arial";
|
||||||
|
ctx.textAlign = "center";
|
||||||
|
ctx.textBaseline = "middle";
|
||||||
|
ctx.fillText(myScore, canvas.width/4, canvas.height/8);
|
||||||
|
ctx.fillText(hisScore, canvas.width/1.25, canvas.height/8);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawPaddle() {
|
||||||
|
ctx.fillStyle = 'white';
|
||||||
|
ctx.fillRect(paddleX, paddleY, paddleWidth, paddleHeight);
|
||||||
|
ctx.fillRect(canvas.width - paddleX - paddleWidth, oPaddleY, paddleWidth, paddleHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
function drawball()
|
||||||
|
{
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.arc(ballX, ballY, ballRadius, 0, 2 * Math.PI);
|
||||||
|
// ctx.lineWidth = 2;
|
||||||
|
ctx.fillStyle = 'red ';
|
||||||
|
ctx.fill();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
// Loop
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
|
||||||
|
matchmaking();
|
||||||
|
// while (!gameId)
|
||||||
|
// ;
|
||||||
|
|
||||||
|
|
||||||
|
function draw(timestamp)
|
||||||
|
{
|
||||||
|
if (gameId === 0 )
|
||||||
|
{
|
||||||
|
requestAnimationFrame(draw)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const deltaTime = timestamp - lastUpdateTime;
|
||||||
|
lastUpdateTime = timestamp;
|
||||||
|
|
||||||
|
ballX += vX * deltaTime * canvas.width;
|
||||||
|
ballY += vY * deltaTime * canvas.width;
|
||||||
|
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
drawPaddle();
|
||||||
|
drawcenter();
|
||||||
|
drawball();
|
||||||
|
is_collision();
|
||||||
|
is_out();
|
||||||
|
requestAnimationFrame(draw);
|
||||||
|
}
|
||||||
|
requestAnimationFrame(draw);
|
||||||
|
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
// Logical Part
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
|
||||||
|
function updateVector()
|
||||||
|
{
|
||||||
|
const relativeBallY = ballY - (paddleY + paddleHeight / 2);
|
||||||
|
const normalizedRelativeBallY = relativeBallY / (paddleHeight / 2);
|
||||||
|
const bounceAngle = normalizedRelativeBallY * maxBounceAngle;
|
||||||
|
|
||||||
|
vY = vX * Math.sin(-bounceAngle);
|
||||||
|
if (vX < 0)
|
||||||
|
vX = -vX;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function updatePaddlePosition(newY)
|
||||||
|
{
|
||||||
|
if (newY >= 0 && newY <= canvas.height - paddleHeight)
|
||||||
|
paddleY = newY;
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_collision()
|
||||||
|
{
|
||||||
|
if (ballX <= paddleX + paddleWidth + ballRadius)
|
||||||
|
{
|
||||||
|
if (ballY <= paddleY + paddleHeight + ballRadius && ballY >= paddleY - ballRadius)//touch paddle
|
||||||
|
{
|
||||||
|
if (ballX + ballRadius > paddleX && ballX - ballRadius < paddleX + paddleWidth)
|
||||||
|
{
|
||||||
|
console.log("hehe here")
|
||||||
|
ballX = paddleX + paddleWidth + ballRadius;
|
||||||
|
}
|
||||||
|
updateVector();
|
||||||
|
}
|
||||||
|
send_info();
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
if (ballY - ballRadius - 2 <= 0 || ballY + ballRadius + 2 >= canvas.height) //touch up or down wall
|
||||||
|
{
|
||||||
|
vY = -vY;
|
||||||
|
// send_info();
|
||||||
|
}
|
||||||
|
else if (ballX + ballRadius + 2 >= canvas.width) //touch right wall
|
||||||
|
{
|
||||||
|
vX = -vX;
|
||||||
|
// send_info();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function is_out()
|
||||||
|
{
|
||||||
|
if (ballX < 0)
|
||||||
|
{
|
||||||
|
if (ballY <= paddleY + paddleHeight + ballRadius && ballY >= paddleY - ballRadius)
|
||||||
|
{
|
||||||
|
console.log('true hehe');
|
||||||
|
ballX = paddleX + paddleWidth + ballRadius;
|
||||||
|
updateVector();
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
ballX = canvas.width / 2;
|
||||||
|
ballY = canvas.height / 2;
|
||||||
|
vX = 0;
|
||||||
|
vY = 0;
|
||||||
|
hisScore += 1;
|
||||||
|
send_point();
|
||||||
|
// send_forced_info();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
// Listener
|
||||||
|
//========================================================================================================
|
||||||
|
//========================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', event => {
|
||||||
|
const mouseY = event.clientY;
|
||||||
|
|
||||||
|
if (!lastMouseY)
|
||||||
|
{
|
||||||
|
lastMouseY = mouseY;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const newY = mouseY > lastMouseY ? paddleY - (lastMouseY - mouseY) : paddleY + (mouseY - lastMouseY);
|
||||||
|
updatePaddlePosition(newY);
|
||||||
|
lastMouseY = mouseY;
|
||||||
|
send_paddle_info();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("touchmove", event => {
|
||||||
|
const touchY = event.touches[0].pageY;
|
||||||
|
|
||||||
|
// if (!lastTouchY)
|
||||||
|
// {
|
||||||
|
// vX = -0.01;
|
||||||
|
// lastTouchY = touchY;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
const newY = touchY > lastTouchY ? paddleY - (lastTouchY - touchY) : paddleY + (touchY - lastTouchY);
|
||||||
|
updatePaddlePosition(newY);
|
||||||
|
lastTouchY = touchY;
|
||||||
|
send_paddle_info();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.addEventListener("keydown", event => {
|
||||||
|
// console.log(event.code);
|
||||||
|
if (event.code === "ArrowUp")
|
||||||
|
{
|
||||||
|
if ((paddleY - paddleSpeed) > 0)
|
||||||
|
paddleY -= paddleSpeed; // déplacer la raquette vers le haut
|
||||||
|
send_paddle_info();
|
||||||
|
}
|
||||||
|
else if (event.code === "ArrowDown")
|
||||||
|
{
|
||||||
|
if (paddleY + paddleSpeed < canvas.height - paddleHeight)
|
||||||
|
paddleY += paddleSpeed; // déplacer la raquette vers le bas
|
||||||
|
send_paddle_info();
|
||||||
|
}
|
||||||
|
else if (event.code === "Space")//space
|
||||||
|
{
|
||||||
|
console.log('vx change to -1');
|
||||||
|
vX = -0.0001;
|
||||||
|
|
||||||
|
// ballSpeed = 0.0001;
|
||||||
|
vY = 0;
|
||||||
|
send_forced_info();
|
||||||
|
// vX = 0.0001;
|
||||||
|
}
|
||||||
|
else if (event.code === "KeyE")
|
||||||
|
{
|
||||||
|
// console.log('vx change to -1');
|
||||||
|
vX = 0;
|
||||||
|
vY = 0;
|
||||||
|
ballX = canvas.width / 2;
|
||||||
|
ballY = canvas.height / 2;
|
||||||
|
send_forced_info();
|
||||||
|
}
|
||||||
|
else if (event.code === "KeyQ" )
|
||||||
|
{
|
||||||
|
if (vX < 0.003 * canvas.width && vX > -0.003 * canvas.width)
|
||||||
|
{
|
||||||
|
if (vX > 0)
|
||||||
|
vX += 0.0001;
|
||||||
|
else
|
||||||
|
vX -= 0.0001;
|
||||||
|
}
|
||||||
|
send_forced_info();
|
||||||
|
// console.log(`vx = ${vX}`);
|
||||||
|
}
|
||||||
|
else if (event.code === "KeyR")
|
||||||
|
{
|
||||||
|
paddleY = 0;
|
||||||
|
paddleHeight = canvas.height;
|
||||||
|
setTimeout(() => {
|
||||||
|
// code à exécuter après 5 secondes
|
||||||
|
paddleHeight = canvas.height * 0.25;
|
||||||
|
paddleY = canvas.height / 2 - paddleHeight / 2;
|
||||||
|
console.log('Cinq secondes se sont écoulées.');
|
||||||
|
}, 5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
36
frontend/src/index.js
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
|
||||||
|
import './styles/index.css';
|
||||||
|
import App from './components/App';
|
||||||
|
import Header from './components/Header';
|
||||||
|
import Home from './components/Home';
|
||||||
|
import Login42 from './components/Login42';
|
||||||
|
import Head from './components/Head';
|
||||||
|
import Field from './components/Field';
|
||||||
|
import PlayButton from './components/PlayButton';
|
||||||
|
import reportWebVitals from './reportWebVitals';
|
||||||
|
import Messages from './components/Messages';
|
||||||
|
import { BrowserRouter, Route, Routes} from 'react-router-dom'
|
||||||
|
|
||||||
|
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||||
|
root.render(
|
||||||
|
<>
|
||||||
|
<Head />
|
||||||
|
<Header />
|
||||||
|
<BrowserRouter>
|
||||||
|
<Routes>
|
||||||
|
<Route exact path="/" element={<Home/>}/>
|
||||||
|
<Route exact path="/pong" element={<PlayButton />}/>
|
||||||
|
<Route exact path="/pong/play" element={<Field />}/>
|
||||||
|
<Route exact path="/login42" element={<Login42 />}/>
|
||||||
|
<Route exact path="/messages" element={<Messages />}/>
|
||||||
|
</Routes>
|
||||||
|
</BrowserRouter>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
|
||||||
|
// If you want to start measuring performance in your app, pass a function
|
||||||
|
// to log results (for example: reportWebVitals(console.log))
|
||||||
|
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||||
|
reportWebVitals();
|
||||||
1
frontend/src/logo.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>
|
||||||
|
After Width: | Height: | Size: 2.6 KiB |
13
frontend/src/reportWebVitals.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
const reportWebVitals = onPerfEntry => {
|
||||||
|
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||||
|
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||||
|
getCLS(onPerfEntry);
|
||||||
|
getFID(onPerfEntry);
|
||||||
|
getFCP(onPerfEntry);
|
||||||
|
getLCP(onPerfEntry);
|
||||||
|
getTTFB(onPerfEntry);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default reportWebVitals;
|
||||||
13
frontend/src/script/login.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
// export const login()
|
||||||
|
// {
|
||||||
|
// alert("Le bouton a été cliqué !");
|
||||||
|
// var formulaire = document.getElementById("loginForm");
|
||||||
|
// formulaire.submit();
|
||||||
|
// }
|
||||||
|
|
||||||
|
export const login = () => {
|
||||||
|
console.log('Hello from myFunction');
|
||||||
|
// alert("Le bouton a été cliqué !");
|
||||||
|
var formulaire = document.getElementById("loginForm");
|
||||||
|
formulaire.submit();
|
||||||
|
}
|
||||||