Affichage dynamique de la navbar et des pages + Connexion/Déconnexion OK

pull/81/head
Baptiste MARCEL 2 years ago
parent c9a405a554
commit a49cc06aa3

@ -3,6 +3,7 @@ import React from 'react';
import { useState } from 'react';
import { IntlProvider } from 'react-intl';
import { GameProvider } from './Contexts/GameContext';
import { AuthProvider } from './Contexts/AuthContext';
/* Page */
import Home from './Pages/Home';
@ -63,9 +64,10 @@ function App() {
// <img src={logo} className="App-logo" alt="logo" />
// </header>
// </div>
<AuthProvider>
<GameProvider>
{/*@ts-ignore*/}
{/*@ts-ignore*/}
<IntlProvider locale={locale} messages={messages[locale]}>
<ThemeProvider>
<BrowserRouter>
@ -85,7 +87,7 @@ function App() {
</ThemeProvider>
</IntlProvider>
</GameProvider>
</AuthProvider>
);
}

@ -1,4 +1,4 @@
import React from 'react';
import React, {useEffect, useState} from 'react';
/* Naviagtion */
import { Navbar, Container, Nav, NavDropdown } from 'react-bootstrap';
@ -7,7 +7,7 @@ import { Navbar, Container, Nav, NavDropdown } from 'react-bootstrap';
import { FormattedMessage } from 'react-intl';
/* Icon */
import { BiLogInCircle } from 'react-icons/bi';
import { BiDoorOpen, BiLogInCircle } from 'react-icons/bi';
import { BsFillPersonPlusFill } from 'react-icons/bs';
import { HiLanguage } from 'react-icons/hi2';
@ -17,16 +17,22 @@ import logo from '../res/img/logo2_preview_rev_1.png';
/* Components */
import ReactCountryFlag from "react-country-flag"
/* Services */
import SessionService from '../services/SessionService';
import AuthService from '../services/AuthService';
/* Style */
import './NavBar.css';
/* Style */
import { useTheme } from '../Style/ThemeContext';
import { useAuth } from '../Contexts/AuthContext';
// @ts-ignore
function AppNavbar({changeLocale}) {
const theme = useTheme();
const {isLoggedIn, logout} = useAuth();
return (
<Navbar expand="lg" className="custom-navbar" style={{ backgroundColor: theme.colors.primary }}>
<Container>
@ -45,14 +51,26 @@ function AppNavbar({changeLocale}) {
</Nav>
<div className='leftdiv'>
<Nav className="ml-auto navbar-title-dd">
<Nav.Link href="login" className='navbar-title-dd' style={{ backgroundColor: theme.colors.secondary }}>
<BiLogInCircle/>
<FormattedMessage id="log_in"/>
</Nav.Link>
<Nav.Link href="signup" className='navbar-title-dd' style={{ backgroundColor: theme.colors.secondary }}>
<BsFillPersonPlusFill/>
<FormattedMessage id="sign_up"/>
</Nav.Link>
{/* Affichage dynamique selon état de connexion */}
{isLoggedIn ? (
<Nav.Link href="/play" onClick={logout} className='navbar-title-dd' style={{ backgroundColor: theme.colors.secondary }}>
<BiDoorOpen />
<FormattedMessage id="log_out" />
</Nav.Link>
)
: (
<>
<Nav.Link href="/login" className='navbar-title-dd' style={{ backgroundColor: theme.colors.secondary }}>
<BiLogInCircle />
<FormattedMessage id="log_in" />
</Nav.Link>
<Nav.Link href="/signup" className='navbar-title-dd' style={{ backgroundColor: theme.colors.secondary }}>
<BsFillPersonPlusFill />
<FormattedMessage id="sign_up" />
</Nav.Link>
</>
)
}
</Nav>
<Nav className="me-auto">
<NavDropdown

@ -21,9 +21,13 @@ import Col from 'react-bootstrap/Col';
/* Component */
import ButtonImgNav from './ButtonImgNav';
/* Types */
import { PlayerProps } from '../types/Player';
//@ts-ignore
function ScoreBoard({Player = null}) {
const ScoreBoard: React.FC<{ Player: PlayerProps }> = ({ Player }) => {
const theme=useTheme();
return (
// <div className='LeaderBoardiv'>
<div className='LeaderBoardiv'>
@ -31,9 +35,36 @@ function ScoreBoard({Player = null}) {
defaultActiveKey="profile"
id="ScoreBoard"
className="mb-3">
<Tab eventKey="perso" title="Vos Stats" disabled>
Tab content for Contact
<Tab eventKey="perso" title="Vos Stats" disabled = { !Player.pseudo.startsWith("Guest_") ? false : true}>
<Container fluid>
<Row>Stats en solo :</Row>
<Row>
<Col sm={10}>Partie Jouées :</Col>
<Col className='leftRow'>{Player !== null ? Player.soloStats.nbGames : "0"}</Col>
</Row>
<Row>
<Col sm={10}>Best-Score :</Col>
<Col className='leftRow'>{Player !== null ? Player.soloStats.bestScore : "0"}</Col>
</Row>
<Row>
<Col sm={10}>Moyenne d'essai :</Col>
<Col className='leftRow'>{Player !== null ? Player.soloStats.avgNbTry : "0"}</Col>
</Row>
<hr/>
<Row>Stats en ligne :</Row>
<Row>
<Col sm={10}>Partie jouée :</Col>
<Col className='leftRow'>{Player !== null ? Player.onlineStats.nbGames : "0"}</Col>
</Row>
<Row>
<Col sm={10}>Nombre de victoire :</Col>
<Col className='leftRow'>{Player !== null ? Player.onlineStats.nbWins : "0"}</Col>
</Row>
<Row>
<Col sm={10}>Ratio P/V :</Col>
<Col className='leftRow'>{Player !== null ? Player.onlineStats.ratio : "0"}</Col>
</Row>
</Container>
</Tab>
<Tab eventKey="daily" title="Daily"
style={{display:"flex", flexDirection:'column', alignItems:'center'}}>

@ -0,0 +1,45 @@
// AuthContext.js
import React, { createContext, useContext, useState, ReactNode } from 'react';
import AuthService from '../services/AuthService';
interface AuthContextProps {
isLoggedIn: boolean;
login: () => void;
logout: () => void;
}
const AuthContext = createContext<AuthContextProps | undefined>(undefined);
const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
const [isLoggedIn, setIsLoggedIn] = useState<boolean>(false);
const login = () => {
setIsLoggedIn(true);
};
const logout = async() => {
try {
await AuthService.logout();
setIsLoggedIn(false);
}
catch (error) {
console.log(error);
};
};
return (
<AuthContext.Provider value={{ isLoggedIn, login, logout }}>
{children}
</AuthContext.Provider>
);
};
const useAuth = (): AuthContextProps => {
const context = useContext(AuthContext);
if (!context) {
throw new Error('useAuth must be used within an AuthProvider');
}
return context;
};
export { AuthProvider, useAuth };

@ -1,4 +1,6 @@
import React from 'react';
import React, {useEffect} from 'react';
import { useAuth } from '../Contexts/AuthContext';
import SessionService from '../services/SessionService';
import './Home.css';
import '../App.css';
import { useTheme } from '../Style/ThemeContext';
@ -9,6 +11,25 @@ import ButtonImgNav from '../Components/ButtonImgNav';
function Home() {
const theme=useTheme();
const {isLoggedIn, login} = useAuth();
useEffect(() => {
// Verifie la connexion
const verifSession = async () => {
try {
const sessionData = await SessionService.getSession();
if (sessionData.user) {
login();
}
}
catch (error) {
console.log(error);
};
}
verifSession();
}, []);
return (
<div className="home-container">

@ -1,11 +1,13 @@
import React, { useState, useEffect } from 'react';
import { AiOutlineSend } from 'react-icons/ai';
import { useNavigate } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import { useAuth } from '../Contexts/AuthContext';
import AuthService from '../services/AuthService';
import '../Style/Global.css';
const SignIn = () => {
const navigate = useNavigate();
const navigate = useNavigate();
const { login } = useAuth();
const [error, setError] = useState<string | null>(null);
const [showConfirmation, setShowConfirmation] = useState(false);
@ -32,6 +34,7 @@ const SignIn = () => {
setShowConfirmation(true);
setTimeout(() => {
login();
navigate('/play'); // 3 secondes avant de rediriger vers la page de connexion
}, 3000);
}

@ -1,12 +1,12 @@
import React, { useEffect, useState } from 'react';
/* Context */
import { useAuth } from '../Contexts/AuthContext';
/* Style */
import './Play.css';
import { useTheme } from '../Style/ThemeContext';
/* Nav */
import { Link } from 'react-router-dom';
/* Component */
import ButtonImgNav from "../Components/ButtonImgNav"
import SessionService from "../services/SessionService";
@ -15,43 +15,66 @@ import SessionService from "../services/SessionService";
import Person from '../res/img/Person.png';
/* Icon */
import trophy from '../res/icon/trophy.png';
import param from '../res/icon/param.png';
import share from '../res/icon/share.png';
import { socket } from '../SocketConfig';
import { useNavigate } from 'react-router-dom';
import GameCreator from '../model/GameCreator';
import { useGame } from '../Contexts/GameContext';
import ScoreBoard from '../Components/ScoreBoard';
import { set } from 'lodash';
/* Types */
import { PlayerProps } from '../types/Player';
function Play() {
const theme=useTheme()
const [username, setUsername] = useState('');
const [nbSoloGames, setNbSoloGames] = useState(0);
const [soloBestScore, setSoloBestScore] = useState(0);
const [soloAverageTry, setSoloAverageTry] = useState(0);
const {isLoggedIn, login} = useAuth();
const [player, setPlayer] = useState<PlayerProps | null>(null);
useEffect(() => {
const fetchUserInformation = async () => {
try {
const sessionData = await SessionService.getSession();
console.log(sessionData);
// Vérifie si il y a une session
if (sessionData.user) {
setUsername(sessionData.user.pseudo);
setNbSoloGames(sessionData.user.soloStats.nbGames);
setSoloBestScore(sessionData.user.soloStats.bestScore);
setSoloAverageTry(sessionData.user.soloStats.averageTry);
} else {
// Pas de session on génère un guest random
setUsername(`Guest ${Math.floor(Math.random() * 100000)}`);
try {
const sessionData = await SessionService.getSession();
// Vérifie si il y a une session
if (sessionData.user) {
// Il y a une session on récupère les infos du joueur
const updatedPlayer: PlayerProps = {
pseudo: sessionData.user.pseudo,
profilePicture: sessionData.user.profilePicture,
soloStats: {
nbGames: sessionData.user.soloStats.nbGames,
bestScore: sessionData.user.soloStats.bestScore,
avgNbTry: sessionData.user.soloStats.avgNbTry,
},
onlineStats: {
nbGames: sessionData.user.onlineStats.nbGames,
nbWins: sessionData.user.onlineStats.nbWins,
ratio: sessionData.user.onlineStats.ratio,
},
};
login();
setPlayer(updatedPlayer);
} else {
// Pas de session on génère un guest random
const guestPlayer: PlayerProps = {
pseudo: 'Guest_' + Math.floor(Math.random() * 1000000),
profilePicture: '',
soloStats: {
nbGames: 0,
bestScore: 0,
avgNbTry: 0,
},
onlineStats: {
nbGames: 0,
nbWins: 0,
ratio: 0,
},
};
setPlayer(guestPlayer);
}
} catch (error) {
console.error(error);
}
} catch (error) {
console.error(error);
}
};
fetchUserInformation();
@ -113,7 +136,7 @@ function Play() {
<div className="MidContainer">
<div>
<h2>
{username}
{player && player.pseudo}
</h2>
<img src={Person}
height='300'
@ -129,7 +152,7 @@ function Play() {
</div>
</div>
<div className='rightContainer'>
<ScoreBoard/>
{player && (<ScoreBoard Player={player}/>)}
</div>
</div>
);

@ -21,6 +21,7 @@
"log_in":" Log in ",
"sign_up":" Sign up ",
"log_out":" Log out ",
"join" : "Join",
"create_room" : "Create room",

@ -21,6 +21,7 @@
"log_in":" Se connecter ",
"sign_up":" S'inscrire ",
"log_out":" Se déconnecter ",
"join" : "Rejoindre",

@ -87,16 +87,16 @@ class AuthController {
}
}
static getSession(req, res) {
console.log(req.session);
// Vérifier si l'utilisateur est connecté
if (req.session.user) {
// Envoyer une réponse réussie
res.status(200).json({ message: 'Utilisateur connecté', user: req.session.user });
} else {
// Envoyer une réponse d'erreur
res.status(401).json({ error: 'Utilisateur non connecté' });
}
static async logout(req, res) {
// Détruire la session pour déconnecter l'utilisateur
req.session.destroy((err) => {
if (err) {
console.error(err);
res.status(500).json({ error: 'Erreur lors de la déconnexion.' });
} else {
res.status(200).json({ message: 'Déconnexion réussie' });
}
});
}
}

@ -6,6 +6,7 @@ const SessionController = require('../controllers/SessionController');
// Routes pour l'authentification
router.post('/auth/signup', AuthController.signUp);
router.post('/auth/signin', AuthController.signIn);
router.delete('/auth/logout', AuthController.logout)
// Routes pour les sessions
router.get('/session', SessionController.getUserInformation);

@ -58,6 +58,29 @@ class AuthService{
throw error;
}
}
static async logout() {
try {
const response = await fetch('http://localhost:3003/auth/logout', {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
},
credentials: 'include',
});
if (response.ok) {
const result = await response.json();
return result;
} else {
const errorResponse = await response.json();
throw new Error(errorResponse.error);
}
} catch (error) {
console.error(error);
throw error;
}
}
}
export default AuthService;

@ -0,0 +1,18 @@
export interface PlayerSoloStats {
nbGames: number;
bestScore: number;
avgNbTry: number;
};
export interface PlayerOnlineStats {
nbGames: number;
nbWins: number;
ratio: number;
};
export interface PlayerProps {
profilePicture: string;
pseudo: string;
soloStats: PlayerSoloStats;
onlineStats: PlayerOnlineStats;
};
Loading…
Cancel
Save