diff --git a/srcs/.env b/srcs/.env index a8fbadb8..33b89fe8 100644 --- a/srcs/.env +++ b/srcs/.env @@ -1,4 +1,5 @@ NODE_ENV=development +WEBSITE_HOST=transcendance POSTGRES_USER=postgres POSTGRES_PASSWORD=9pKpKEgiamxwk5P7Ggsz POSTGRES_DB=transcendance_db diff --git a/srcs/requirements/nestjs/api_back/src/app.module.ts b/srcs/requirements/nestjs/api_back/src/app.module.ts index e3d193c6..63fa879c 100644 --- a/srcs/requirements/nestjs/api_back/src/app.module.ts +++ b/srcs/requirements/nestjs/api_back/src/app.module.ts @@ -14,6 +14,7 @@ import { GameModule } from './game/game.module'; AuthenticationModule, PassportModule.register({ session: true }), FriendshipsModule, + GameModule, ConfigModule.forRoot(), TypeOrmModule.forRoot({ type: 'postgres', @@ -27,7 +28,6 @@ import { GameModule } from './game/game.module'; //avec une classe pour le module synchronize: true, }), - GameModule, ], controllers: [AppController], providers: [AppService], diff --git a/srcs/requirements/nestjs/api_back/src/game/dto/grantTicket.dto.ts b/srcs/requirements/nestjs/api_back/src/game/dto/grantTicket.dto.ts index 21ae8c3b..c010fc11 100644 --- a/srcs/requirements/nestjs/api_back/src/game/dto/grantTicket.dto.ts +++ b/srcs/requirements/nestjs/api_back/src/game/dto/grantTicket.dto.ts @@ -1,11 +1,12 @@ -import { IsBoolean, IsInt, IsNotEmpty, IsNumber, IsString } from "class-validator"; +import { IsBoolean, IsEmpty, IsInt, IsNotEmpty, IsNumber, IsString } from "class-validator"; +import { IsNull } from "typeorm"; export class GrantTicketDto { @IsString() @IsNotEmpty() playerOneUsername : string @IsString() - playerTwousername : string + playerTwoUsername : string @IsNumber() gameOptions : number @IsBoolean() diff --git a/srcs/requirements/nestjs/api_back/src/game/dto/validateTicket.dto.ts b/srcs/requirements/nestjs/api_back/src/game/dto/validateTicket.dto.ts index d1d49f42..8c594dda 100644 --- a/srcs/requirements/nestjs/api_back/src/game/dto/validateTicket.dto.ts +++ b/srcs/requirements/nestjs/api_back/src/game/dto/validateTicket.dto.ts @@ -1,17 +1,15 @@ -import { IsBase64, IsBoolean, IsNotEmpty, IsNumber, IsString } from "class-validator"; +import { IsBase64, IsBoolean, IsEmpty, IsNotEmpty, IsNumber, IsString } from "class-validator"; export class ValidateTicketDto { @IsString() @IsNotEmpty() playerOneUsername : string @IsString() - playerTwousername : string + playerTwoUsername : string @IsNumber() gameOptions : number @IsBoolean() isGameIsWithInvitation : boolean - @IsNumber() - numberOfRegisteredUser : number @IsBase64() @IsNotEmpty() token : string diff --git a/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts b/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts index a35132af..9481b32e 100644 --- a/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts +++ b/srcs/requirements/nestjs/api_back/src/game/entity/tokenGame.entity.ts @@ -8,13 +8,15 @@ export class TokenGame { @Column() playerOneUsername : string @Column({nullable: true}) - playerTwousername : string + playerTwoUsername : string @Column() gameOptions : number @Column() isGameIsWithInvitation : boolean @Column({default: 0, nullable: true}) numberOfRegisteredUser : number + @Column({default : false}) + isSecondUserAcceptedRequest : boolean @Column() token : string } diff --git a/srcs/requirements/nestjs/api_back/src/game/game.controller.ts b/srcs/requirements/nestjs/api_back/src/game/game.controller.ts index a810c31d..4198172b 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.controller.ts @@ -10,8 +10,7 @@ import { GameService } from './game.service'; @Controller('game') export class GameController { - constructor (private readonly gameService : GameService, - private readonly userService : UsersService) { } + constructor (private readonly gameService : GameService) { } @Post('ticket') @UseGuards(AuthenticateGuard) @@ -22,10 +21,20 @@ export class GameController { if (grantTicketDto.playerOneUsername != user.username) return new HttpException('You can\'t request a game for another person.', 403 ) else if (user.status !== "connected") - return new HttpException('You must not be in game...', 403 ) + return new HttpException('You must not be in game...', HttpStatus.FORBIDDEN ) return this.gameService.generateToken(user, grantTicketDto); } + @Get('requested') + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + async requestIfAnotherUserHasRespondToquestForGame(@Req() req, @Body('playerTwoUsername') body) + { + const user : User = req.user; + return this.gameService.requestIfAnotherUserHasRespondToquestForGame(user, body); + } + + //N'est valable que pour le game-serveur. @Post('gameServer/validate') async validateTicket(@Body() validateTicketDto : ValidateTicketDto, @Req() request) @@ -38,12 +47,19 @@ export class GameController { @Post('decline') @UseGuards(AuthenticateGuard) @UseGuards(TwoFactorGuard) - async declineInvitation(@Body() validateTicketDto : ValidateTicketDto, @Req() req) + async declineInvitation(@Body('token') token, @Req() req) { const user : User = req.user; - if (user.username !== validateTicketDto.playerTwousername) - return new HttpException("This cannot be done", HttpStatus.FORBIDDEN); - return this.gameService.declineInvitation(validateTicketDto); + return this.gameService.declineInvitation(user, token); + } + + @Post('accept') + @UseGuards(AuthenticateGuard) + @UseGuards(TwoFactorGuard) + async acceptInvitation(@Body('token') token, @Req() req) + { + const user : User = req.user; + return this.gameService.acceptInvitation(user, token); } @Get('invitations') diff --git a/srcs/requirements/nestjs/api_back/src/game/game.module.ts b/srcs/requirements/nestjs/api_back/src/game/game.module.ts index 42b69b90..e834599f 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.module.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.module.ts @@ -1,14 +1,17 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { Friendship } from 'src/friendship/entities/friendship.entity'; +import { FriendshipService } from 'src/friendship/friendship.service'; import { User } from 'src/users/entities/user.entity'; import { UsersService } from 'src/users/users.service'; +import { Game } from './entity/game.entity'; import { TokenGame } from './entity/tokenGame.entity'; import { GameController } from './game.controller'; import { GameService } from './game.service'; @Module({ - imports: [TypeOrmModule.forFeature([TokenGame, User])], + imports: [TypeOrmModule.forFeature([TokenGame, User, Game, Friendship])], controllers: [GameController], - providers: [GameService, UsersService] + providers: [GameService, UsersService, FriendshipService] }) export class GameModule {} diff --git a/srcs/requirements/nestjs/api_back/src/game/game.service.ts b/srcs/requirements/nestjs/api_back/src/game/game.service.ts index 866b789d..3197ca85 100644 --- a/srcs/requirements/nestjs/api_back/src/game/game.service.ts +++ b/srcs/requirements/nestjs/api_back/src/game/game.service.ts @@ -8,6 +8,7 @@ import { GrantTicketDto } from './dto/grantTicket.dto'; import { Game } from './entity/game.entity'; import { ValidateTicketDto } from './dto/validateTicket.dto'; import { TokenGame } from './entity/tokenGame.entity'; +import { UsersService } from 'src/users/users.service'; @Injectable() export class GameService { @@ -18,6 +19,7 @@ export class GameService { private readonly userRepository : Repository, @InjectRepository(TokenGame) private readonly tokenGameRepository : Repository, + private readonly userService : UsersService ) { } async encryptToken(toEncrypt : string) : Promise { @@ -35,38 +37,28 @@ export class GameService { async generateToken(user : User, grantTicketDto : GrantTicketDto) { - if (grantTicketDto.isGameIsWithInvitation === true) + if (user.status === "In Game") + return new HttpException("You can't play two games", HttpStatus.FORBIDDEN); + else if (grantTicketDto.isGameIsWithInvitation === true) { - let secondUser : User; - (user.username === grantTicketDto.playerOneUsername) ? - secondUser = await this.userRepository.findOneBy({username : grantTicketDto.playerTwousername}) : - secondUser = await this.userRepository.findOneBy({username : grantTicketDto.playerOneUsername}) + const secondUser : Partial = await this.userService.findOneByUsername(user.id.toString(), grantTicketDto.playerTwoUsername) if (!secondUser) return new HttpException("The requested second player does not exist", HttpStatus.NOT_FOUND); const encryptedTextToReturn = await this.encryptToken(user.username + '_' + secondUser.username + '_' + grantTicketDto.gameOptions + '_' + grantTicketDto.isGameIsWithInvitation + '_' + new Date()) - const validateTicketDto : ValidateTicketDto = new ValidateTicketDto(); - validateTicketDto.playerOneUsername = grantTicketDto.playerOneUsername; - validateTicketDto.playerTwousername = grantTicketDto.playerTwousername; - validateTicketDto.numberOfRegisteredUser = 0; - validateTicketDto.isGameIsWithInvitation = grantTicketDto.isGameIsWithInvitation; - validateTicketDto.gameOptions = grantTicketDto.gameOptions; - validateTicketDto.token = encryptedTextToReturn; - const tok = this.tokenGameRepository.create(validateTicketDto); + const tok = this.tokenGameRepository.create(grantTicketDto); + tok.isSecondUserAcceptedRequest = false; + tok.numberOfRegisteredUser = 0; + tok.token = encryptedTextToReturn; this.tokenGameRepository.save(tok); return { token : encryptedTextToReturn }; } else if (grantTicketDto.isGameIsWithInvitation === false) { const encryptedTextToReturn = await this.encryptToken(user.username + '_' + grantTicketDto.gameOptions + '_' + grantTicketDto.isGameIsWithInvitation + '_' + new Date()) - const validateTicketDto : ValidateTicketDto = new ValidateTicketDto(); - validateTicketDto.playerOneUsername = grantTicketDto.playerOneUsername; - validateTicketDto.playerTwousername = ""; - validateTicketDto.numberOfRegisteredUser = 0; - validateTicketDto.isGameIsWithInvitation = grantTicketDto.isGameIsWithInvitation; - validateTicketDto.gameOptions = grantTicketDto.gameOptions; - validateTicketDto.token = encryptedTextToReturn; - const tok = this.tokenGameRepository.create(validateTicketDto); + const tok = this.tokenGameRepository.create(grantTicketDto); + tok.numberOfRegisteredUser = 0; + tok.token = encryptedTextToReturn; this.tokenGameRepository.save(tok); return { token : encryptedTextToReturn }; } @@ -74,51 +66,64 @@ export class GameService { } async validateToken(validateTicketDto : ValidateTicketDto) { - - let tokenGame : TokenGame; if (validateTicketDto.isGameIsWithInvitation === true) { - tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') - .where('tokenGame.playerOneUsername = :playerOneUsername', {playerOneUsername : validateTicketDto.playerOneUsername}) - .andWhere('tokenGame.playerTwousername = :playerTwousername', {playerTwousername : validateTicketDto.playerTwousername}) - .andWhere('tokenGame.gameOption = :gameOption', {gameOption : validateTicketDto.gameOptions}) - .andWhere('tokenGame.isGameIsWithInvitation = :isGameIsWithInvitation', {isGameIsWithInvitation: validateTicketDto.isGameIsWithInvitation}) - .andWhere('tokenGame.token = :token', {token : validateTicketDto.token}) + const tokenGame : TokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') + .where('tokengame.playerOneUsername = :playerOneUsername', {playerOneUsername : validateTicketDto.playerOneUsername}) + .andWhere('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : validateTicketDto.playerTwoUsername}) + .andWhere('tokengame.gameOptions = :gameOption', {gameOption : validateTicketDto.gameOptions}) + .andWhere('tokengame.isGameIsWithInvitation = :isGameIsWithInvitation', {isGameIsWithInvitation: true}) + .andWhere('tokengame.isSecondUserAcceptedRequest = :choice', {choice : true}) + .andWhere('tokengame.token = :token', {token : validateTicketDto.token}) .getOne(); + if (tokenGame) + { + tokenGame.numberOfRegisteredUser++; + if (tokenGame.numberOfRegisteredUser === 2) + { + this.tokenGameRepository.remove(tokenGame) + const userOne : User = await this.userRepository.createQueryBuilder('user') + .where("user.username = :username", {username : tokenGame.playerOneUsername}) + .getOne(); + userOne.status = "In Game"; + this.userRepository.save(userOne); + const userTwo : User = await this.userRepository.createQueryBuilder('user') + .where("user.username = :username", {username : tokenGame.playerTwoUsername}) + .getOne(); + userTwo.status = "In Game"; + this.userRepository.save(userTwo); + } + return true; + } } - else + else if (validateTicketDto.isGameIsWithInvitation === false) { - tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') - .where('tokenGame.playerOneUsername = :playerOneUsername', {playerOneUsername : validateTicketDto.playerOneUsername}) - .andWhere('tokenGame.gameOption = :gameOption', {gameOption : validateTicketDto.gameOptions}) - .andWhere('tokenGame.isGameIsWithInvitation = :isGameIsWithInvitation', {isGameIsWithInvitation: validateTicketDto.isGameIsWithInvitation}) - .andWhere('tokenGame.token = :token', {token : validateTicketDto.token}) + const tokenGame : TokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') + .where('tokengame.playerOneUsername = :playerOneUsername', {playerOneUsername : validateTicketDto.playerOneUsername}) + .andWhere('tokengame.gameOptions = :gameOption', {gameOption : validateTicketDto.gameOptions}) + .andWhere('tokengame.isGameIsWithInvitation = :isGameIsWithInvitation', {isGameIsWithInvitation: false}) + .andWhere('tokengame.token = :token', {token : validateTicketDto.token}) .getOne(); - } - if (tokenGame) - tokenGame.numberOfRegisteredUser++; - if (tokenGame && tokenGame.isGameIsWithInvitation === false) - { - this.tokenGameRepository.remove(tokenGame) - this.userRepository.update(tokenGame.playerOneUsername, {status : "In Game"}) - return true; - } - else if (tokenGame && tokenGame.isGameIsWithInvitation === true) - { - if (tokenGame.numberOfRegisteredUser === 2) + if (tokenGame) { this.tokenGameRepository.remove(tokenGame) - this.userRepository.update(tokenGame.playerOneUsername, {status : "In Game"}) - this.userRepository.update(tokenGame.playerTwousername, {status : "In Game"}) + console.log("USERNAME : " + tokenGame.playerOneUsername) + const user : User = await this.userRepository.createQueryBuilder('user') + .where("user.username = :username", {username : tokenGame.playerOneUsername}) + .getOne(); + user.status = "In Game"; + this.userRepository.save(user); + return true; } - return true; } return false; } async findInvitations(user : User) { const game = await this.tokenGameRepository.createQueryBuilder('tokengame') - .where('tokenGame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) + .where('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) + .andWhere('tokengame.isGameIsWithInvitation = :invit', {invit : true}) + .andWhere('tokengame.isSecondUserAcceptedRequest = :choice', {choice : false}) .getMany(); if (!game) return new HttpException( "No invitations !", HttpStatus.NOT_FOUND); @@ -126,25 +131,57 @@ export class GameService { for (const gameToken of game) { partialGame.push({ playerOneUsername : gameToken.playerOneUsername, - playerTwousername : gameToken.playerTwousername, + playerTwoUsername : gameToken.playerTwoUsername, gameOptions : gameToken.gameOptions, - isGameIsWithInvitation : gameToken.isGameIsWithInvitation, token : gameToken.token, }); } return partialGame; } - async declineInvitation(validateTicketDto : ValidateTicketDto) + async declineInvitation(user : User, token : string) { - const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') - .where('tokenGame.playerOneUsername = :playerOneUsername', {playerOneUsername : validateTicketDto.playerOneUsername}) - .andWhere('tokenGame.playerTwousername = :playerTwousername', {playerTwousername : validateTicketDto.playerTwousername}) - .andWhere('tokenGame.gameOption = :gameOption', {gameOption : validateTicketDto.gameOptions}) - .andWhere('tokenGame.isGameIsWithInvitation = :isGameIsWithInvitation', {isGameIsWithInvitation: validateTicketDto.isGameIsWithInvitation}) - .andWhere('tokenGame.token = :token', {token : validateTicketDto.token}) + if (user.status === "In Game") + return new HttpException("You must finish your game before decline.", HttpStatus.FORBIDDEN) + const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokengame') + .andWhere('tokengame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) + .andWhere('tokengame.token = :token', {token : token}) .getOne(); - return this.tokenGameRepository.remove(tokenGame); + if (tokenGame) + return this.tokenGameRepository.remove(tokenGame); + return new HttpException("Invitation not found !", HttpStatus.NOT_FOUND) + } + + async acceptInvitation(user : User, token : string) + { + if (user.status === "In Game") + return new HttpException("You must finish your game before accept.", HttpStatus.FORBIDDEN) + const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') + .andWhere('tokenGame.playerTwoUsername = :playerTwoUsername', {playerTwoUsername : user.username}) + .andWhere('tokenGame.token = :token', {token : token}) + .getOne(); + if (tokenGame) + { + tokenGame.isSecondUserAcceptedRequest = true; + this.tokenGameRepository.save(tokenGame) + return HttpStatus.OK + } + return new HttpException("Invitation not found !", HttpStatus.NOT_FOUND) + } + + async requestIfAnotherUserHasRespondToquestForGame(user : User, token : string) { + if (user.status === "In Game") + return new HttpException("You can't do that.", HttpStatus.BAD_REQUEST) + const tokenGame = await this.tokenGameRepository.createQueryBuilder('tokenGame') + .andWhere('tokenGame.token = :token', {token : token}) + .andWhere('tokenGame.isSecondUserAcceptedRequest = :isSecondUserAcceptedRequest', {isSecondUserAcceptedRequest : true}) + .getOne(); + if (tokenGame && tokenGame.isSecondUserAcceptedRequest === true) + return {isSecondUserAcceptedRequest : true} + else if (tokenGame && tokenGame.isSecondUserAcceptedRequest === false) + return {isSecondUserAcceptedRequest : false} + else if (!tokenGame) + return new HttpException("Not Found", HttpStatus.NOT_FOUND) } } diff --git a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts index 2cefe160..a7e3074d 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.controller.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.controller.ts @@ -85,7 +85,7 @@ export class UsersController { const user = await this.usersService.update(req.user.id, usersUpdateDto); if (user.isEnabledTwoFactorAuth === false && user.isTwoFactorAuthenticated === true) this.usersService.setIsTwoFactorAuthenticatedWhenLogout(user.id); - console.log ("Enbale 2FA " + user.isEnabledTwoFactorAuth + " Is authenticated " + user.isTwoFactorAuthenticated); + console.log ("Enable 2FA " + user.isEnabledTwoFactorAuth + " Is authenticated " + user.isTwoFactorAuthenticated); if (user.isEnabledTwoFactorAuth === true && user.isTwoFactorAuthenticated === false) { response.status(201).send('2FA redirect') diff --git a/srcs/requirements/nestjs/api_back/src/users/users.service.ts b/srcs/requirements/nestjs/api_back/src/users/users.service.ts index 929d93d9..be1c19b2 100644 --- a/srcs/requirements/nestjs/api_back/src/users/users.service.ts +++ b/srcs/requirements/nestjs/api_back/src/users/users.service.ts @@ -4,12 +4,9 @@ import { User } from './entities/user.entity'; import { Repository } from 'typeorm'; import { CreateUsersDto } from './dto/create-users.dto'; import { UpdateUsersDto } from './dto/update-users.dto'; -import { Friendship } from '../friendship/entities/friendship.entity'; import { PaginationQueryDto } from 'src/common/dto/pagination-query.dto'; import { UserStats } from './entities/userStat.entities'; import { FriendshipService } from 'src/friendship/friendship.service'; -import { stringify } from 'querystring'; - // On va devoir sûrement trouver un moyen plus simple pour passer l'id, sûrement via des pipes // ou des interceptors, mais pour l'instant on va faire comme ça. @Injectable() diff --git a/srcs/requirements/svelte/api_front/src/App.svelte b/srcs/requirements/svelte/api_front/src/App.svelte index 7a383eb1..5f293b5e 100644 --- a/srcs/requirements/svelte/api_front/src/App.svelte +++ b/srcs/requirements/svelte/api_front/src/App.svelte @@ -2,7 +2,7 @@ // routing // may not need {link} here import Router, { link, replace } from "svelte-spa-router"; - import { primaryRoutes } from "./routes/primaryRoutes.js"; + import { primaryRoutes } from "./routes/primaryRoutes.js"; // import primaryRoutes from "./routes/primaryRoutes.svelte"; const conditionsFailed = (event) => { diff --git a/srcs/requirements/svelte/api_front/src/pages/GamePage.svelte b/srcs/requirements/svelte/api_front/src/pages/GamePage.svelte deleted file mode 100644 index 5e08c6f4..00000000 --- a/srcs/requirements/svelte/api_front/src/pages/GamePage.svelte +++ /dev/null @@ -1,106 +0,0 @@ - - - -
-
- game options -
- - -
-
- - -
-
- - - - - -
-
- -
-
-
- -
-

--- keys ---

-

move up: 'w' or 'up arrow'

-

move down: 's' OR 'down arrow'

-

grid on/off: 'g'

-
- -
- -
- - - - - \ No newline at end of file diff --git a/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte b/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte index 754776ea..11ec14ff 100644 --- a/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte +++ b/srcs/requirements/svelte/api_front/src/pages/game/Game.svelte @@ -1,39 +1,153 @@ - - - +
.
-{#if optionsAreNotSet} -
-
-
- game options -
- - -
-
- - -
-
- - -
-
- -
-
+ {#if showError === true} +
+

{errorMessageWhenAttemptingToGetATicket}

- -
-

--- keys ---

-

move up: 'w' or 'up arrow'

-

move down: 's' OR 'down arrow'

-

grid on/off: 'g'

-
+ {/if} + + {#if showWaitPage === true} +
+ Connecting to the game... +
+

{waitingMessage}

+
+
+ {/if} + +{#if optionsAreNotSet} + {#if showGameOption === true} +
+
+ +
+ game options +
+ + +
+
+ + +
+
+ + +
+
+ + +
+ {#if invite_someone === true} + + {/if} +
+ +
+
+
+
+ {/if} + {#if showInvitations} +
+ +
+ Current invitation(s) + {#if isThereAnyInvitation} + {#each invitations as invitation } +
+ {invitation.playerOneUsername} has invited you to play a pong ! + + +
+ {/each} + {/if} + {#if isThereAnyInvitation ===false} +

Currently, no one asked to play with you.

+ + {/if} +
+
+ {/if} {/if}
@@ -128,21 +316,29 @@ body { /* max-height: 80vh; */ /* overflow: hidden; */ } -#div_game_options { +#div_game { text-align: center; font-family: "Bit5x3"; color: rgb(245, 245, 245); font-size: x-large; } -#div_game_options fieldset { + +#error_notification { + text-align: center; + display: block; + font-family: "Bit5x3"; + color: rgb(143, 19, 19); + font-size: x-large; +} +#div_game fieldset { max-width: 50vw; width: auto; margin: 0 auto; } -#div_game_options fieldset div { +#div_game fieldset div { padding: 10px; } -#play_pong_button { +#pong_button { font-family: "Bit5x3"; color: rgb(245, 245, 245); background-color: #333333; diff --git a/srcs/requirements/svelte/api_front/src/pieces/Header.svelte b/srcs/requirements/svelte/api_front/src/pieces/Header.svelte index dee06c62..083f09d3 100644 --- a/srcs/requirements/svelte/api_front/src/pieces/Header.svelte +++ b/srcs/requirements/svelte/api_front/src/pieces/Header.svelte @@ -24,6 +24,7 @@ Potato Pong Logo (push('/'))}>

Potato Pong