From 3770dd4f99e4f194c0a81bc9247131bed76d538e Mon Sep 17 00:00:00 2001 From: Quentin Roussel Date: Fri, 29 Mar 2024 12:38:12 +0100 Subject: [PATCH 1/4] Interface d'attente + logout --- traque-front/app/team/track/page.js | 13 +++++------ traque-front/components/team/actionDrawer.jsx | 5 ++++- traque-front/components/team/map.jsx | 2 +- .../components/team/placementOverlay.jsx | 19 ++++++++++++++++ .../components/team/waitingScreen.jsx | 21 ++++++++++++++++++ traque-front/context/teamConnexionContext.jsx | 4 ++-- traque-front/hook/useSocketAuth.jsx | 12 +++++++++- traque-front/public/icons/logout.png | Bin 0 -> 1785 bytes 8 files changed, 63 insertions(+), 13 deletions(-) create mode 100644 traque-front/components/team/placementOverlay.jsx create mode 100644 traque-front/components/team/waitingScreen.jsx create mode 100644 traque-front/public/icons/logout.png diff --git a/traque-front/app/team/track/page.js b/traque-front/app/team/track/page.js index fb16cbd..7e133d5 100644 --- a/traque-front/app/team/track/page.js +++ b/traque-front/app/team/track/page.js @@ -1,5 +1,7 @@ "use client"; import ActionDrawer from '@/components/team/actionDrawer'; +import PlacementOverlay from '@/components/team/placementOverlay'; +import { WaitingScreen } from '@/components/team/waitingScreen'; import { useTeamConnexion } from '@/context/teamConnexionContext'; import useGame from '@/hook/useGame'; import { GameState } from '@/util/gameState'; @@ -15,10 +17,11 @@ const PlacementMap = dynamic(() => import('@/components/team/map').then((mod) => }); export default function Track() { - const { gameState, name, ready } = useGame(); + const { gameState} = useGame(); const { useProtect } = useTeamConnexion(); useProtect(); return <> + {gameState == GameState.SETUP && } {gameState == GameState.PLAYING &&
@@ -26,13 +29,7 @@ export default function Track() { } {gameState == GameState.PLACEMENT &&
-
-
Placement
-
{name}
- {!ready &&
Positionez vous dans le cercle
} - {ready &&
Restez dans le cercle en attendant que la partie commence
} - -
+
} diff --git a/traque-front/components/team/actionDrawer.jsx b/traque-front/components/team/actionDrawer.jsx index f9e095e..349ddab 100644 --- a/traque-front/components/team/actionDrawer.jsx +++ b/traque-front/components/team/actionDrawer.jsx @@ -5,13 +5,16 @@ import TextInput from "../util/textInput"; export default function ActionDrawer() { const [visible, setVisible] = useState(false); - const { sendCurrentPosition } = useGame(); + const { sendCurrentPosition, name } = useGame(); return (
setVisible(!visible)} /> {visible &&
+
+ {name} +
30min before penalty diff --git a/traque-front/components/team/map.jsx b/traque-front/components/team/map.jsx index fab937e..725e5d5 100644 --- a/traque-front/components/team/map.jsx +++ b/traque-front/components/team/map.jsx @@ -82,7 +82,7 @@ export function PlacementMap({ ...props}) { } - + {startingArea && } ) } diff --git a/traque-front/components/team/placementOverlay.jsx b/traque-front/components/team/placementOverlay.jsx new file mode 100644 index 0000000..c4bb5a6 --- /dev/null +++ b/traque-front/components/team/placementOverlay.jsx @@ -0,0 +1,19 @@ +import { useTeamConnexion } from "@/context/teamConnexionContext"; +import useGame from "@/hook/useGame" + +export default function PlacementOverlay() { + const { name, ready } = useGame(); + const {logout} = useTeamConnexion(); + return ( + <> + +
+
Placement
+
{name}
+ {!ready &&
Positionez vous dans le cercle
} + {ready &&
Restez dans le cercle en attendant que la partie commence
} + +
+ + ) +} \ No newline at end of file diff --git a/traque-front/components/team/waitingScreen.jsx b/traque-front/components/team/waitingScreen.jsx new file mode 100644 index 0000000..9d534f7 --- /dev/null +++ b/traque-front/components/team/waitingScreen.jsx @@ -0,0 +1,21 @@ +import { useTeamConnexion } from "@/context/teamConnexionContext"; +import useGame from "@/hook/useGame" + +export function WaitingScreen() { + const { name } = useGame(); + const { logout } = useTeamConnexion(); + return ( +
+
+ Equipe : {name} +
+
+ Jeu en préparation, veuillez patienter... +
+
+ Vous avez perdu Le Jeu +
+ +
+ ) +} \ No newline at end of file diff --git a/traque-front/context/teamConnexionContext.jsx b/traque-front/context/teamConnexionContext.jsx index 9b82f24..4f0ae3e 100644 --- a/traque-front/context/teamConnexionContext.jsx +++ b/traque-front/context/teamConnexionContext.jsx @@ -7,10 +7,10 @@ import { usePasswordProtect } from "@/hook/usePasswordProtect"; const teamConnexionContext = createContext(); const TeamConnexionProvider = ({ children }) => { const { teamSocket } = useSocket(); - const { login, password: teamId, loggedIn, loading } = useSocketAuth(teamSocket, "team_password"); + const { login, password: teamId, loggedIn, loading, logout } = useSocketAuth(teamSocket, "team_password"); const useProtect = () => usePasswordProtect("/team", "/team/track", loading, loggedIn); - const value = useMemo(() => ({ teamId, login, loggedIn, loading, useProtect}), [teamId, login, loggedIn, loading]); + const value = useMemo(() => ({ teamId, login, logout, loggedIn, loading, useProtect}), [teamId, login, loggedIn, loading]); return ( diff --git a/traque-front/hook/useSocketAuth.jsx b/traque-front/hook/useSocketAuth.jsx index 7f4bfdb..b17a2f5 100644 --- a/traque-front/hook/useSocketAuth.jsx +++ b/traque-front/hook/useSocketAuth.jsx @@ -4,6 +4,7 @@ import { useLocalStorage } from './useLocalStorage'; import { usePathname } from 'next/navigation'; const LOGIN_MESSAGE = "login"; +const LOGOUT_MESSAGE = "logout"; const LOGIN_RESPONSE_MESSAGE = "login_response"; export function useSocketAuth(socket, passwordName) { @@ -13,15 +14,24 @@ export function useSocketAuth(socket, passwordName) { const [savedPassword, setSavedPassword, savedPasswordLoading] = useLocalStorage(passwordName, null); useEffect(() => { + console.log("Checking saved password", savedPassword, loggedIn); if (savedPassword && !loggedIn) { + console.log("Logging in with saved password", savedPassword); socket.emit(LOGIN_MESSAGE, savedPassword); } }, [savedPassword]); function login(password) { + console.log("Logging", password); setSavedPassword(password) } + function logout() { + setSavedPassword(null); + setLoggedIn(false); + socket.emit(LOGOUT_MESSAGE) + } + useSocketListener(socket, LOGIN_RESPONSE_MESSAGE,(loginResponse) => { setWaitingForResponse(false); setLoggedIn(loginResponse); @@ -39,5 +49,5 @@ export function useSocketAuth(socket, passwordName) { }, [waitingForResponse, savedPasswordLoading, savedPassword]); - return {login,password: savedPassword, loggedIn, loading}; + return {login,logout,password: savedPassword, loggedIn, loading}; } \ No newline at end of file diff --git a/traque-front/public/icons/logout.png b/traque-front/public/icons/logout.png new file mode 100644 index 0000000000000000000000000000000000000000..38c0cfd96704026e96dc1385beefd055cd0042bd GIT binary patch literal 1785 zcmZvdc~p~E8i((fjS#kkEeH|PNC*NF7Z^SSB|#7Z3Sm=$;6RHOib`btCL>6tS#XU=)=d4BhO|9jqh&Mn{v z_~?<$NdN#np08Ih02ocg00^r=Z^O<;4WQ&;A5Z8>w?mHRqAm0dPX<80{m%oPv)8xK zGzt7&q23yLy_{Ci$O`leShpsM-tEVrM6gh{W?A2P*qPh{kI9o@G%f>D^Y{!l+ zjo_B%8VGT|!b7765W>wsF1BwwzLa`;WIFDX6e83D6aIZo6Ox(t2*A)@$Z#IcBR-x_84k%UcOxP5nrscal!qV|3y z`8;deq#Dzgtj`8>4|N`Iy;@Nug!;CPTJ(K+=eNtZ{9is$F=hVZDCo$k`6wvLrXHRD zMwqE|Usj`a%^83Y{a>YT<*`Y*{1MH^589q3T^GJy8Nw_nfoS5eIUMMO{mlY_tR*rv%M-fzRUxQlh=d&>q}hFp2i!L(l0Z8v`$*AxonY8RjI>PWc`Y z`AKp{7aEMK-J2#o1I<0ug4vzt-gjokKb13lC&a(7*LxN3wEgkY6eu5T(4kxn8oJ}^ zpa<8$fydAryyL_N{Pg(a#0(Byv^ipI<%~aN7Ukr*)5+YjZw`3~EK9X;jAu|TvGv*y zRBqY3ZP!-!7t%o%1&6XlK`BG4w#3wyJ;*xl=T26XDce#h`*{s5IhY5JucM#|NjUlE@$$#R>hl9djjxi-j4I zn3zBP{H5uCP<0=>6ZhWH|3PtSfgdH7vtFcY>s<_05;x0?xrEQ(3tGc3l(DI%j49L; zx0WxFVM&w}&Ig{l@UcO8ZD&53_F=bs7&LQJ8kR@y>n+&lO@w|3kr$9LLu<5ah!pzS z)55*j*z1|56b8q}_2YkXa9!4uJt6qw?%HrKg*p9fS{Z4pw$b;&>Tz7It7@H) zEe4|jc`i=l8^Vx~(ywxHGK*pLz}A*VgG6?_1?`Qge@l1&BM#K}SshZdVf1Cuw-yt6 zKO*;?N8ipQ(81K*^p<(c#FfrzEf~Ul6|J%^=7`+^tFSwjBPgx;sO2{j_T{x5ybpns-{Qh!JMAf950}$+AAFhh8U;xKW9YunRrbZSU z9B-V%A=G%hD)=MC<0lJW51Q^h*~Xj{{^TY|GoY?CADi(MWN*sc($oJ4D2O(WZ3Q~H zKL=k`nAtgY7V5Oxcq*8EF==N;fx=NT>f1EEgeW&i*H literal 0 HcmV?d00001 From ed2e324a454991f183931e059f1fa0f29c0b5311 Mon Sep 17 00:00:00 2001 From: Quentin Roussel Date: Fri, 29 Mar 2024 13:42:48 +0100 Subject: [PATCH 2/4] improved style when overflow --- traque-front/app/admin/layout.js | 6 +++--- traque-front/app/admin/page.js | 6 ++++-- traque-front/app/admin/teams/page.js | 2 +- traque-front/components/admin/teamList.jsx | 2 +- traque-front/components/admin/teamReady.jsx | 16 ++++++++++++++++ 5 files changed, 25 insertions(+), 7 deletions(-) create mode 100644 traque-front/components/admin/teamReady.jsx diff --git a/traque-front/app/admin/layout.js b/traque-front/app/admin/layout.js index 0463940..a951f13 100644 --- a/traque-front/app/admin/layout.js +++ b/traque-front/app/admin/layout.js @@ -6,8 +6,8 @@ export default function AdminLayout({ children}) { return ( -
-
+
+
Admin
  • Home
  • @@ -15,7 +15,7 @@ export default function AdminLayout({ children}) {
  • Map
-
+
{children}
diff --git a/traque-front/app/admin/page.js b/traque-front/app/admin/page.js index c8c7e5d..dbb81a6 100644 --- a/traque-front/app/admin/page.js +++ b/traque-front/app/admin/page.js @@ -1,4 +1,5 @@ "use client"; +import { TeamReady } from "@/components/admin/teamReady"; import BlueButton, { GreenButton, RedButton } from "@/components/util/button"; import { useAdminConnexion } from "@/context/adminConnexionContext"; import useAdmin from "@/hook/useAdmin"; @@ -9,14 +10,15 @@ export default function AdminPage() { const { gameState, changeState } = useAdmin(); useProtect(); return ( -
-
+
+

Game state

Current : {gameState} changeState(GameState.SETUP)}>Reset game changeState(GameState.PLACEMENT)}>Start placement changeState(GameState.PLAYING)}>Start game
+ {gameState == GameState.PLACEMENT &&
}
) } \ No newline at end of file diff --git a/traque-front/app/admin/teams/page.js b/traque-front/app/admin/teams/page.js index 0b6db60..8e1bd12 100644 --- a/traque-front/app/admin/teams/page.js +++ b/traque-front/app/admin/teams/page.js @@ -15,7 +15,7 @@ export default function TeamAdminPage() { return (
-
+

Team list

diff --git a/traque-front/components/admin/teamList.jsx b/traque-front/components/admin/teamList.jsx index 85e828a..d6fd196 100644 --- a/traque-front/components/admin/teamList.jsx +++ b/traque-front/components/admin/teamList.jsx @@ -12,7 +12,7 @@ const reorder = (list, startIndex, endIndex) => { }; function TeamListItem({ team, index, onSelected, itemSelected }) { - const classNames = 'w-full p-3 m-3 shadow ' + (itemSelected ? "bg-blue-400" : "bg-gray-100"); + const classNames = 'w-full p-3 my-3 shadow ' + (itemSelected ? "bg-blue-400" : "bg-gray-100"); return ( onSelected(team.id)}> {provided => ( diff --git a/traque-front/components/admin/teamReady.jsx b/traque-front/components/admin/teamReady.jsx new file mode 100644 index 0000000..21eb6d3 --- /dev/null +++ b/traque-front/components/admin/teamReady.jsx @@ -0,0 +1,16 @@ +import useAdmin from "@/hook/useAdmin" + +export function TeamReady() { + const {teams} = useAdmin(); + return
+

Teams ready status

+ {teams.map((team) => team.ready ? ( +
+
{team.name} : Ready
+
) : ( +
+
{team.name} : Not ready
+
+ ))} +
+} \ No newline at end of file From 198acdc699bdae49c0c8ea12eed6c8de3b598adc Mon Sep 17 00:00:00 2001 From: Quentin Roussel Date: Fri, 29 Mar 2024 16:01:03 +0100 Subject: [PATCH 3/4] cahnged design drawer improved map drawing tool --- traque-front/components/admin/mapPicker.jsx | 45 ++++++++----------- traque-front/components/admin/teamEdit.jsx | 6 ++- traque-front/components/admin/teamList.jsx | 11 ++++- traque-front/components/team/actionDrawer.jsx | 38 +++++++++------- traque-front/hook/mapDrawing.jsx | 37 +++++++++++++++ 5 files changed, 90 insertions(+), 47 deletions(-) create mode 100644 traque-front/hook/mapDrawing.jsx diff --git a/traque-front/components/admin/mapPicker.jsx b/traque-front/components/admin/mapPicker.jsx index f6aa757..a265f1d 100644 --- a/traque-front/components/admin/mapPicker.jsx +++ b/traque-front/components/admin/mapPicker.jsx @@ -3,6 +3,7 @@ import { useLocation } from "@/hook/useLocation"; import { use, useEffect, useState } from "react"; import "leaflet/dist/leaflet.css"; import { Circle, MapContainer, TileLayer, useMap } from "react-leaflet"; +import { useMapCircleDraw } from "@/hook/mapDrawing"; function MapPan(props) { const map = useMap(); @@ -34,36 +35,26 @@ function MapEventListener({onClick, onMouseMove}) { return null; } +const DEFAULT_ZOOM = 17; export function CircularAreaPicker({area, setArea, ...props}) { - const DEFAULT_ZOOM = 17; const location = useLocation(Infinity); - const [drawing, setDrawing] = useState(false); - const [center, setCenter] = useState(area?.center || null); - const [radius, setRadius] = useState(area?.radius || null); + const {handleClick, handleMouseMove, center, radius} = useMapCircleDraw(area, setArea); + return ( + + + {center && radius && } + + + ) +} - useEffect(() => { - console.log(area) - setDrawing(false); - setCenter(area?.center || null); - setRadius(area?.radius || null); - }, [area]) - - function handleClick(e) { - if(!drawing) { - setCenter(e.latlng); - setRadius(null); - setDrawing(true); - } else { - setDrawing(false); - setArea({center, radius}); - } - } - - function handleMouseMove(e) { - if(drawing) { - setRadius(e.latlng.distanceTo(center)); - } - } +export function ZonePicker({minArea, setMinArea, maxArea, setMaxArea, ...props}) { + const location = useLocation(Infinity); + const {handleClick: maxClick, handleMouseMove: maxHover, center: maxCenter, radius: maxRadius} = useMapCircleDraw(minArea, setMinArea); + const {handleClick: minClick, handleMouseMove: minHover, center: minCenter, radius: minRadius} = useMapCircleDraw(maxArea, setMaxArea); return ( Rename
- Remove + updateTeam(team.id, {captured: !team.captured})}>{team.captured ? "Revive" : "Capture"} + Remove

Team details

@@ -55,6 +56,7 @@ export default function TeamEdit({ selectedTeamId, setSelectedTeamId }) {

Chasing : {getTeamName(team.chasing)}

Chased by : {getTeamName(team.chased)}

Capture code : {String(team.captureCode).padStart(4, '0')}

+

Captured : {team.captured ? "Yes" : "No"}

diff --git a/traque-front/components/admin/teamList.jsx b/traque-front/components/admin/teamList.jsx index d6fd196..ee6ee41 100644 --- a/traque-front/components/admin/teamList.jsx +++ b/traque-front/components/admin/teamList.jsx @@ -12,7 +12,16 @@ const reorder = (list, startIndex, endIndex) => { }; function TeamListItem({ team, index, onSelected, itemSelected }) { - const classNames = 'w-full p-3 my-3 shadow ' + (itemSelected ? "bg-blue-400" : "bg-gray-100"); + let bgColor; + if(itemSelected) { + bgColor = "bg-blue-400"; + }else if(team.captured) { + bgColor = "bg-red-400"; + } + else { + bgColor = "bg-gray-100"; + } + const classNames = 'w-full p-3 my-3 shadow ' + (bgColor); return ( onSelected(team.id)}> {provided => ( diff --git a/traque-front/components/team/actionDrawer.jsx b/traque-front/components/team/actionDrawer.jsx index 349ddab..17610e7 100644 --- a/traque-front/components/team/actionDrawer.jsx +++ b/traque-front/components/team/actionDrawer.jsx @@ -2,18 +2,27 @@ import useGame from "@/hook/useGame"; import { useState } from "react" import BlueButton, { GreenButton, RedButton } from "../util/button"; import TextInput from "../util/textInput"; +import { useTeamConnexion } from "@/context/teamConnexionContext"; export default function ActionDrawer() { const [visible, setVisible] = useState(false); - const { sendCurrentPosition, name } = useGame(); + const { sendCurrentPosition, name, captureCode } = useGame(); + const {logout} = useTeamConnexion(); return ( -
+
setVisible(!visible)} /> - {visible &&
-
+ {visible &&
+
+ +
+
- {name} + {name} +
+
+ Capture code + {captureCode}
30min @@ -25,27 +34,22 @@ export default function ActionDrawer() {
-
+
Update position
-
- Message log -
-
- See target info -
-
+
+
Target
+
+ See target info +
{ console.log(i) }} /> Capture target
-
+
Signal emergency
-
- Log out -
}
diff --git a/traque-front/hook/mapDrawing.jsx b/traque-front/hook/mapDrawing.jsx new file mode 100644 index 0000000..f354905 --- /dev/null +++ b/traque-front/hook/mapDrawing.jsx @@ -0,0 +1,37 @@ +import { useEffect, useState } from "react"; +import { useLocation } from "./useLocation"; + +export function useMapCircleDraw(area, setArea) { + const [drawing, setDrawing] = useState(false); + const [center, setCenter] = useState(area?.center || null); + const [radius, setRadius] = useState(area?.radius || null); + + useEffect(() => { + setDrawing(false); + setCenter(area?.center || null); + setRadius(area?.radius || null); + }, [area]) + + function handleClick(e) { + if(!drawing) { + setCenter(e.latlng); + setRadius(null); + setDrawing(true); + } else { + setDrawing(false); + setArea({center, radius}); + } + } + + function handleMouseMove(e) { + if(drawing) { + setRadius(e.latlng.distanceTo(center)); + } + } + return { + handleClick, + handleMouseMove, + center, + radius, + } +} \ No newline at end of file From 3d6e469e5afb007522d156effa23bb57f226ed9c Mon Sep 17 00:00:00 2001 From: Quentin Roussel Date: Fri, 29 Mar 2024 16:48:41 +0100 Subject: [PATCH 4/4] front end elimination --- traque-front/app/team/track/page.js | 8 ++++++-- traque-front/components/team/actionDrawer.jsx | 12 +++++++++--- traque-front/hook/useGame.jsx | 7 +++++-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/traque-front/app/team/track/page.js b/traque-front/app/team/track/page.js index 7e133d5..d7a6db1 100644 --- a/traque-front/app/team/track/page.js +++ b/traque-front/app/team/track/page.js @@ -17,16 +17,20 @@ const PlacementMap = dynamic(() => import('@/components/team/map').then((mod) => }); export default function Track() { - const { gameState} = useGame(); + const { gameState, captured} = useGame(); const { useProtect } = useTeamConnexion(); useProtect(); return <> {gameState == GameState.SETUP && } - {gameState == GameState.PLAYING &&
+ {gameState == GameState.PLAYING && !captured &&
} + {gameState == GameState.PLAYING && captured &&
+
Vous avez été capturé
+
Instructions de retour ici
+
} {gameState == GameState.PLACEMENT &&
diff --git a/traque-front/components/team/actionDrawer.jsx b/traque-front/components/team/actionDrawer.jsx index 17610e7..fe9dfce 100644 --- a/traque-front/components/team/actionDrawer.jsx +++ b/traque-front/components/team/actionDrawer.jsx @@ -6,9 +6,15 @@ import { useTeamConnexion } from "@/context/teamConnexionContext"; export default function ActionDrawer() { const [visible, setVisible] = useState(false); - const { sendCurrentPosition, name, captureCode } = useGame(); + const [enemyCaptureCode, setEnemyCaptureCode] = useState(""); + const { sendCurrentPosition, name, captureCode, capture } = useGame(); const {logout} = useTeamConnexion(); + function handleCapture() { + capture(enemyCaptureCode); + setEnemyCaptureCode(""); + } + return (
setVisible(!visible)} /> @@ -43,8 +49,8 @@ export default function ActionDrawer() { See target info
- { console.log(i) }} /> - Capture target + setEnemyCaptureCode(e.target.value)} /> + Capture target
diff --git a/traque-front/hook/useGame.jsx b/traque-front/hook/useGame.jsx index c867a23..6fd468c 100644 --- a/traque-front/hook/useGame.jsx +++ b/traque-front/hook/useGame.jsx @@ -14,17 +14,20 @@ export default function useGame() { teamSocket.emit("send_position"); } - useEffect(() => console.log("teamInfos", teamInfos), [teamInfos]); - + function capture(captureCode) { + teamSocket.emit("capture", captureCode); + } return { sendCurrentPosition, + capture, enemyPosition: teamInfos?.enemyLocation || null, currentPosition: teamInfos?.currentLocation || null, startingArea: teamInfos?.startingArea || null, captureCode: teamInfos?.captureCode || null, name: teamInfos?.name || null, ready: teamInfos?.ready || false, + captured: teamInfos?.captured || false, teamId, gameState, };