diff --git a/API/src/socket.io/UserInfo.ts b/API/src/socket.io/UserInfo.ts new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/Frontend/quizz-game/package-lock.json b/Frontend/quizz-game/package-lock.json index 499d5d910ab3c48dc6cf784d1ad390600453109b..119667477327dfa3b2a70b9e4dc4014c4d6e0f25 100644 --- a/Frontend/quizz-game/package-lock.json +++ b/Frontend/quizz-game/package-lock.json @@ -18,6 +18,7 @@ "@angular/router": "^16.0.0", "crypto-js": "^4.1.1", "rxjs": "~7.8.0", + "socket.io-client": "^4.6.2", "tslib": "^2.3.0", "zone.js": "~0.13.0" }, @@ -3022,8 +3023,7 @@ "node_modules/@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", - "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==", - "dev": true + "integrity": "sha512-+9jVqKhRSpsc591z5vX+X5Yyw+he/HCB4iQ/RYxw35CEPaY1gnsNE43nf9n9AaYjAQrTiI/mOwKUKdUs9vf7Xg==" }, "node_modules/@tailwindcss/aspect-ratio": { "version": "0.4.2", @@ -4973,7 +4973,6 @@ "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, "dependencies": { "ms": "2.1.2" }, @@ -5261,11 +5260,22 @@ "node": ">=10.0.0" } }, + "node_modules/engine.io-client": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.4.0.tgz", + "integrity": "sha512-GyKPDyoEha+XZ7iEqam49vz6auPnNJ9ZBfy89f+rMMas8AuiMWOZ9PVzu8xb9ZC6rafUqiGHSCfu22ih66E+1g==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.0.3", + "ws": "~8.11.0", + "xmlhttprequest-ssl": "~2.0.0" + } + }, "node_modules/engine.io-parser": { "version": "5.0.6", "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.0.6.tgz", "integrity": "sha512-tjuoZDMAdEhVnSFleYPCtdL2GXwVTGtNjoeJd9IhIG3C1xs9uwxqRNEu5WpnDZCaozwVlK/nuQhpodhXSIMaxw==", - "dev": true, "engines": { "node": ">=10.0.0" } @@ -8293,8 +8303,7 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -10867,11 +10876,24 @@ "ws": "~8.11.0" } }, + "node_modules/socket.io-client": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.6.2.tgz", + "integrity": "sha512-OwWrMbbA8wSqhBAR0yoPK6EdQLERQAYjXb3A0zLpgxfM1ZGLKoxHx8gVmCHA6pcclRX5oA/zvQf7bghAS11jRA==", + "dependencies": { + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.2", + "engine.io-client": "~6.4.0", + "socket.io-parser": "~4.2.4" + }, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/socket.io-parser": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.2.tgz", - "integrity": "sha512-DJtziuKypFkMMHCm2uIshOYC7QaylbtzQwiMYDuCKy3OPkjLzu4B2vAhTlqipRHHzrI0NJeBAizTK7X+6m1jVw==", - "dev": true, + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", + "integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.1" @@ -12534,7 +12556,6 @@ "version": "8.11.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz", "integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==", - "dev": true, "engines": { "node": ">=10.0.0" }, @@ -12551,6 +12572,14 @@ } } }, + "node_modules/xmlhttprequest-ssl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", + "integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", diff --git a/Frontend/quizz-game/package.json b/Frontend/quizz-game/package.json index 02f1ca8426d0abeee0fdd352ac4b34eee3455771..1f7d3b486d430e35b66d7619b92eaacbf246aa90 100644 --- a/Frontend/quizz-game/package.json +++ b/Frontend/quizz-game/package.json @@ -20,6 +20,7 @@ "@angular/router": "^16.0.0", "crypto-js": "^4.1.1", "rxjs": "~7.8.0", + "socket.io-client": "^4.6.2", "tslib": "^2.3.0", "zone.js": "~0.13.0" }, diff --git a/Frontend/quizz-game/src/app/homepage/homepage.component.html b/Frontend/quizz-game/src/app/homepage/homepage.component.html index 114dc7228107e494c817764c413a8e50f3cebc4d..e498d993a423b2358d6756cc20ba835682d21bd5 100644 --- a/Frontend/quizz-game/src/app/homepage/homepage.component.html +++ b/Frontend/quizz-game/src/app/homepage/homepage.component.html @@ -12,9 +12,16 @@ </div> + + </div> <div class="w-3/4 h-screen"> <router-outlet></router-outlet> + <div class="fixed w-3/4 bottom-0 left-1/4 right-0 flex justify-center mb-4"> + <button class="bg-red-500 hover:bg-red-600 text-white font-bold py-2 px-4 rounded" (click)="logOut()"> + Se déconnecter + </button> + </div> </div> </div> diff --git a/Frontend/quizz-game/src/app/homepage/homepage.component.ts b/Frontend/quizz-game/src/app/homepage/homepage.component.ts index 50fa2cec1839d5ffe55c4d1035e56a0d13b4bda8..58929bd7801ec9b7ea345e61ff7dcd4ed1f76080 100644 --- a/Frontend/quizz-game/src/app/homepage/homepage.component.ts +++ b/Frontend/quizz-game/src/app/homepage/homepage.component.ts @@ -1,5 +1,8 @@ import {Component, OnInit} from '@angular/core'; import {User} from "../manage/users/user-model"; +import {ActivatedRoute, Router} from "@angular/router"; +import {QuizzService} from "./quizz.service"; +import {SessionService} from "../login/session.service"; @Component({ selector: 'app-homepage', @@ -7,10 +10,29 @@ import {User} from "../manage/users/user-model"; styleUrls: ['./homepage.component.css'] }) export class HomepageComponent implements OnInit { + loading=false; players: User[]= []; + constructor(private sessionService: SessionService, private actRoute: ActivatedRoute, private quizzService: QuizzService, private router: Router) { + } + ngOnInit() { - this.players.push(new User("test", "voila", "moi", "sdfg@sdf.th", "user", "fsfdss")); + this.loading=true; + this.actRoute.paramMap.subscribe((paramM) => { + if (!paramM.has('username')) { + this.router.navigate(['/', 'login']); + return; + } + this.quizzService.username = paramM.get('username')!!; + console.log(this.quizzService.username); + + }) + } + //this.players.push(new User("test", "voila", "moi", "sdfg@sdf.th", "user", "fsfdss")); + logOut(){ + this.router.navigate(['/', 'login']); + //this.sessionService.deleteToken(); + this.quizzService.socket.disconnect(); } onUserConnect(user:User){ diff --git a/Frontend/quizz-game/src/app/homepage/quizz.service.ts b/Frontend/quizz-game/src/app/homepage/quizz.service.ts index 36b1331b4789b984ed9c3216fd6d4f4616a6b15d..6957542528d96db82569a6062b8538b374c54151 100644 --- a/Frontend/quizz-game/src/app/homepage/quizz.service.ts +++ b/Frontend/quizz-game/src/app/homepage/quizz.service.ts @@ -1,15 +1,73 @@ import { Injectable } from '@angular/core'; -import {User} from "../manage/users/user-model"; -import {BehaviorSubject} from "rxjs"; +import {BehaviorSubject, Subject} from "rxjs"; +import {HttpClient} from "@angular/common/http"; +import {Session} from "../login/session-model"; +import {SessionService} from "../login/session.service"; +import { io, Socket } from 'socket.io-client'; + @Injectable({ providedIn: 'root' }) export class QuizzService { - private _players= new BehaviorSubject<User[]>([]); + private _players= new BehaviorSubject<Session[]>([]); + private _username!: string; + private _userInfo!: Session; + public userInfoSubject = new Subject<Session>(); + private _socket!: Socket; + get players(){ return this._players.asObservable(); } - constructor() { } + + get username(): string{ + return this._username; + } + + set username(value: string){ + this._username=value; + } + + get userInfo(): Session{ + return this._userInfo; + } + + get socket(): Socket{ + return this._socket; + } + + + + constructor(private httpClient: HttpClient, private sessionService: SessionService) { } + + async getUserInfo(): Promise<Session> { + return new Promise<any>((resolve, reject) => { + this.httpClient.get<any>('http://localhost:30992/api/v1/gamer/' + this.username).subscribe( + response => { + this._userInfo=new Session( + response.access_user.firstname, + response.access_user.lastname + ) + this.userInfoSubject.next(this.userInfo); + this.connetToSocketIo(); + resolve(this._userInfo); + }, + error => { + reject(error.error.message); + } + ); + }); + } + + private connetToSocketIo(){ + const token = this.sessionService.token; + this._socket= io('http://localhost:30992', { + auth: { + token: token // Inclure le JWT dans la requête d'authentification + } + }); + } + + } diff --git a/Frontend/quizz-game/src/app/homepage/waiting-players/waiting-players.component.html b/Frontend/quizz-game/src/app/homepage/waiting-players/waiting-players.component.html index 934d865f560e3b1562fd0e7860c18a8b10758621..9084e14c61d3a87120d8642a49c13905c5f7ef7f 100644 --- a/Frontend/quizz-game/src/app/homepage/waiting-players/waiting-players.component.html +++ b/Frontend/quizz-game/src/app/homepage/waiting-players/waiting-players.component.html @@ -1,14 +1,22 @@ -<script src="waiting-players.component.ts"></script> <div class="flex items-center justify-center h-screen bg-primary"> <div class="bg-white rounded-lg shadow p-8"> - <h1 class="text-2xl font-bold mb-4">Bienvenue></h1> - <h2 class="text-2xl font-bold mb-4">En attente de 3 joueurs...</h2> - <p class="text-gray-600">Veuillez patienter pendant que d'autres joueurs se connectent.</p> - <div class="flex justify-center mt-6"> - <div class="w-8 h-8 bg-sky-500 rounded-full animate-bounce"></div> - <div class="w-8 h-8 bg-sky-500 rounded-full mx-1 "></div> - <div class="w-8 h-8 bg-sky-500 rounded-full"></div> + <app-loading *ngIf="loading"></app-loading> + <div *ngIf="!loading"> + <h1 class="text-3xl font-bold mb-4">Bienvenue {{ userInfo.firstname}} {{ userInfo.lastname }}</h1> </div> + <div *ngIf="!loading && !gameBegin"> + <h2 class="text-2xl font-bold mb-4">En attente de {{ playerLeft }} joueurs...</h2> + <p class="text-gray-600">Veuillez patienter pendant que d'autres joueurs se connectent.</p> + <div class="flex justify-center mt-6"> + <div class="w-8 h-8 bg-sky-500 rounded-full animate-bounce"></div> + <div class="w-8 h-8 bg-sky-500 rounded-full mx-1 "></div> + <div class="w-8 h-8 bg-sky-500 rounded-full"></div> + </div> + </div> + <div *ngIf="gameBegin"> + <h2 class="text-2xl font-bold mb-4">Le jeu peut maintenant commencé</h2> + </div> + </div> </div> diff --git a/Frontend/quizz-game/src/app/homepage/waiting-players/waiting-players.component.ts b/Frontend/quizz-game/src/app/homepage/waiting-players/waiting-players.component.ts index cc6d73fe26c0648e901d820c1cf841d8677c5894..e92c4a3f96396ee631238d7ff3dc1114ab001881 100644 --- a/Frontend/quizz-game/src/app/homepage/waiting-players/waiting-players.component.ts +++ b/Frontend/quizz-game/src/app/homepage/waiting-players/waiting-players.component.ts @@ -1,24 +1,70 @@ -import {Component, OnInit} from '@angular/core'; +import {AfterViewInit, Component, Input, OnDestroy, OnInit} from '@angular/core'; import {Session} from "../../login/session-model"; -import {SessionService} from "../../login/session.service"; import {Subscription} from "rxjs"; +import {QuizzService} from "../quizz.service"; +import {Router} from "@angular/router"; +import {SessionService} from "../../login/session.service"; @Component({ selector: 'app-waiting-players', templateUrl: './waiting-players.component.html', styleUrls: ['./waiting-players.component.css'] }) -export class WaitingPlayersComponent implements OnInit{ +export class WaitingPlayersComponent implements OnInit, OnDestroy{ userInfo!: Session; userSub!: Subscription; - constructor(private sessionService: SessionService) { + loading!: boolean; + private startGameSubscription!: any; + private playersLeftSub!:any; + gameBegin!:boolean; + playerLeft!: number; + constructor(private sessionService: SessionService, private quizzService: QuizzService, private router: Router) { } ngOnInit() { - this.userSub=this.sessionService.sessionSubject.subscribe((session)=>{ + this.loading=true; + this.gameBegin=false; + this.userSub=this.quizzService.userInfoSubject.subscribe((session)=>{ this.userInfo=session; + }); + this.quizzService.getUserInfo().then(userInfo => { + if(this.quizzService.socket){ + this.playersLeftSub=this.quizzService.socket.on('players-left', (playerLeft) => { + console.log("player left:", playerLeft); + this.gameBegin=false; + this.playerLeft=playerLeft; + }); + this.startGameSubscription=this.quizzService.socket.on('start-game', () => { + console.log("start game"); + this.gameBegin=true; + }); + } + this.loading=false; + + }).catch(error=>{ + this.loading=false; + console.log("erreur get user:", error); + if(error === "Invalid token user"){ + alert("Votre session a expiré, veuillez vous reconnecter"); + this.router.navigate(['/', 'login']); + //this.sessionService.deleteToken(); + this.quizzService.socket.disconnect(); + } }) - console.log(this.userInfo); + } + + + + ngOnDestroy() { + if(this.userSub) + this.userSub.unsubscribe(); + /* + if(this.startGameSubscription) + this.startGameSubscription.unsubscribe(); + if(this.playersLeftSub) + this.playersLeftSub.unsubscribe(); + + */ } } diff --git a/Frontend/quizz-game/src/app/login/session.service.ts b/Frontend/quizz-game/src/app/login/session.service.ts index 33b48722d0d880d5927aafb64fa0d48c62383d53..102ecebf3b71999585b6c1cab88cf589461e7687 100644 --- a/Frontend/quizz-game/src/app/login/session.service.ts +++ b/Frontend/quizz-game/src/app/login/session.service.ts @@ -29,6 +29,10 @@ export class SessionService { localStorage.setItem(SessionService.LS_SESSION_TOKEN, token) } + deleteToken(){ + localStorage.removeItem(SessionService.LS_SESSION_TOKEN) + } + constructor() { } } diff --git a/Frontend/quizz-game/src/app/manage/manage.component.ts b/Frontend/quizz-game/src/app/manage/manage.component.ts index 2740150c3fcf958fc69b21c13ab144a658e2f7bf..21dfa9878968156bd544d64d24780bccfa5178b9 100644 --- a/Frontend/quizz-game/src/app/manage/manage.component.ts +++ b/Frontend/quizz-game/src/app/manage/manage.component.ts @@ -28,8 +28,19 @@ export class ManageComponent implements OnInit { console.log(this.manageService.username); this.manageService.getUserInfo().then(userInfo => { this.loading=false; + if(userInfo.type === "user"){ + alert("Vous n'avez pas les autorisations nécessaires pour accéder à ses ressouces, vous allez être redirigé vers la plateforme du quizz"); + this.router.navigate(['/'+this.manageService.username+'/play']); + } this.userNamLast=userInfo.firstname+' '+userInfo.lastname; this.userEm=userInfo.email; + }).catch(error=>{ + this.loading=false; + console.log("erreur get user:", error); + if(error === "Invalid token user"){ + alert("Votre session a expiré, veuillez vous reconnecter"); + this.router.navigate(['/', 'login']); + } }) })