From 76f82abda30a86d02c1a2e33ca996fafc1ddbcb7 Mon Sep 17 00:00:00 2001
From: sansho88 <sansho88@hotmail.fr>
Date: Mon, 23 Oct 2023 21:44:49 +0200
Subject: [PATCH 1/4] Mise a jour en temps reel a chaque fin de match des
 stats, ainsi que du matchHistory. Tentative de reduction des requetes recu
 avec les ws a chaque partie mais bizarre.

---
 front-end/src/app/home/page.tsx               |  1 +
 .../(ben_proto)/DevTools/NavBarDev.tsx        |  3 +-
 front-end/src/components/AvatarComponent.tsx  |  1 +
 .../src/components/LeaderboardComponent.tsx   | 29 ++++++++++++++---
 .../src/components/MatchHistoryComponent.tsx  | 22 ++++++++++---
 front-end/src/components/ProfileComponent.tsx |  3 ++
 front-end/src/components/StatsComponent.tsx   | 20 ++++++++++--
 .../src/components/UserListComponent.tsx      | 32 ++++++++++---------
 8 files changed, 83 insertions(+), 28 deletions(-)

diff --git a/front-end/src/app/home/page.tsx b/front-end/src/app/home/page.tsx
index 4c6ae9c2..6176ef26 100644
--- a/front-end/src/app/home/page.tsx
+++ b/front-end/src/app/home/page.tsx
@@ -18,6 +18,7 @@ export default function ShowHomePage() {
 			router.push("/auth");
 		else
 			setIsTokenExists(true);
+		return;
 	});
 	return (
 		isTokenExists ?
diff --git a/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx b/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx
index 72971ff3..96449e49 100644
--- a/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx
+++ b/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx
@@ -8,7 +8,7 @@ import * as apiReq from '@/components/api/ApiReq'
 
 export function NavBar({className}: {className: string}) {
 
-	const {userContext, setUserContext} = useContext(UserContext);
+	const {userContext} = useContext(UserContext);
 	const {logged, setLogged} = useContext(LoggedContext);
 	const [isHovered, setIsHovered] = useState(false);
   const [turnOffAuth, setTurnOffAuth] = useState<boolean>(false);
@@ -25,6 +25,7 @@ export function NavBar({className}: {className: string}) {
 	|
 	  <div className=' text-violet-700'>{userContext?.nickname}</div>
   </div>)
+      return;
   }, [userContext])
 
 
diff --git a/front-end/src/components/AvatarComponent.tsx b/front-end/src/components/AvatarComponent.tsx
index bf0124c8..316d44f4 100644
--- a/front-end/src/components/AvatarComponent.tsx
+++ b/front-end/src/components/AvatarComponent.tsx
@@ -54,6 +54,7 @@ const Avatar: React.FC<avatarProps> = ({path, width, height, playerStatus, isMai
 
 	useEffect(() => {
 		setStatusColor(getEnumNameByIndex(Colors, playerStatus));
+        return;
 	}, [playerStatus]);
 
 	path = !path ? "/tests/avatar.jpg" : path;
diff --git a/front-end/src/components/LeaderboardComponent.tsx b/front-end/src/components/LeaderboardComponent.tsx
index f95fd28e..5fccdc7c 100644
--- a/front-end/src/components/LeaderboardComponent.tsx
+++ b/front-end/src/components/LeaderboardComponent.tsx
@@ -1,15 +1,22 @@
-import React, {useEffect, useState} from "react";
-import {ILeaderboard} from "@/shared/types";
+import React, {useContext, useEffect, useRef, useState} from "react";
+import {EStatus, ILeaderboard, IUser} from "@/shared/types";
 import {getApi} from "@/components/api/ApiReq";
 import {v4 as uuidv4} from "uuid";
 import Profile from "@/components/ProfileComponent";
+import {SocketContextChat, UserContext} from "@/context/globalContext";
 
 const Leaderboard : React.FC = () => {
     const [leaderboard, setLeaderboard] = useState<ILeaderboard[]>([]);
     let leaderboardElements: React.JSX.Element[] = [];
+    const socketChat      = useContext(SocketContextChat);
+    const socketChatRef   = useRef(socketChat);
+    const {userContext} = useContext(UserContext);
+    let refreshLeaderboard = true;
 
     useEffect(() => {
-            if (leaderboard && leaderboard.length == 0)
+        if (refreshLeaderboard)
+        {
+            //if (leaderboard && leaderboard.length == 0)
                 getApi.getLeaderboard()
                     .then((res) => {
                         setLeaderboard(res.data);
@@ -20,12 +27,24 @@ const Leaderboard : React.FC = () => {
                         setLeaderboard(res.data);
                     })
             }, 30000);
-
+            refreshLeaderboard = false;
             return () => {
                 clearInterval(timer);
             };
-    }, )
 
+        }
+
+    }, [refreshLeaderboard] )
+
+    socketChatRef.current?.on("userUpdate", (data: IUser) => {
+        if (data.UserID == userContext.UserID && data.status == EStatus.Online)
+        {
+            refreshLeaderboard = true;
+            console.log("refresh leaderboard");
+        }
+    });
+
+    socketChatRef.current?.off("userUpdate", () => {});
 
     if (leaderboard.length > 0 ){
         const rankColorsArray = ["gold", "silver", "sienna"]
diff --git a/front-end/src/components/MatchHistoryComponent.tsx b/front-end/src/components/MatchHistoryComponent.tsx
index d82326d5..16d3f622 100644
--- a/front-end/src/components/MatchHistoryComponent.tsx
+++ b/front-end/src/components/MatchHistoryComponent.tsx
@@ -1,8 +1,8 @@
-import React, {useContext, useEffect, useState} from "react";
-import {IMatch, IRelationships} from "@/shared/types";
+import React, {useContext, useEffect, useRef, useState} from "react";
+import {EStatus, IMatch, IRelationships, IUser} from "@/shared/types";
 import {getApi} from "@/components/api/ApiReq";
 import {v4 as uuidv4} from "uuid";
-import {SelectedUserContext} from "@/context/globalContext";
+import {SelectedUserContext, SocketContextChat} from "@/context/globalContext";
 import UserOptions from "@/components/UserOptions";
 
 const MatchHistory : React.FC = () => {
@@ -11,6 +11,8 @@ const MatchHistory : React.FC = () => {
     const [selectedUserRelationships, setSelectedUserRelationships] = useState<IRelationships>({followed:[], blocked:[]});
     const [refresh, setRefresh] = useState(false);
     let matchElements : React.JSX.Element[] = [];
+    const socketChat      = useContext(SocketContextChat);
+    const socketChatRef   = useRef(socketChat);
 
     useEffect(() => {
         if (selectedUserContext)
@@ -37,6 +39,15 @@ const MatchHistory : React.FC = () => {
         }
     }, [selectedUserContext])
 
+    socketChatRef.current?.on("userUpdate", (data: IUser) => {
+        if (selectedUserContext && data.UserID == selectedUserContext.UserID && selectedUserContext.status == EStatus.Online)
+        {
+            setSelectedUserContext(data);
+        }
+    });
+
+    socketChatRef.current?.off("userUpdate", () => {});
+
 
     if (matchesList.length > 0 && matchesList.at(0).ID >= 0){
         for (const match of matchesList) {
@@ -70,8 +81,9 @@ const MatchHistory : React.FC = () => {
             <h1>MATCHES HISTORY</h1>
             {selectedUserContext ?
                 <ul>
-                    <div>{selectedUserContext.nickname}</div>
-                        ({selectedUserContext.login}) <UserOptions user={selectedUserContext} relationships={selectedUserRelationships} setRefresh={setRefresh}/>
+                    {selectedUserContext.nickname}
+                        <span style={{position: "absolute", right: "0"}}>({selectedUserContext.login})</span>
+                    <UserOptions user={selectedUserContext} relationships={selectedUserRelationships} setRefresh={setRefresh}/>
                     <div>{matchElements}</div>
                 </ul>
                 : "No user selected"
diff --git a/front-end/src/components/ProfileComponent.tsx b/front-end/src/components/ProfileComponent.tsx
index b50daae4..58d36572 100644
--- a/front-end/src/components/ProfileComponent.tsx
+++ b/front-end/src/components/ProfileComponent.tsx
@@ -31,6 +31,7 @@ const Profile: React.FC<ProfileProps> = ({children, className ,user, avatarSize,
 
     useEffect(() => {
         setStatusColor(getEnumNameByIndex(Colors, user.status));
+        return;
     }, [user.login]);
 
     socketChatRef.current?.on("userUpdate", (data: IUser) => {
@@ -41,6 +42,8 @@ const Profile: React.FC<ProfileProps> = ({children, className ,user, avatarSize,
         }
     });
 
+    socketChatRef.current?.off("userUpdate", () => {});
+
     useEffect(() => {
         if (isNicknameUsed && modifiedNick !== user.nickname) {
           setNickErrMsg("Unavailable");
diff --git a/front-end/src/components/StatsComponent.tsx b/front-end/src/components/StatsComponent.tsx
index eb7036d1..e546911b 100644
--- a/front-end/src/components/StatsComponent.tsx
+++ b/front-end/src/components/StatsComponent.tsx
@@ -1,7 +1,8 @@
-import React, {useEffect, useState} from "react";
+import React, {useContext, useEffect, useRef, useState} from "react";
 import {getApi} from "@/components/api/ApiReq";
 import {IGameStats, IUser} from "@/shared/types";
 import getUserStatsById = getApi.getUserStatsById;
+import {SocketContextChat} from "@/context/globalContext";
 
 interface StatsProps {
     user: IUser;
@@ -10,6 +11,8 @@ interface StatsProps {
 const Stats: React.FC<StatsProps> = ({className, user})=>{
 
     const [stats, setStats] = useState<IGameStats>({nbWin:0, level:-1, rank:0, nbLoose:0, exp: 0});
+    const socketChat      = useContext(SocketContextChat);
+    const socketChatRef   = useRef(socketChat);
 
     useEffect(() => {
         if (stats.level < 0)
@@ -17,10 +20,23 @@ const Stats: React.FC<StatsProps> = ({className, user})=>{
                 setStats(result.data);
             })
                 .catch((error) => console.error("Request for STATS failed: " + error));
+        return () => {};
     })
 
+    socketChatRef.current?.on("userUpdate", (data: IUser) => {
+        if (data.UserID == user.UserID && data.status != user.status)
+        {
+            getUserStatsById(user.UserID).then((result) => {
+                setStats(result.data);
+            })
+                .catch((error) => console.error("Request for STATS failed: " + error));
+        }
+    });
+    socketChatRef.current?.off("userUpdate", () => {});
+
+
     return (
-        <div className={className}>
+        <div className={className} style={{marginTop: "1ch"}}>
             <span style={{color: "green", marginInline: "4px", fontFamily: "sans-serif", lineHeight: "1.5em", transition: "1000ms"}}>{" " + stats.nbWin + "🏆  "}</span>
             <span style={{color: "red", marginInline: "4px", fontFamily: "sans-serif", lineHeight: "1.5em", transition: "1000ms"}}>{" " +  stats.nbLoose + " 🏳 "}</span>
             <span style={{color: "gold", marginInline: "4px", fontFamily: "sans-serif", lineHeight: "1.5em", transition: "1000ms"}}>{" " + stats.rank +" 🎖 "}️</span>
diff --git a/front-end/src/components/UserListComponent.tsx b/front-end/src/components/UserListComponent.tsx
index 81a886da..62b164e1 100644
--- a/front-end/src/components/UserListComponent.tsx
+++ b/front-end/src/components/UserListComponent.tsx
@@ -1,4 +1,4 @@
-import React, { use, useEffect, useState} from "react";
+import React, {useEffect, useState} from "react";
 import Profile from "@/components/ProfileComponent";
 import Button from "@/components/CustomButtonComponent";
 import {v4 as uuidv4} from "uuid";
@@ -12,9 +12,9 @@ import { IUser } from "@/shared/types";
 interface UserListProps{
     avatarSize?: string | undefined;
     usersList?: string | undefined;
-    showUserProps?: boolean;
     adminMode?: boolean
     channelID?: number;
+    showUserProps?: boolean;
 }
 const UserList : React.FC<UserListProps> = ({className, id, userListIdProperty, avatarSize, showUserProps, usersList, adminMode, channelID}) => {
 
@@ -44,7 +44,7 @@ const UserList : React.FC<UserListProps> = ({className, id, userListIdProperty,
                 {
                     if (subs.length > 0) {
                         for (const user of subs) {
-                            allDiv = allDivPush(allDiv, user, muteList, subs, blocked, undefined);
+                            allDiv = allDivPush(allDiv, user, muteList, subs, blocked, undefined, true);
                         }
                         for (const user of bannedList) {
                             allDiv = allDivPush(allDiv, user.user, muteList, subs, blocked, user.bannedID);
@@ -78,25 +78,27 @@ const UserList : React.FC<UserListProps> = ({className, id, userListIdProperty,
                 })
                 .catch((error) => console.error("[UserList] Impossible to get relationships of actual user: " + error));
         }
+        return;
     }, [refresh]);
 
     const allDivPush = (
-        allDiv: React.JSX.Element[], 
+        allDiv: React.JSX.Element[],
         user: IUser,
-        muteList: channelsDTO.IMuteEntity[], 
-        follow: IUser[], 
-        blocked: IUser[], 
-        banID?: number) => {
+        muteList: channelsDTO.IMuteEntity[],
+        follow: IUser[],
+        blocked: IUser[],
+        banID?: number,
+        showStats?: boolean) => {
         allDiv.push(
             <li key={user.login + "List" + uuidv4()}>
-                <Profile user={user} avatarSize={avatarSize}>
-                    {showUserProps == true && <UserOptions 
-                    user={user} 
-                    relationships={{followed: follow, blocked:blocked}} 
-                    channelID={channelID} 
-                    showAdminOptions={adminMode} 
+                <Profile user={user} avatarSize={avatarSize} showStats={showStats}>
+                    {showUserProps == true && <UserOptions
+                    user={user}
+                    relationships={{followed: follow, blocked:blocked}}
+                    channelID={channelID}
+                    showAdminOptions={adminMode}
                     setRefresh={setRefresh}
-                    banID={banID} 
+                    banID={banID}
                     muteID={muteList.find(muteUser => muteUser.user.UserID === user.UserID)?.muteID ?? undefined}/>}
                 </Profile>
             </li>

From b1995371284ac4dbc79d53c0012d5ff8319c04ed Mon Sep 17 00:00:00 2001
From: sansho88 <sansho88@hotmail.fr>
Date: Wed, 25 Oct 2023 11:48:39 +0200
Subject: [PATCH 2/4] Creation de la popup pour les userAdminOptions

---
 front-end/src/app/globals.css                 | 15 ++++++++++
 .../src/components/MatchHistoryComponent.tsx  | 13 +++++----
 front-end/src/components/UserOptions.tsx      | 28 ++++++++++++++-----
 front-end/src/shared/routesApi.ts             |  4 +--
 4 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/front-end/src/app/globals.css b/front-end/src/app/globals.css
index 4506815d..6ab87605 100644
--- a/front-end/src/app/globals.css
+++ b/front-end/src/app/globals.css
@@ -429,6 +429,21 @@ body {
     padding-left: 0.4vw;
 }
 
+#adminOptionsSettings{
+    position: absolute;
+    top: 0;
+    right: 0;
+    margin: 0.5em;
+    padding: 0.5em;
+    border-radius: 0.5em;
+    background: rgba(0, 0, 0, 0.27);
+    border: 2px rgba(0, 0, 0, 0.11);
+    border-style: inherit ;
+    box-shadow: 3px 4px 10px  rgba(0, 0, 0, 0.27);
+    border-radius: 8px;
+    z-index: 1;
+}
+
 .game{
     display: inline;
     margin-inline: auto;
diff --git a/front-end/src/components/MatchHistoryComponent.tsx b/front-end/src/components/MatchHistoryComponent.tsx
index 16d3f622..b88b0dac 100644
--- a/front-end/src/components/MatchHistoryComponent.tsx
+++ b/front-end/src/components/MatchHistoryComponent.tsx
@@ -26,27 +26,28 @@ const MatchHistory : React.FC = () => {
                 .then((res) => {
                     setSelectedUserRelationships({followed:res.data.followed, blocked:res.data?.blocked});
                 });
-            const timer = setInterval(() => {
+            /*const timer = setInterval(() => {
                 getApi.getMatchHistoryFromUserId(selectedUserContext.UserID)
                     .then((res) => {
                         setMatchesList(res.data);
                     })
             }, 10000);
-
+*/
             return () => {
-                clearInterval(timer);
+                //clearInterval(timer);
             };
         }
     }, [selectedUserContext])
 
     socketChatRef.current?.on("userUpdate", (data: IUser) => {
         if (selectedUserContext && data.UserID == selectedUserContext.UserID && selectedUserContext.status == EStatus.Online)
-        {
             setSelectedUserContext(data);
-        }
     });
 
-    socketChatRef.current?.off("userUpdate", () => {});
+    socketChatRef.current?.off("userUpdate", (data: IUser) => {
+        if (selectedUserContext && data.UserID == selectedUserContext.UserID && selectedUserContext.status == EStatus.Online)
+            setSelectedUserContext(data);
+    });
 
 
     if (matchesList.length > 0 && matchesList.at(0).ID >= 0){
diff --git a/front-end/src/components/UserOptions.tsx b/front-end/src/components/UserOptions.tsx
index 7e9402d9..d8b3c0f6 100644
--- a/front-end/src/components/UserOptions.tsx
+++ b/front-end/src/components/UserOptions.tsx
@@ -27,6 +27,7 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s
     const [isWaitingChallenge, setIsWaitingChallenge] = useState<boolean>(false);
     const [isDurationVisible, setIsDurationVisible] = useState<boolean>(false);
     const [durType, setDurationType] = useState<typeof DurationType[keyof typeof DurationType]>(DurationType.Ban);
+    const [showPopupAdmin, setShowPopupAdmin] = useState<boolean>(false);
 
     const socketRef = useContext(SocketContextChat)
     const socketRefGame = useContext(SocketContextGame)
@@ -142,6 +143,16 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s
         }
     }
 
+    const adminOptionsSettings = () => {
+
+        return (
+            <div  id={"adminOptionsSettings"} style={{marginTop:"10px"}}>
+                <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/>
+                <Button image={"/door-red.svg"} onClick={() => {handleKick()}} alt={"Kick"} margin={"0 5px 0 0"} title={"Kick"}/>
+                <Button image={`/hammer-${banID === undefined ? "red" : "green"}.svg`} onClick={() => {handleBan()}}  alt={"Ban"} title={`${banID !== undefined && "Un" || ""}Ban`}/>
+            </div>
+        )
+    }
 
     useEffect(() => {
         if (socketRefGame){
@@ -166,19 +177,22 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s
 
                         <Button image={"/send-message.svg"} onClick={handleMp} alt={"Send MP"} title={"MP"}/>
 
-                        {showAdminOptions &&
-                            <span style={{float:"right"}}>
-                                <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/>
-                                <Button image={"/door-red.svg"} onClick={() => {handleKick()}} alt={"Kick"} margin={"0 5px 0 0"} title={"Kick"}/>
-                                <Button image={`/hammer-${banID === undefined ? "red" : "green"}.svg`} onClick={() => {handleBan()}}  alt={"Ban"} title={`${banID !== undefined && "Un" || ""}Ban`}/>
-                            </span>
-                        }
                         { !isWaitingChallenge && user.status != EStatus.Offline &&
                             <>
                                 <Button image={"/sword.svg"} onClick={() => handleChallenge(EGameMod.classic)} alt={"Challenge"} title={"Classic Challenge"}/>
                                 <Button image={"/swordGhost.svg"} onClick={() => handleChallenge(EGameMod.ghost)} alt={"Challenge"} title={"Ghost Challenge"}/>
                             </>
                         }
+
+                        <Button image={"/joystick.svg"} onClick={() => setShowPopupAdmin(!showPopupAdmin)} alt={"Admin window"} title={"Admin window"}/>
+
+                        {showAdminOptions && showPopupAdmin && adminOptionsSettings()}
+                            {/*<span style={{float:"right"}}>
+                                <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/>
+                                <Button image={"/door-red.svg"} onClick={() => {handleKick()}} alt={"Kick"} margin={"0 5px 0 0"} title={"Kick"}/>
+                                <Button image={`/hammer-${banID === undefined ? "red" : "green"}.svg`} onClick={() => {handleBan()}}  alt={"Ban"} title={`${banID !== undefined && "Un" || ""}Ban`}/>
+                            </span>*/}
+
                     </span>
                     {isDurationVisible && <PutDuration 
                     user={user} 
diff --git a/front-end/src/shared/routesApi.ts b/front-end/src/shared/routesApi.ts
index 3ae3002b..d1839a35 100644
--- a/front-end/src/shared/routesApi.ts
+++ b/front-end/src/shared/routesApi.ts
@@ -153,10 +153,10 @@ export namespace strRoutes {
 		return `${serverApi}/${routeUsers}/get/Relationships/${targetId}`
 	}
 	export const getUsersAll = () => {
-		return `${serverApi})${routeUsers}/get/`
+		return `${serverApi}/${routeUsers}/get/`
 	}
 	export const getUserById = () => {
-		return `${serverApi})${routeUsers}/get/`
+		return `${serverApi}/${routeUsers}/get/`
 	}
 	export const getUserByLogin = () => {
 		return `${serverApi}/${routeUsers}/get/`

From 0bd81a54c3d0b1c6a7547f8ca22721e64ab7c425 Mon Sep 17 00:00:00 2001
From: sansho88 <sansho88@hotmail.fr>
Date: Wed, 25 Oct 2023 16:18:34 +0200
Subject: [PATCH 3/4] Les options admin s affichent en dessous et sont cachees
 + console.log removed

---
 front-end/public/slavery-whip.svg             |  2 +
 front-end/src/app/globals.css                 | 35 +++++++++++++---
 .../src/components/UserListComponent.tsx      |  1 -
 front-end/src/components/UserOptions.tsx      | 42 ++++++++-----------
 .../chat/subComponents/PutDuration.tsx        | 20 ++++-----
 5 files changed, 59 insertions(+), 41 deletions(-)
 create mode 100644 front-end/public/slavery-whip.svg

diff --git a/front-end/public/slavery-whip.svg b/front-end/public/slavery-whip.svg
new file mode 100644
index 00000000..a3aacff2
--- /dev/null
+++ b/front-end/public/slavery-whip.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<svg width="21px" height="21px" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg"><path fill="goldenrod" d="M375.04 37.43l-35.083 43.386L314.95 37.92l-4.055 46.084c63.786 18.442 66.642 100.816 27.71 132.69l85.49-13.003-43.322-14.56 77.688-45.347-75.374 3.55 61.728-79.298-78.498 35.002 8.725-65.607zM70.296 58.395c-15.223.03-31.116 5.526-48.545 16.935v47.135c43.16-38.49 90.794-21.734 133.76 24.56 23.57 29.96 48.492 64.923 98.338 78.166 37.686 10.014 77.26-8.695 87.326-45.94 3.85-14.245 4.485-29.96.107-44.334-4.376-14.372-14.476-27.512-30.585-33.684h-.002c-10.558-4.044-22.308-4.223-32.888-.554-10.582 3.668-20.198 11.696-24.35 23.586-2.616 7.492-2.486 15.654.41 23.072 2.897 7.42 9.143 14.25 18.01 16.82h.002c5.33 1.544 10.872 1.284 16.1-.896 4.803-2.004 9.515-6.272 11.41-12.166-11.492 10.304-28.43 5.458-28.97-14.328-.205-2.172.02-4.445.68-6.34v-.002c2.117-6.06 6.64-9.944 12.83-12.09 6.188-2.146 13.84-2.04 20.08.35h.003c10.562 4.046 16.314 11.563 19.394 21.677 3.08 10.116 2.78 22.718-.27 34.015-7.294 26.984-35.235 40.528-64.488 32.756-32.45-8.62-52.41-27.42-70.373-48.985l.15-.223C143.74 93.958 109.2 58.32 70.296 58.395zm228.437 90.863l1.01.576c.027-.112.06-.22.086-.332l-1.096-.244zm157.87 64.904c-17.884-.094-38.857 9.058-55.942 26.143-5.313 5.313-9.848 11.004-13.588 16.86-93.743-56.462-329.905 76.312-178.974 189.757l-.002.002H88.78l-26.452 47.74h257.164l-88.478-103.25c24.27-26.708 67.453-43.706 96.996-45.064 13.793 45.097 36.25 113.497 71.734 148.312h60.867c-43.07-46.548-76.537-109.094-81.936-179.85 1.615 3.23 3.692 6.19 6.283 8.782 18.664 18.663 55.953 11.632 83.29-15.703 27.335-27.335 34.364-64.623 15.7-83.286-7-7-16.615-10.385-27.345-10.442z"/></svg>
\ No newline at end of file
diff --git a/front-end/src/app/globals.css b/front-end/src/app/globals.css
index 6ab87605..a94debc0 100644
--- a/front-end/src/app/globals.css
+++ b/front-end/src/app/globals.css
@@ -195,7 +195,7 @@ body {
 .friends {
   position: absolute;
   top: 5.9px;
-  right: 0vw;
+  right: 0;
   display: flex;
   flex-direction: row;
   align-items: center;
@@ -430,20 +430,43 @@ body {
 }
 
 #adminOptionsSettings{
-    position: absolute;
-    top: 0;
+    position: relative;
+    bottom: 0;
     right: 0;
     margin: 0.5em;
     padding: 0.5em;
-    border-radius: 0.5em;
-    background: rgba(0, 0, 0, 0.27);
+    background: rgba(0, 0, 0, 0.47);
     border: 2px rgba(0, 0, 0, 0.11);
-    border-style: inherit ;
     box-shadow: 3px 4px 10px  rgba(0, 0, 0, 0.27);
     border-radius: 8px;
     z-index: 1;
 }
 
+#muteDuration{
+    position: relative;
+    width: 1vw;
+    bottom: 0;
+    right: 0;
+    margin: 0.5em;
+    padding: 0.5em;
+    background: rgba(0, 0, 0, 0.47);
+    border: 2px rgba(0, 0, 0, 0.11);
+    box-shadow: 3px 4px 10px  rgba(0, 0, 0, 0.27);
+    border-radius: 8px;
+    z-index: 1;
+}
+
+#muteDuration input{
+    background-color: #2d3748;
+    padding: 0.5rem;
+    border-radius: 0.5rem;
+    color: #f56565;
+    height: 1rem;
+    text-align: center;
+    outline:inset;
+    width:42%
+}
+
 .game{
     display: inline;
     margin-inline: auto;
diff --git a/front-end/src/components/UserListComponent.tsx b/front-end/src/components/UserListComponent.tsx
index 9bfdb0c4..77ac9972 100644
--- a/front-end/src/components/UserListComponent.tsx
+++ b/front-end/src/components/UserListComponent.tsx
@@ -130,7 +130,6 @@ const UserList : React.FC<UserListProps> = ({
                         banID={banID}
                         muteID={muteList.find(muteUser => muteUser.user.UserID === user.UserID)?.muteID ?? undefined}
                         adminID={userAdmin?.UserID ?? undefined}
-                        isOwner={isOwner}
                     />}
                 </Profile>
             </li>
diff --git a/front-end/src/components/UserOptions.tsx b/front-end/src/components/UserOptions.tsx
index 44c7bb90..055ca580 100644
--- a/front-end/src/components/UserOptions.tsx
+++ b/front-end/src/components/UserOptions.tsx
@@ -18,11 +18,10 @@ export interface userOptionsProps {
    banID?: number;
    muteID?: number;
    adminID?: number;
-   isOwner?: boolean;
    setRefresh: React.Dispatch<React.SetStateAction<boolean>>;
 }
 
-const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, showAdminOptions, relationships, channelID, setRefresh, banID, muteID, adminID, isOwner}) => {
+const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, showAdminOptions, relationships, channelID, setRefresh, banID, muteID, adminID}) => {
     const {userContext} = useContext(UserContext);
     const [isFollowed, setIsFollowed] = useState(relationships.followed && !!relationships.followed.find(tmpUser => user.UserID === tmpUser.UserID));
     const [isBlocked, setIsBlocked] = useState(relationships.blocked && !!relationships.blocked.find(tmpUser => user.UserID == tmpUser.UserID));
@@ -98,19 +97,19 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s
     }
 
     function handleKick() {
-        if (!showAdminOptions || channelID === undefined) return console.log('NO RIGHTS TO DO THIS ACTION');
+        if (!showAdminOptions || channelID === undefined) return NotificationManager.error(`You can\'t kick ${user.nickname} (${user.login})`);
         apiReq.putApi.putKickUser(channelID, user.UserID)
             .then(() => {
-                console.log('KICK SUCCESS')
+                NotificationManager.success(`You kicked ${user.nickname} (${user.login})`);
                 setRefresh(true);
             })
             .catch(() => {
-                console.log('KICK FAILED')
+                NotificationManager.error(`You can\'t kick ${user.nickname} (${user.login})`);
             })
     }
 
     function handleBan() {
-        if (!showAdminOptions || channelID === undefined) return console.log('NO RIGHTS TO DO THIS ACTION');
+        if (!showAdminOptions || channelID === undefined) return NotificationManager.error(`You can\'t ban ${user.nickname} (${user.login})`);
         if (banID === undefined) {
             setDurationType(DurationType.Ban);
             setIsDurationVisible(!isDurationVisible);
@@ -118,17 +117,17 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s
         else {
             apiReq.putApi.putUnbanUser(banID)
                 .then(() => {
-                    console.log('UNBAN SUCCESS')
+                    NotificationManager.success(`You unbanned ${user.nickname} (${user.login})`);
                     setRefresh(true);
                 })
                 .catch(() => {
-                    console.log('UNBAN FAILED')
+                    NotificationManager.error(`You can\'t unban ${user.nickname} (${user.login})`);
                 })
         }
     }
 
     function handleMute() {
-        if (!showAdminOptions || channelID === undefined) return console.log('NO RIGHTS TO DO THIS ACTION');
+        if (!showAdminOptions || channelID === undefined) return NotificationManager.error(`You can\'t mute ${user.nickname} (${user.login})`);
         if (muteID === undefined) {
             setDurationType(DurationType.Mute);
             setIsDurationVisible(!isDurationVisible);
@@ -136,17 +135,16 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s
         else {
             apiReq.putApi.putUnmuteUser(muteID ? muteID : -1)
                 .then(() => {
-                    console.log('UNMUTE SUCCESS')
+                    NotificationManager.success(`You unmuted ${user.nickname} (${user.login})`);
                     setRefresh(true);
                 })
                 .catch(() => {
-                    console.log('UNMUTE FAILED')
+                   NotificationManager.error(`You can\'t unmute ${user.nickname} (${user.login})`);
                 })
         }
     }
 
     const adminOptionsSettings = () => {
-
         return (
             <div  id={"adminOptionsSettings"} style={{marginTop:"10px"}}>
                 <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/>
@@ -157,25 +155,25 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s
         )
     }
     function handleGrant() {
-        if (!showAdminOptions || channelID === undefined) return console.log('NO RIGHTS TO DO THIS ACTION');
+        if (!showAdminOptions || channelID === undefined) return NotificationManager.error(`You can\'t grant ${user.nickname} (${user.login})`);
         if (adminID === undefined) {
             apiReq.putApi.putGrantAdmin(channelID, user.UserID)
                 .then(() => {
-                    console.log('GRANT SUCCESS')
+                    NotificationManager.success(`You granted ${user.nickname} (${user.login})`);
                     setRefresh(true);
                 })
                 .catch(() => {
-                    console.log('GRANT FAILED')
+                    NotificationManager.error(`You can\'t grant ${user.nickname} (${user.login})`);
                 })
         }
         else {
             apiReq.putApi.putRevokeAdmin(channelID, user.UserID) //adminID === user.UserID
                 .then(() => {
-                    console.log('REVOKE SUCCESS')
+                    NotificationManager.success(`You revoked ${user.nickname} (${user.login})`);
                     setRefresh(true);
                 })
                 .catch(() => {
-                    console.log('REVOKE FAILED')
+                    NotificationManager.error(`You can\'t revoke ${user.nickname} (${user.login})`);
                 })
         }
     }
@@ -211,21 +209,17 @@ const UserOptions: React.FC<userOptionsProps> = ({classname, idProperty, user, s
                             </>
                         }
 
-                        <Button image={"/joystick.svg"} onClick={() => setShowPopupAdmin(!showPopupAdmin)} alt={"Admin window"} title={"Admin window"}/>
+                        {showAdminOptions && <Button image={"/slavery-whip.svg"} onClick={() => setShowPopupAdmin(!showPopupAdmin)} alt={"Admin window"} title={"Admin window"}/>}
 
                         {showAdminOptions && showPopupAdmin && adminOptionsSettings()}
-                            {/*<span style={{float:"right"}}>
-                                <Button image={`/block-message-${muteID === undefined ? "red" : "green"}.svg`} onClick={() => {handleMute()}} alt={"Mute"} margin={"0 5px 0 0"} title={`${muteID != undefined && "Un" || ""}Mute`}/>
-                                <Button image={"/door-red.svg"} onClick={() => {handleKick()}} alt={"Kick"} margin={"0 5px 0 0"} title={"Kick"}/>
-                                <Button image={`/hammer-${banID === undefined ? "red" : "green"}.svg`} onClick={() => {handleBan()}}  alt={"Ban"} title={`${banID !== undefined && "Un" || ""}Ban`}/>
-                            </span>*/}
+
 
                     </span>
                     {isDurationVisible && <PutDuration 
                     user={user} 
                     channelID={channelID} 
                     handleType={durType} 
-                    isVisible={isDurationVisible}
+                    isVisible={isDurationVisible && showPopupAdmin}
                     setDurationType={setDurationType}
                     setIsDurationVisible={setIsDurationVisible}
                     setRefresh={setRefresh}
diff --git a/front-end/src/components/chat/subComponents/PutDuration.tsx b/front-end/src/components/chat/subComponents/PutDuration.tsx
index f8304250..e2224409 100644
--- a/front-end/src/components/chat/subComponents/PutDuration.tsx
+++ b/front-end/src/components/chat/subComponents/PutDuration.tsx
@@ -2,8 +2,9 @@ import { IUser } from "@/shared/types";
 import Image from "next/image";
 import * as apiReq from '@/components/api/ApiReq'
 import React, { useState } from "react";
-import { text } from "stream/consumers";
 import { inherits } from "util";
+import {NotificationManager} from 'react-notifications';
+
 
 export const DurationType = {
 	none: 0,
@@ -37,21 +38,21 @@ const PutDuration: React.FC<PutDurationProps> = ({ user, channelID, handleType,
 		if (handleType === DurationType.Ban) {
 			apiReq.putApi.putBanUser(channelID, user.UserID, duration * 60)
 				.then(() => {
-					console.log('BAN SUCCESS')
+					NotificationManager.success(`You banned ${user.nickname} (${user.login}) for ${duration} minutes.`);
 					setRefresh(true);
 				})
 				.catch(() => {
-					console.log('BAN FAILED')
+					NotificationManager.error(`You can\'t ban ${user.nickname} (${user.login})`);
 				})
 			}
 			else if (handleType === DurationType.Mute) {
 				apiReq.putApi.putMuteUser(channelID, user.UserID, duration* 60)
 				.then(() => {
-					console.log('MUTE SUCCESS')
+					NotificationManager.success(`You muted ${user.nickname} (${user.login}) for ${duration} minutes.`);
 					setRefresh(true);
 				})
 				.catch(() => {
-					console.log('MUTE FAILED')
+					NotificationManager.error(`You can\'t mute ${user.nickname} (${user.login})`);
 				})
 		}
 		setDurationType(DurationType.none);
@@ -59,17 +60,16 @@ const PutDuration: React.FC<PutDurationProps> = ({ user, channelID, handleType,
 	}
 
 	return (
-		<div>
+		<>
 			{isVisible && (
-				<div className="flex flex-col justify-center items-center text-white" style={{minWidth:"fit-content"}}>
-					<label htmlFor="duration">Duration (in minutes)<h6>0 for infinit</h6></label>
+				<div id="muteDuration" style={{minWidth:"fit-content"}}>
+					<label htmlFor="duration">Duration (in minutes)<h6>0 for infinite</h6></label>
 					<input
 						type="number"
 						name="duration"
 						id="duration"
 						placeholder="duration in minutes"
 						value={duration}
-						style={{backgroundColor: "#2d3748", padding: "0.5rem", borderRadius: "0.5rem", color: "#f56565", height: "1rem", textAlign: "center", outline:"inset", width:"100%"}}
 						onChange={(e) => changeDuration(e)}
 					/>
 					{isVisible && (<button onClick={handleDuration} style={{ verticalAlign: "-webkit-baseline-middle" }}>
@@ -83,7 +83,7 @@ const PutDuration: React.FC<PutDurationProps> = ({ user, channelID, handleType,
 					</button>)}
 				</div>
 			)}
-		</div>
+		</>
 	);
 }
 

From 233b56e1ca70dc94f48804fac46debf715fcc9bb Mon Sep 17 00:00:00 2001
From: sansho88 <sansho88@hotmail.fr>
Date: Wed, 25 Oct 2023 16:23:49 +0200
Subject: [PATCH 4/4] SUPPRESSION DE LA NAVBAR (RIP)

---
 front-end/src/app/layout.tsx                  |   2 -
 .../(ben_proto)/DevTools/NavBarDev.tsx        | 146 ------------------
 2 files changed, 148 deletions(-)
 delete mode 100644 front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx

diff --git a/front-end/src/app/layout.tsx b/front-end/src/app/layout.tsx
index e035accf..8c1f1834 100644
--- a/front-end/src/app/layout.tsx
+++ b/front-end/src/app/layout.tsx
@@ -1,5 +1,4 @@
 import { Providers } from "@/context/providers";
-import { NavBar } from '@/components/(ben_proto)/DevTools/NavBarDev'
 import './globals.css'
 import { Inter } from 'next/font/google'
 
@@ -24,7 +23,6 @@ export default function RootLayout({
 				{/* <div className='main-background'> */}
 					<Providers>
 						{children}
-            <NavBar className='absolute bottom-0 right-0 w-screen bg-slate-800' />
 					</Providers>
 				</div>
 			</body>
diff --git a/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx b/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx
deleted file mode 100644
index 96449e49..00000000
--- a/front-end/src/components/(ben_proto)/DevTools/NavBarDev.tsx
+++ /dev/null
@@ -1,146 +0,0 @@
-'use client'
-import Link from 'next/link'
-import React, {useState, useContext, useEffect, } from 'react'
-import {UserContext, LoggedContext} from "@/context/globalContext";
-import * as apiReq from '@/components/api/ApiReq'
-
-
-
-export function NavBar({className}: {className: string}) {
-
-	const {userContext} = useContext(UserContext);
-	const {logged, setLogged} = useContext(LoggedContext);
-	const [isHovered, setIsHovered] = useState(false);
-  const [turnOffAuth, setTurnOffAuth] = useState<boolean>(false);
-  // const [isHovered, setIsHovered] = useState(false);
-
-	const [infoUser, setInfoUser] = useState<JSX.Element>(<></>)
-
-  useEffect(() => {
-	  setInfoUser(
-	  <div className='flex'>id:
-	  <div className=' text-red-700'>{userContext?.UserID}</div>
-	|
-	  <div className=' text-green-700'>{userContext?.login}</div>
-	|
-	  <div className=' text-violet-700'>{userContext?.nickname}</div>
-  </div>)
-      return;
-  }, [userContext])
-
-
-  const handleMouseEnter = () => {
-      setIsHovered(true);
-  }
-
-  const handleMouseLeave = () => {
-      setIsHovered(false);
-  }
-
-
-  function Dropdown() {
-    const [isOpen, setIsOpen] = useState(false);
-
-    return (
-        <div className="relative inline-block text-left">
-            <div>
-                <button type="button" 
-                        className="inline-flex justify-center w-full rounded-md border border-gray-300 shadow-sm px-4 py-2 text-sm font-medium text-red-500 
-                        hover: focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-indigo-500" 
-                        id="options-menu" 
-                        aria-haspopup="true" 
-                        aria-expanded="true" 
-                        onClick={() => setIsOpen(!isOpen)}>
-                    EasyReqSQL
-                    <svg className="-mr-1 ml-2 h-5 w-5" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
-                        <path fillRule="evenodd" d="M5 5a1 1 0 011.707-.707l4.586 4.586a1 1 0 010 1.414l-4.586 4.586A1 1 0 015 14V5z" clipRule="evenodd" />
-                    </svg>
-                </button>
-            </div>
-            {isOpen && (
-                <div className="origin-bottom-right absolute right-0 bottom-full w-50 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5">
-                    <div className="py-1" role="menu" aria-orientation="vertical" aria-labelledby="options-menu">
-                        <button onClick={() => apiReq.deleteApi.deleteUsersAll()} className="block px-4 py-2 text-sm text-red-500 hover:bg-gray-100 hover:text-red-900" role="menuitem">DELETE ALL USERS</button>
-                    </div>
-                </div>
-            )}
-        </div>
-    );
-}
-
-
-
-
-function toggleAuthRequired() {
-  if (turnOffAuth)
-  {
-    setLogged(false);
-    setTurnOffAuth(false);
-  }
-  else
-  {
-    setLogged(true);
-    setTurnOffAuth(true);
-  }
-}
-
-	function SubNav() {
-
-		return (
-			<>
-				{/* <Link href="/home">HOME</Link> */}
-				{/* <Link href="/chat">CHAT v2</Link> */}
-				{/* <Link href="/proto/chat">CHATROOM</Link> */}
-				{/* <Link href={`/profile/${userContext?.login}`}>PROFILE</Link> */}
-				{/* <Link href="/auth">AUTH</Link> */}
-        {/* <Dropdown/> */}
-				{infoUser}
-				{/* <button onClick={() => {setLogged(false);localStorage.removeItem("login");}}> DISCONNECT </button> */}
-			</>
-		)
-	}
-  
-  
-	function SubNavNotLog() {
-    
-    return (
-			<>
-				{/* <Link href="/">HOME</Link> */}
-				{/* <Link href="/auth">AUTH LOGIN</Link> */}
-      <Dropdown/>
-        {/* <button onClick={toggleAuthRequired} >{turnOffAuth ? <>ON</> : <>OFF</>}</button> */}
-				{/* <Link href="/login">OLD LOGIN</Link> */}
-				<div className=' text-red-500'>user:(not logged)</div>
-			</>
-		)
-	}
-
-	
-	return (
-		<>
-    <div 
-            onMouseEnter={handleMouseEnter} 
-            onMouseLeave={handleMouseLeave}
-        >
-			{!isHovered ? (
-					<div className='absolute bottom-0 left-[48vw] w-auto rounded-t-xl  px-2 bg-slate-800 opacity-40'>
-						<div className="h-10 flex justify-center items-center space-x-10">
-							<button onClick={() => setIsHovered(false)} className=' text-white'> devbar </button>
-						</div>
-					</div>
-			) : (
-				<div className={className}>
-					<div className=" text-white h-10 flex justify-center items-center space-x-10">
-						<div className=" text-red-600 absolute left-5">Navbar Dev </div>
-						{logged ? <SubNav /> : 
-            // <SubNavNotLog />
-            <SubNav />
-            }
-						<button onClick={() => setIsHovered(false)}> ❌ </button>
-					</div>
-				</div>
-			)}
-      </div>
-		</>
-	);
-}
\ No newline at end of file