See target info
diff --git a/traque-front/components/team/loginForm.jsx b/traque-front/components/team/loginForm.jsx
index 044bdbc..b5e76c9 100644
--- a/traque-front/components/team/loginForm.jsx
+++ b/traque-front/components/team/loginForm.jsx
@@ -1,6 +1,6 @@
"use client";
import { useState } from "react";
-import Button from "../util/button";
+import BlueButton from "../util/button";
import TextInput from "../util/textInput";
export default function LoginForm({ onSubmit, title, placeholder, buttonText}) {
@@ -14,7 +14,7 @@ export default function LoginForm({ onSubmit, title, placeholder, buttonText}) {
)
}
\ No newline at end of file
diff --git a/traque-front/components/team/map.jsx b/traque-front/components/team/map.jsx
index 15b5132..7d9a426 100644
--- a/traque-front/components/team/map.jsx
+++ b/traque-front/components/team/map.jsx
@@ -4,6 +4,7 @@ import { MapContainer, Marker, Popup, TileLayer, useMap } from 'react-leaflet'
import 'leaflet-defaulticon-compatibility/dist/leaflet-defaulticon-compatibility.css'
import "leaflet-defaulticon-compatibility";
import "leaflet/dist/leaflet.css";
+import useGame from '@/hook/useGame';
const DEFAULT_ZOOM = 17;
@@ -15,7 +16,7 @@ function MapPan(props) {
useEffect(() => {
if(!initialized && props.center) {
- map.flyTo(props.center, DEFAULT_ZOOM);
+ map.flyTo(props.center, DEFAULT_ZOOM, {animate: false});
setInitialized(true)
}
},[props.center]);
@@ -23,8 +24,8 @@ function MapPan(props) {
return null;
}
-export default function LiveMap({enemyPosition, currentPosition, ...props}) {
-
+export default function LiveMap({ ...props}) {
+ const {currentPosition, enemyPosition} = useGame();
return (
{children}
)
diff --git a/traque-front/context/adminConnexionContext.jsx b/traque-front/context/adminConnexionContext.jsx
index d2949ad..52dad56 100644
--- a/traque-front/context/adminConnexionContext.jsx
+++ b/traque-front/context/adminConnexionContext.jsx
@@ -1,38 +1,26 @@
"use client";
-import { createContext, useContext, useEffect, useMemo, useState } from "react";
+import { createContext, useContext, useMemo, } from "react";
import { useSocket } from "./socketContext";
-import { useSocketListener } from "@/hook/useSocketListener";
-import { useLocalStorage } from "@/hook/useLocalStorage";
+import { useSocketAuth } from "@/hook/useSocketAuth";
+import { usePasswordProtect } from "@/hook/usePasswordProtect";
-const adminContext = createContext();
+const adminConnexionContext = createContext();
const AdminConnexionProvider = ({ children }) => {
- const [loggedIn, setLoggedIn] = useState(false);
- const [savedPassword, setSavedPassword] = useLocalStorage("admin_password", null);
const { adminSocket } = useSocket();
+ const { login, loggedIn, loading } = useSocketAuth(adminSocket, "admin_password");
+ const useProtect = () => usePasswordProtect("/admin/login", "/admin", loading, loggedIn);
- useEffect(() => {
- if (savedPassword && !loggedIn) {
- adminSocket.emit("login", savedPassword);
- }
- }, [savedPassword]);
-
- function login(password) {
- setSavedPassword(password)
- }
-
- useSocketListener(adminSocket, "login_response", setLoggedIn);
-
- const value = useMemo(() => ({ login, loggedIn }), [loggedIn]);
+ const value = useMemo(() => ({ login, loggedIn, loading, useProtect }), [loggedIn, loading]);
return (
-
+
{children}
-
+
);
}
function useAdminConnexion() {
- return useContext(adminContext);
+ return useContext(adminConnexionContext);
}
export { AdminConnexionProvider, useAdminConnexion };
diff --git a/traque-front/context/adminContext.jsx b/traque-front/context/adminContext.jsx
index f4dfc48..0f3cdd4 100644
--- a/traque-front/context/adminContext.jsx
+++ b/traque-front/context/adminContext.jsx
@@ -3,15 +3,17 @@ import { createContext, useContext, useEffect, useMemo, useState } from "react";
import { useSocket } from "./socketContext";
import { useSocketListener } from "@/hook/useSocketListener";
import { useAdminConnexion } from "./adminConnexionContext";
+import { GameState } from "@/util/gameState";
const adminContext = createContext();
function AdminProvider({children}) {
const [teams, setTeams] = useState([]);
- const [started, setStarted] = useState(false);
const { adminSocket } = useSocket();
const {loggedIn} = useAdminConnexion();
+ const [gameState, setGameState] = useState(GameState.SETUP);
+ useSocketListener(adminSocket, "game_state", setGameState);
//Send a request to get the teams when the user logs in
useEffect(() => {
adminSocket.emit("get_teams");
@@ -19,9 +21,8 @@ function AdminProvider({children}) {
//Bind listeners to update the team list and the game status on socket message
useSocketListener(adminSocket, "teams", setTeams);
- useSocketListener(adminSocket, "game_started", setStarted);
- const value = useMemo(() => ({teams, setTeams, started, setStarted}), [teams, started]);
+ const value = useMemo(() => ({teams, setTeams, gameState}), [teams, gameState]);
return (
{children}
diff --git a/traque-front/context/socketContext.jsx b/traque-front/context/socketContext.jsx
index 273c3a5..5bd13cf 100644
--- a/traque-front/context/socketContext.jsx
+++ b/traque-front/context/socketContext.jsx
@@ -6,8 +6,6 @@ const { io } = require("socket.io-client");
const SOCKET_URL = 'wss://' + process.env.NEXT_PUBLIC_SOCKET_HOST + ':' + process.env.NEXT_PUBLIC_SOCKET_PORT;
const USER_SOCKET_URL = SOCKET_URL + "/player";
const ADMIN_SOCKET_URL = SOCKET_URL + "/admin";
-console.log(USER_SOCKET_URL);
-console.log(ADMIN_SOCKET_URL);
export const teamSocket = io(USER_SOCKET_URL);
export const adminSocket = io(ADMIN_SOCKET_URL);
diff --git a/traque-front/context/teamConnexionContext.jsx b/traque-front/context/teamConnexionContext.jsx
index 68c2e27..9b82f24 100644
--- a/traque-front/context/teamConnexionContext.jsx
+++ b/traque-front/context/teamConnexionContext.jsx
@@ -1,32 +1,20 @@
"use client";
-import { createContext, useContext, useEffect, useMemo, useState } from "react";
+import { createContext, useContext, useMemo } from "react";
import { useSocket } from "./socketContext";
-import { useSocketListener } from "@/hook/useSocketListener";
-import { useLocalStorage } from "@/hook/useLocalStorage";
+import { useSocketAuth } from "@/hook/useSocketAuth";
+import { usePasswordProtect } from "@/hook/usePasswordProtect";
const teamConnexionContext = createContext();
const TeamConnexionProvider = ({ children }) => {
- const [loggedIn, setLoggedIn] = useState(false);
- const [teamId, setTeamId] = useLocalStorage("team_id", null);
const { teamSocket } = useSocket();
+ const { login, password: teamId, loggedIn, loading } = useSocketAuth(teamSocket, "team_password");
+ const useProtect = () => usePasswordProtect("/team", "/team/track", loading, loggedIn);
- useEffect(() => {
- if (teamId && !loggedIn) {
- teamSocket.emit("login", teamId);
- }
- }, [teamId]);
+ const value = useMemo(() => ({ teamId, login, loggedIn, loading, useProtect}), [teamId, login, loggedIn, loading]);
- function login(id) {
- setTeamId(id);
- }
-
- useSocketListener(teamSocket, "login_response", setLoggedIn);
-
- const value = useMemo(() => ({ teamId, login, loggedIn }), [teamId, login, loggedIn]);
-
return (
- {children}
+ {children}
);
}
@@ -35,5 +23,5 @@ function useTeamConnexion() {
return useContext(teamConnexionContext);
}
-export { TeamConnexionProvider, useTeamConnexion};
+export { TeamConnexionProvider, useTeamConnexion };
diff --git a/traque-front/context/teamContext.jsx b/traque-front/context/teamContext.jsx
index 480b28a..f7b056d 100644
--- a/traque-front/context/teamContext.jsx
+++ b/traque-front/context/teamContext.jsx
@@ -5,24 +5,29 @@ import { createContext, useContext, useEffect, useMemo, useState } from "react";
import { useSocket } from "./socketContext";
import { useTeamConnexion } from "./teamConnexionContext";
+
const teamContext = createContext()
function TeamProvider({children}) {
const [enemyPosition, setEnemyPosition] = useState();
- const currentPosition = useLocation(10000);
+ const [currentPosition, setCurrentPosition] = useState();
+ const [gameState, setGameState] = useState(GameState.SETUP);
+ const measuredLocation = useLocation(10000);
const {teamSocket} = useSocket();
const {loggedIn} = useTeamConnexion();
+ useSocketListener(teamSocket, "game_state", setGameState);
useSocketListener(teamSocket, "enemy_position", setEnemyPosition);
+ useSocketListener(teamSocket, "live_location", setCurrentPosition);
//Send the current position to the server when the user is logged in
useEffect(() => {
- console.log("sending position", currentPosition);
+ console.log("sending position", measuredLocation);
if(loggedIn) {
- teamSocket.emit("update_position", currentPosition);
+ teamSocket.emit("update_position", measuredLocation);
}
- }, [loggedIn, currentPosition]);
+ }, [loggedIn, measuredLocation]);
- const value = useMemo(() => ({enemyPosition, currentPosition}), [enemyPosition, currentPosition]);
+ const value = useMemo(() => ({enemyPosition, currentPosition, gameState}), [enemyPosition, currentPosition, gameState]);
return (
{children}
diff --git a/traque-front/hook/useAdmin.jsx b/traque-front/hook/useAdmin.jsx
index 45e9ede..56c566e 100644
--- a/traque-front/hook/useAdmin.jsx
+++ b/traque-front/hook/useAdmin.jsx
@@ -2,7 +2,7 @@ import { useAdminContext } from "@/context/adminContext";
import { useSocket } from "@/context/socketContext";
export default function useAdmin(){
- const {teams, started} = useAdminContext();
+ const {teams, gameState } = useAdminContext();
const {adminSocket} = useSocket();
function pollTeams() {
@@ -30,18 +30,14 @@ export default function useAdmin(){
adminSocket.emit("remove_team", teamId);
}
- function setTeamName(teamId, newName) {
- adminSocket.emit("rename_team", teamId, newName);
+ function updateTeam(teamId, team) {
+ adminSocket.emit("update_team", teamId, team);
}
- function startGame() {
- adminSocket.emit("start_game");
+ function changeState(state) {
+ adminSocket.emit("change_state", state);
}
- function stopGame() {
- adminSocket.emit("stop_game");
- }
-
- return { teams, started, pollTeams, getTeam, getTeamName, reorderTeams, addTeam, removeTeam, startGame, stopGame, setTeamName };
+ return {teams, gameState, pollTeams, getTeam, getTeamName, reorderTeams, addTeam, removeTeam, changeState, updateTeam };
}
\ No newline at end of file
diff --git a/traque-front/hook/useGame.jsx b/traque-front/hook/useGame.jsx
index b9e200b..7c7bfec 100644
--- a/traque-front/hook/useGame.jsx
+++ b/traque-front/hook/useGame.jsx
@@ -6,12 +6,13 @@ import { useTeamContext } from "@/context/teamContext";
export default function useGame() {
const {teamSocket} = useSocket();
- const {loggedIn, login, teamId} = useTeamConnexion();
- const {currentPosition, enemyPosition} = useTeamContext();
+ const {teamId} = useTeamConnexion();
+ const {currentPosition, enemyPosition, gameState} = useTeamContext();
function sendCurrentPosition() {
teamSocket.emit("send_position");
}
- return { sendCurrentPosition, login, enemyPosition, currentPosition, loggedIn, teamId };
+
+ return { sendCurrentPosition, enemyPosition, currentPosition, teamId, gameState};
}
\ No newline at end of file
diff --git a/traque-front/hook/useLocalStorage.jsx b/traque-front/hook/useLocalStorage.jsx
index 103da22..14a63ce 100644
--- a/traque-front/hook/useLocalStorage.jsx
+++ b/traque-front/hook/useLocalStorage.jsx
@@ -3,6 +3,7 @@ import { useEffect, useState } from "react";
export function useLocalStorage(key, initialValue) {
const [storedValue, setStoredValue] = useState(initialValue);
+ const [loading, setLoading] = useState(true);
useEffect(() => {
try {
@@ -11,6 +12,7 @@ export function useLocalStorage(key, initialValue) {
} catch (error) {
console.log(error);
}
+ setLoading(false);
}, []);
const setValue = value => {
@@ -23,5 +25,5 @@ export function useLocalStorage(key, initialValue) {
}
}
- return [storedValue, setValue];
+ return [storedValue, setValue, loading];
}
\ No newline at end of file
diff --git a/traque-front/hook/useLocation.jsx b/traque-front/hook/useLocation.jsx
index 70e8c17..37d1272 100644
--- a/traque-front/hook/useLocation.jsx
+++ b/traque-front/hook/useLocation.jsx
@@ -9,9 +9,12 @@ export function useLocation(interval) {
const [location, setLocation] = useState();
useEffect(() => {
function update() {
+ console.log('Updating location');
navigator.geolocation.getCurrentPosition((position) => {
setLocation([position.coords.latitude, position.coords.longitude]);
- setTimeout(update, interval);
+ if(interval != Infinity) {
+ setTimeout(update, interval);
+ }
}, () => { }, { enableHighAccuracy: true, timeout: Infinity, maximumAge: 0 });
}
update();
diff --git a/traque-front/hook/usePasswordProtect.jsx b/traque-front/hook/usePasswordProtect.jsx
new file mode 100644
index 0000000..581bce4
--- /dev/null
+++ b/traque-front/hook/usePasswordProtect.jsx
@@ -0,0 +1,15 @@
+"use client";
+import { redirect, usePathname } from "next/navigation";
+import { useEffect } from "react";
+
+export function usePasswordProtect(loginPath, redirectPath, loading, loggedIn) {
+ const path = usePathname();
+ useEffect(() => {
+ if (!loggedIn && !loading && path !== loginPath) {
+ redirect(loginPath);
+ }
+ if(loggedIn && !loading && path === loginPath) {
+ redirect(redirectPath)
+ }
+ }, [loggedIn, loading, path]);
+}
\ No newline at end of file
diff --git a/traque-front/hook/useSocketAuth.jsx b/traque-front/hook/useSocketAuth.jsx
new file mode 100644
index 0000000..7f4bfdb
--- /dev/null
+++ b/traque-front/hook/useSocketAuth.jsx
@@ -0,0 +1,43 @@
+import {useEffect, useState} from 'react';
+import { useSocketListener } from './useSocketListener';
+import { useLocalStorage } from './useLocalStorage';
+import { usePathname } from 'next/navigation';
+
+const LOGIN_MESSAGE = "login";
+const LOGIN_RESPONSE_MESSAGE = "login_response";
+
+export function useSocketAuth(socket, passwordName) {
+ const [loggedIn, setLoggedIn] = useState(false);
+ const [loading, setLoading] = useState(true);
+ const [waitingForResponse, setWaitingForResponse] = useState(true);
+ const [savedPassword, setSavedPassword, savedPasswordLoading] = useLocalStorage(passwordName, null);
+
+ useEffect(() => {
+ if (savedPassword && !loggedIn) {
+ socket.emit(LOGIN_MESSAGE, savedPassword);
+ }
+ }, [savedPassword]);
+
+ function login(password) {
+ setSavedPassword(password)
+ }
+
+ useSocketListener(socket, LOGIN_RESPONSE_MESSAGE,(loginResponse) => {
+ setWaitingForResponse(false);
+ setLoggedIn(loginResponse);
+ });
+
+ useEffect(() => {
+ //There is a password saved and we recieved a login response
+ if(savedPassword && !waitingForResponse && !savedPasswordLoading) {
+ setLoading(false);
+ }
+ //We tried to load the saved password but it is not there
+ else if (savedPassword == null && !savedPasswordLoading) {
+ setLoading(false);
+ }
+ }, [waitingForResponse, savedPasswordLoading, savedPassword]);
+
+
+ return {login,password: savedPassword, loggedIn, loading};
+}
\ No newline at end of file
diff --git a/traque-front/util/gameState.js b/traque-front/util/gameState.js
new file mode 100644
index 0000000..e5514f7
--- /dev/null
+++ b/traque-front/util/gameState.js
@@ -0,0 +1,6 @@
+export const GameState = {
+ SETUP: "setup",
+ PLACEMENT: "placement",
+ PLAYING: "playing",
+ FINISHED: "finished"
+}
\ No newline at end of file