diff --git a/code/backend/src/controllers/login.controller.ts b/code/backend/src/controllers/login.controller.ts
index 2fc4c432..32ea5c7e 100644
--- a/code/backend/src/controllers/login.controller.ts
+++ b/code/backend/src/controllers/login.controller.ts
@@ -43,14 +43,19 @@ class LoginController {
}
const email = loginReq.userName;
- const player = await PlayerModel.findOne({ email });
- if (player?.isVerified == "pending" || player?.isVerified == "rejected") {
+ const manager = await ManagerModel.findOne({
+ teamId: loginReq.teamId,
+ email: email,
+ });
+ console.log(300);
+ console.log(manager);
+
+ console.log(manager?.isVerified);
+
+ if (manager?.isVerified == "pending" || manager?.isVerified == "rejected") {
throw new Error(HttpMsg.MANAGER_NOT_VERIFIED);
}
-
-
-
try {
// create refresh token
const refreshToken = createRefreshTokenManager(loginReq, role);
@@ -84,9 +89,6 @@ class LoginController {
loginReq.password
);
-
-
-
if (!isMatch) {
throw new Error(HttpMsg.PASSWORD_INCORRECT);
}
@@ -97,7 +99,6 @@ class LoginController {
throw new Error(HttpMsg.PLAYER_NOT_VERIFIED);
}
-
try {
// create refresh token
const refreshToken = createRefreshToken(loginReq, role);
diff --git a/code/backend/src/controllers/manager.controller.ts b/code/backend/src/controllers/manager.controller.ts
index 06897ef3..4677f368 100644
--- a/code/backend/src/controllers/manager.controller.ts
+++ b/code/backend/src/controllers/manager.controller.ts
@@ -1,4 +1,9 @@
-import { Manager, ManagerResponse, ManagerTeamResponse } from "../models/manager.model";
+import {
+ Manager,
+ ManagerResponse,
+ ManagerTeamResponse,
+ ManagersArrayResponse,
+} from "../models/manager.model";
import TeamModel from "../db/team.schema";
import managerService from "../services/manager.service";
import managersInTeamService from "../services/managers.in.team.service";
@@ -92,7 +97,7 @@ class ManagerController {
// check the manager exits in that team
const managerExists = await managerService.checkManagerExistsInTeam(
managerEmail,
- teamId
+ teamId
);
const newManagerExists = await managerService.checkManagerExistsInTeam(
@@ -100,7 +105,7 @@ class ManagerController {
teamId
);
- if (newManagerExists){
+ if (newManagerExists) {
throw new Error("New Manager already exists in the team");
}
@@ -176,34 +181,51 @@ class ManagerController {
}
// get all the teamPlayers with their details
- async getPlayers(teamId: string): Promise<{ [jerseyId: number]: TeamPlayerResponse }>{
-
- try{
+ async getPlayers(
+ teamId: string
+ ): Promise<{ [jerseyId: number]: TeamPlayerResponse }> {
+ try {
const response = await managersInTeamService.getPlayersInTeam(teamId);
// console.log(response);
return response;
- }catch(error) {
+ } catch (error) {
console.error(error);
throw error;
}
+ }
+ // get all the teamManagers with their details
+ async getManagers(teamId: string): Promise> {
+ try {
+ const response = await managersInTeamService.getManagersInTeam(teamId);
+ // console.log(response);
+ return response;
+ } catch (error) {
+ console.error(error);
+ throw error;
+ }
}
//get Team Analytics
- async getTeamAnalytics(teamId: string, duration:string): Promise {
-
+ async getTeamAnalytics(
+ teamId: string,
+ duration: string
+ ): Promise {
// 'Last Week' , 'Last Month' , 'All Time'
let durationNumber: number = 0;
- if (duration == "All Time"){
+ if (duration == "All Time") {
durationNumber = Date.now();
- } else if (duration == "Last Month"){
+ } else if (duration == "Last Month") {
durationNumber = 30 * 24 * 60 * 60 * 1000;
- } else if (duration == "Last Week"){
+ } else if (duration == "Last Week") {
durationNumber = 7 * 24 * 60 * 60 * 1000;
}
try {
- const response = await managersInTeamService.getTeamAnalytics(teamId, durationNumber);
+ const response = await managersInTeamService.getTeamAnalytics(
+ teamId,
+ durationNumber
+ );
return response;
} catch (error) {
console.error(error);
diff --git a/code/backend/src/controllers/player.controller.ts b/code/backend/src/controllers/player.controller.ts
index ae0f0034..c49ecee3 100644
--- a/code/backend/src/controllers/player.controller.ts
+++ b/code/backend/src/controllers/player.controller.ts
@@ -2,7 +2,7 @@ import playersInTeamService from "../services/players.in.team.service";
import managerService from "../services/manager.service";
import playerService from "../services/player.service";
import { HttpMsg } from "../exceptions/http.codes.mgs";
-import { TeamIdEmailExistsResponse, TeamResponse} from "../models/team.model";
+import { TeamIdEmailExistsResponse, TeamResponse } from "../models/team.model";
import teamService from "../services/team.service";
import { v4 as uuidv4 } from "uuid";
import PlayerModel from "../db/player.schema";
@@ -10,24 +10,29 @@ import TeamModel from "../db/team.schema";
import { sendInvitationEmail } from "../email/playerInviteEmail";
import { sendVerificationEmail } from "../email/playerVerifyEmail";
import { findSourceMap } from "module";
-import { Player, PlayerInTeamResponse, PlayerRequestBody, PlayerResponse, PlayerTeamRequest } from "../models/player.model";
+import {
+ Player,
+ PlayerInTeamResponse,
+ PlayerRequestBody,
+ PlayerResponse,
+ PlayerTeamRequest,
+} from "../models/player.model";
import PlayerTeamModel from "../db/players.in.team.schema";
import { AnalyticsSummary } from "../types/types";
class PlayerController {
-
// add player to the player team collection
async addNewPlayer(
jerseyId: number,
fullName: string,
newPlayerEmail: string,
teamId: string,
- managerEmail: string,
-
+ managerEmail: string
): Promise {
try {
// check the team exist
- const teamIdEmailExistsResponse: TeamIdEmailExistsResponse = await teamService.checkTeamEmailExist(teamId,managerEmail);
+ const teamIdEmailExistsResponse: TeamIdEmailExistsResponse =
+ await teamService.checkTeamEmailExist(teamId, managerEmail);
if (!teamIdEmailExistsResponse.teamExists) {
throw new Error(HttpMsg.TEAM_NOT_FOUND);
}
@@ -35,24 +40,21 @@ class PlayerController {
throw new Error(HttpMsg.MANAGER_DEOS_NOT_EXIST);
}
// check if player already exists in the team
- const playerExistsInTeam = await playersInTeamService.checkPlayerExistsInTeam(
- jerseyId,
- teamId,
- );
+ const playerExistsInTeam =
+ await playersInTeamService.checkPlayerExistsInTeam(jerseyId, teamId);
-
if (playerExistsInTeam) {
throw new Error(HttpMsg.PLAYER_ALREADY_EXISTS_IN_TEAM);
- // If player not exist in that team => added to the team (player in teams)
- }else{
+ // If player not exist in that team => added to the team (player in teams)
+ } else {
// Create a player with an invitation token
const invitationToken = generateInvitationToken();
const teamInstance = await TeamModel.findOne({ teamId });
const teamName = teamInstance?.teamName; // Add null check using optional chaining operator
const playerInTeamResponse = await playersInTeamService.addPlayerToTeam(
- newPlayerEmail,
+ newPlayerEmail,
teamId,
jerseyId,
fullName,
@@ -60,13 +62,19 @@ class PlayerController {
);
// Send the invitation email
- await sendInvitationEmail(fullName, newPlayerEmail, invitationToken, teamName!);
- return playerInTeamResponse
+
+ await sendInvitationEmail(
+ fullName,
+ newPlayerEmail,
+ invitationToken,
+ teamName!
+ );
+
+ return playerInTeamResponse;
}
-
- // // check if new player already has an account
- // //TODO: Remove if user will not be able to create an account within 30 days
+ // // check if new player already has an account
+ // //TODO: Remove if user will not be able to create an account within 30 days
// const playerExists = await playerService.checkPlayerExists(newPlayerEmail);
// // If player not exist in the player collection => added to the player collection
@@ -78,58 +86,49 @@ class PlayerController {
// newPlayerEmail
// );
// }
-
-
} catch (error) {
console.error(error);
throw error;
}
-
}
- // create player
- async createPlayer(
- email: string,
- password: string
- ): Promise {
+ // create player
+ async createPlayer(email: string, password: string): Promise {
try {
// check if player already has an account
const exists: boolean = await playerService.checkPlayerExists(email);
if (exists) {
throw new Error(HttpMsg.PLAYER_ALREADY_HAS_ACCOUNT);
-
} else {
// Create a new player account
// const playerRequestBody: PlayerRequestBody = new PlayerRequestBody(
// email,
// password
// );
-
+
// Create a player with an invitation token
const invitationToken = generateInvitationToken();
- const playerResponse = await playerService.createPlayer(email, password, invitationToken);
+ const playerResponse = await playerService.createPlayer(
+ email,
+ password,
+ invitationToken
+ );
// Send the verification email
await sendVerificationEmail(email, invitationToken);
return playerResponse;
-
}
} catch (error) {
console.error(error);
throw error;
}
-
}
//get player details
- async getPlayer(
- playerEmail: string
- ): Promise {
+ async getPlayer(playerEmail: string): Promise {
try {
- const playerResponse = await playerService.getPlayer(
- playerEmail
- );
+ const playerResponse = await playerService.getPlayer(playerEmail);
return playerResponse;
} catch (error) {
console.error(error);
@@ -152,15 +151,20 @@ class PlayerController {
}
// Update player in Team
async updatePlayer(
- playerTeamRequest: PlayerTeamRequest,
- managerEmail: string,
- teamId: string,
-
-): Promise {
-
- try{
+ playerTeamRequest: PlayerTeamRequest,
+ managerEmail: string,
+ teamId: string
+ ): Promise {
+ try {
+ const existingPlayer = await PlayerTeamModel.findOne({
+ teamId: teamId,
+ jerseyId: playerTeamRequest.jerseyId,
+ });
+ const newEmail = playerTeamRequest.playerEmail;
+ const prevEmail = existingPlayer?.playerEmail;
// check the team exist and manager exist
- const teamIdEmailExistsResponse: TeamIdEmailExistsResponse = await teamService.checkTeamEmailExist(teamId,managerEmail);
+ const teamIdEmailExistsResponse: TeamIdEmailExistsResponse =
+ await teamService.checkTeamEmailExist(teamId, managerEmail);
if (!teamIdEmailExistsResponse.teamExists) {
throw new Error(HttpMsg.TEAM_NOT_FOUND);
}
@@ -168,37 +172,43 @@ class PlayerController {
throw new Error(HttpMsg.MANAGER_DEOS_NOT_EXIST);
}
// check if player exists in the team
- const playerExistsInTeam = await playersInTeamService.checkPlayerExistsInTeam(
- playerTeamRequest.jerseyId,
- teamId,
- );
+ const playerExistsInTeam =
+ await playersInTeamService.checkPlayerExistsInTeam(
+ playerTeamRequest.jerseyId,
+ teamId
+ );
- if (playerExistsInTeam){
- const playerInTeamResponse = await playersInTeamService.updatePlayerInTeam(playerTeamRequest);
+ if (playerExistsInTeam) {
+ const playerInTeamResponse =
+ await playersInTeamService.updatePlayerInTeam(
+ playerTeamRequest,
+ teamId
+ );
//If the email get changed => send verification email
- if (playerInTeamResponse.playerEmail != playerTeamRequest.playerEmail){
-
+ if (prevEmail != newEmail) {
// Create a player with an invitation token
const invitationToken = generateInvitationToken();
const teamInstance = await TeamModel.findOne({ teamId });
const teamName = teamInstance?.teamName; // Add null check using optional chaining operator
- // Send the invitation email
- await sendInvitationEmail(playerInTeamResponse.fullName, playerInTeamResponse.playerEmail, invitationToken, teamName!);
+ // Send the invitation email
+ await sendInvitationEmail(
+ playerInTeamResponse.fullName,
+ playerInTeamResponse.playerEmail,
+ invitationToken,
+ teamName!
+ );
}
-
return playerInTeamResponse;
- }else{
- throw new Error(HttpMsg.PLAYER_NOT_EXISTS_IN_TEAM)
+ } else {
+ throw new Error(HttpMsg.PLAYER_NOT_EXISTS_IN_TEAM);
}
-
- }catch(error){
+ } catch (error) {
console.error(error);
throw error;
}
-
}
// Remove player in team
@@ -206,12 +216,11 @@ class PlayerController {
jerseyId: number,
teamId: string,
managerEmail: string
-
- ): Promise{
-
- try{
+ ): Promise {
+ try {
// check the team exist
- const teamIdEmailExistsResponse: TeamIdEmailExistsResponse = await teamService.checkTeamEmailExist(teamId,managerEmail);
+ const teamIdEmailExistsResponse: TeamIdEmailExistsResponse =
+ await teamService.checkTeamEmailExist(teamId, managerEmail);
if (!teamIdEmailExistsResponse.teamExists) {
throw new Error(HttpMsg.TEAM_NOT_FOUND);
}
@@ -219,67 +228,61 @@ class PlayerController {
throw new Error(HttpMsg.MANAGER_DEOS_NOT_EXIST);
}
// check if player already exists in the team
- const playerExistsInTeam = await playersInTeamService.checkPlayerExistsInTeam(
- jerseyId,
- teamId,
- );
- if (playerExistsInTeam){
+ const playerExistsInTeam =
+ await playersInTeamService.checkPlayerExistsInTeam(jerseyId, teamId);
+ if (playerExistsInTeam) {
const isRemoved = await playersInTeamService.removePlayerInTeam(
jerseyId,
teamId
);
return isRemoved;
- }else{
+ } else {
throw new Error(HttpMsg.PLAYER_NOT_EXISTS_IN_TEAM);
- }
-
-
- }catch(error){
+ }
+ } catch (error) {
console.error(error);
throw error;
}
}
// Get all the teams of player
- async getTeamsForPlayer(
- playerEmail: string
- ): Promise>{
-
- try {
- const teams = await playerService.getTeamsForPlayer(playerEmail);
- return teams;
- } catch (error) {
- console.error(error);
- throw new Error("Error in player service");
- }
+ async getTeamsForPlayer(playerEmail: string): Promise> {
+ try {
+ const teams = await playerService.getTeamsForPlayer(playerEmail);
+ return teams;
+ } catch (error) {
+ console.error(error);
+ throw new Error("Error in player service");
+ }
}
-
+
async getAnalyticsSummary(
email: string,
duration: string
- ): Promise{
+ ): Promise {
// 'Last Week' , 'Last Month' , 'All Time'
let durationNumber: number = 0;
- if (duration == "All Time"){
+ if (duration == "All Time") {
durationNumber = Date.now();
- } else if (duration == "Last Month"){
+ } else if (duration == "Last Month") {
durationNumber = 30 * 24 * 60 * 60 * 1000;
- } else if (duration == "Last Week"){
+ } else if (duration == "Last Week") {
durationNumber = 7 * 24 * 60 * 60 * 1000;
}
// console.log(durationNumber);
try {
- const analyticsSummary = await playerService.getAnalyticsSummary(email, durationNumber);
+ const analyticsSummary = await playerService.getAnalyticsSummary(
+ email,
+ durationNumber
+ );
return analyticsSummary;
} catch (error) {
console.error(error);
throw new Error("Error in player service");
}
-
}
-
}
function generateInvitationToken(): string {
// Generate a UUID (v4) using the uuid library
diff --git a/code/backend/src/controllers/team.controller.ts b/code/backend/src/controllers/team.controller.ts
index 57adc5a3..16a210cc 100644
--- a/code/backend/src/controllers/team.controller.ts
+++ b/code/backend/src/controllers/team.controller.ts
@@ -93,6 +93,8 @@ class TeamController {
managerEmail,
teamId
);
+
+ // console.log(managerExists);
return managerExists;
} catch (error) {
console.error(error);
diff --git a/code/backend/src/exceptions/http.codes.mgs.ts b/code/backend/src/exceptions/http.codes.mgs.ts
index d04443c9..f7b4beb7 100644
--- a/code/backend/src/exceptions/http.codes.mgs.ts
+++ b/code/backend/src/exceptions/http.codes.mgs.ts
@@ -30,7 +30,10 @@ enum HttpMsg {
MANAGER_NOT_FOUND = "Manager not found",
TEAM_NOT_FOUND = "Team not found",
MANAGER_NOT_VERIFIED = "Manager not verified",
+ MANAGER_REMOVE_FAILED = "Manager remove failed",
MANAGER_DEOS_NOT_EXIST = "Manager does not exist",
+ MANAGER_REMOVE_SUCCESS = "Manager remove success",
+ MANAGER_JOINED_SUCCESS = "Manager joined success",
PLAYER_EXIT_ERROR = "Player exited error",
PLAYER_ALREADY_HAS_ACCOUNT = "Player already has an account",
PLAYER_ALREADY_EXISTS_IN_TEAM = "Player already exists in team",
diff --git a/code/backend/src/models/manager.model.ts b/code/backend/src/models/manager.model.ts
index 6b0d048f..563ee37c 100644
--- a/code/backend/src/models/manager.model.ts
+++ b/code/backend/src/models/manager.model.ts
@@ -51,7 +51,7 @@ class ManagerRequestBody {
public firstName: string;
public lastName: string;
public email: string;
- public password: string;
+ public password: string;
public invitationToken: string;
public isVerified: string;
@@ -79,15 +79,30 @@ class ManagerTeamResponse {
public teamId: string;
public accepted: string;
- public constructor(
- managerEmail: string,
- teamId: string,
- accepted: string
- ) {
+ public constructor(managerEmail: string, teamId: string, accepted: string) {
this.managerEmail = managerEmail;
this.teamId = teamId;
this.accepted = accepted;
}
}
-export { ManagerExistsResponse, Manager, ManagerResponse, ManagerRequestBody, ManagerTeamResponse };
+class ManagersArrayResponse {
+ public name?: string;
+ public email: string;
+ public verification: string;
+
+ public constructor(email: string, name: string, verification: string) {
+ this.name = name;
+ this.email = email;
+ this.verification = verification;
+ }
+}
+
+export {
+ ManagerExistsResponse,
+ Manager,
+ ManagerResponse,
+ ManagerRequestBody,
+ ManagerTeamResponse,
+ ManagersArrayResponse,
+};
diff --git a/code/backend/src/routes/manager.route.ts b/code/backend/src/routes/manager.route.ts
index 0a98dd5e..79679700 100644
--- a/code/backend/src/routes/manager.route.ts
+++ b/code/backend/src/routes/manager.route.ts
@@ -14,7 +14,6 @@ import ManagerModel from "../db/manager.schema";
import ROLES from "../config/roles";
import authService from "../services/auth.service";
-
// Create an instance of the Express Router
const router = Router();
@@ -42,12 +41,14 @@ router.post("/add", async (req: Request, res: Response) => {
managerEmail,
newManagerEmail,
teamId
- );
+ );
if (state) {
- res.send(HttpMsg.MANAGER_ADD_SUCCESS);
+ res.status(HttpCode.OK).send({ message: HttpMsg.MANAGER_ADD_SUCCESS });
} else {
- res.send({ message: HttpMsg.MANAGER_ADD_FAILED });
+ res
+ .status(HttpCode.BAD_REQUEST)
+ .send({ message: HttpMsg.MANAGER_ADD_FAILED });
}
} catch (err) {
if (err instanceof Error) {
@@ -82,18 +83,21 @@ router.get("/exists/:email/:teamId", async (req: Request, res: Response) => {
try {
// Check if a manager with the given email exists in team
- const exists: boolean = await managerController.checkManagerExistsInTeam(email, teamId);
+ const exists: boolean = await managerController.checkManagerExistsInTeam(
+ email,
+ teamId
+ );
// const existsResponse: ManagerExistsResponse = new ManagerExistsResponse(
// exists
// );
if (exists) {
res.send(exists);
- }else{
+ } else {
const teamExistsRes = await teamController.checkTeamExist(teamId);
- if (teamExistsRes.teamExists){
+ if (teamExistsRes.teamExists) {
throw new Error(HttpMsg.MANAGER_DEOS_NOT_EXIST);
- }else{
+ } else {
throw new Error(HttpMsg.TEAM_NOT_FOUND);
}
}
@@ -113,7 +117,7 @@ router.post("/", async (req: Request, res: Response) => {
// Extract manager details from the request body
const teamId = req.body.teamId;
const fullName = req.body.fullName;
- const names = fullName.split(' ');
+ const names = fullName.split(" ");
const firstName = names[0];
const lastName = names[1];
const email = req.body.email;
@@ -225,9 +229,58 @@ router.get("/", async (req: Request, res: Response) => {
}
});
-// Endpoint to get player details of the team
-router.get("/getTeamPlayers",async (req:Request, res: Response) => {
+// Endpoint to remove a manager from a team
+router.delete("/remove", async (req: Request, res: Response) => {
+ // Extract the 'teamId' and 'email' from the request body
+ const teamId = req.body.teamId;
+ const email = req.body.userName;
+ const managerEmail = req.body.email;
+
+ console.log(teamId, email, managerEmail);
+ // Validate the 'teamId' and 'email'
+ if (!teamId || !email || !managerEmail) {
+ console.log(HttpMsg.BAD_REQUEST);
+ res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ return;
+ }
+
+ try {
+ //Check if the respond sending manager different from the manager to be removed
+ if (email == managerEmail) {
+ throw new Error(HttpMsg.MANAGER_REMOVE_FAILED);
+ }
+ // Check if the manager exists in the team
+ const manager = await ManagerModel.findOne({
+ teamId: teamId,
+ email: managerEmail,
+ });
+ console.log(manager);
+ if (!manager) {
+ console.log(HttpMsg.MANAGER_NOT_FOUND);
+ res
+ .status(HttpCode.BAD_REQUEST)
+ .send({ message: HttpMsg.MANAGER_NOT_FOUND });
+ return;
+ }
+
+ // Remove the manager from the team
+ await manager.deleteOne();
+ // Send a success response to the client
+ res.send({ message: "Manager removed from team successfully" });
+ res.status(HttpCode.OK).send({ message: HttpMsg.MANAGER_REMOVE_SUCCESS });
+ } catch (error) {
+ if (error instanceof Error) {
+ // If 'error' is an instance of Error, send the error message
+ res.status(HttpCode.BAD_REQUEST).send({ message: error.message });
+ } else {
+ // If 'error' is of unknown type, send a generic error message
+ res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ }
+ }
+});
+// Endpoint to get player details of the team
+router.get("/getTeamPlayers", async (req: Request, res: Response) => {
const managerEmail = req.body.userName;
const teamId = req.body.teamId;
// check the request comes from the manager
@@ -243,21 +296,61 @@ router.get("/getTeamPlayers",async (req:Request, res: Response) => {
return;
}
-
-
- try{
- const managerExists = await managerController.checkManagerExistsInTeam(managerEmail, teamId);
+ try {
+ const managerExists = await managerController.checkManagerExistsInTeam(
+ managerEmail,
+ teamId
+ );
- if (managerExists){
+ if (managerExists) {
const teamPlayerResponse = await managerController.getPlayers(teamId);
res.send(teamPlayerResponse);
- }else{
+ res.status(HttpCode.OK);
+ } else {
throw new Error(HttpMsg.MANAGER_DEOS_NOT_EXIST);
}
-
+ } catch (err) {
+ if (err instanceof Error) {
+ // If 'err' is an instance of Error, send the error message
+ res.status(HttpCode.BAD_REQUEST).send({ message: err.message });
+ } else {
+ // If 'err' is of unknown type, send a generic error message
+ res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ }
+ }
+});
+// Endpoint to get manager details of the team
+router.get("/getTeamManagers", async (req: Request, res: Response) => {
+ const managerEmail = req.body.userName;
+ const teamId = req.body.teamId;
+ // check the request comes from the manager
+ if (req.body.role != ROLES.MANAGER) {
+ console.log(HttpMsg.UNAUTHORIZED);
+ res.status(HttpCode.UNAUTHORIZED).send({ message: HttpMsg.BAD_REQUEST });
+ return;
+ }
+
+ if (!managerEmail) {
+ console.log(HttpMsg.BAD_REQUEST);
+ res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ return;
+ }
+
+ try {
+ const managerExists = await managerController.checkManagerExistsInTeam(
+ managerEmail,
+ teamId
+ );
- }catch (err) {
+ if (managerExists) {
+ const teamPlayerResponse = await managerController.getManagers(teamId);
+ res.send(teamPlayerResponse);
+ res.status(HttpCode.OK);
+ } else {
+ throw new Error(HttpMsg.MANAGER_DEOS_NOT_EXIST);
+ }
+ } catch (err) {
if (err instanceof Error) {
// If 'err' is an instance of Error, send the error message
res.status(HttpCode.BAD_REQUEST).send({ message: err.message });
@@ -277,8 +370,6 @@ router.put("/join-team", async (req: Request, res: Response) => {
const lastName = req.body.lastName;
const password = req.body.password;
-
-
// Check if either Team ID or Team Name is missing
if (!teamId || !email || !firstName || !lastName || !password) {
console.log(HttpMsg.BAD_REQUEST);
@@ -293,62 +384,60 @@ router.put("/join-team", async (req: Request, res: Response) => {
return;
}
-
-
try {
-
- // Check if a manager with the given email exists
- const exists: boolean = await teamController.checkManagerExistsInTeam(
+ // Check if a manager with the given email exists
+ const exists: boolean = await teamController.checkManagerExistsInTeam(
+ email,
+ teamId
+ );
+
+ if (!exists) {
+ console.log(HttpMsg.MANAGER_DEOS_NOT_EXIST);
+ res.send({ message: HttpMsg.MANAGER_DEOS_NOT_EXIST });
+ return;
+ } else {
+ const manager = await ManagerModel.findOne({
+ email: email,
+ teamId: teamId,
+ });
+ const managerAuth = await authService.checkAuthExistsForManager(
email,
teamId
);
- if (!exists) {
- console.log(HttpMsg.MANAGER_DEOS_NOT_EXIST);
- res.send({ message: HttpMsg.MANAGER_DEOS_NOT_EXIST });
- return;
- } else {
- const manager = await ManagerModel.findOne({
- email: email,
- teamId: teamId
- });
-
- if (manager) {
-
- if (manager.isVerified == "pending"){
-
- throw new Error(HttpMsg.MANAGER_NOT_VERIFIED);
- }else{
- manager.firstName = firstName;
- manager.lastName = lastName;
-
- await manager.save();
-
- await authService.createAuthManager(
- email,
- password,
- teamId
- );
-
- const managerResponse = new ManagerResponse(
- {
- teamId: teamId,
- firstName: manager.firstName,
- lastName: manager.lastName,
- email: manager.email,
- password: "##",
- invitationToken: " ",
- isVerified: manager.isVerified
-
- });
- res.send(managerResponse);
- }
-
- }else{
- res.send(HttpMsg.MANAGER_DEOS_NOT_EXIST)
+ console.log(manager, managerAuth);
+ if (manager && !managerAuth) {
+ if (manager.isVerified == "pending") {
+ throw new Error(HttpMsg.MANAGER_NOT_VERIFIED);
+ } else {
+ manager.firstName = firstName;
+ manager.lastName = lastName;
+
+ await manager.save();
+
+ await authService.createAuthManager(email, password, teamId);
+
+ const managerResponse = new ManagerResponse({
+ teamId: teamId,
+ firstName: manager.firstName,
+ lastName: manager.lastName,
+ email: manager.email,
+ password: "##",
+ invitationToken: " ",
+ isVerified: manager.isVerified,
+ });
+ res.send(managerResponse);
+ res
+ .status(HttpCode.OK)
+ .send({ message: HttpMsg.MANAGER_JOINED_SUCCESS });
}
+ } else {
+ res
+ .status(HttpCode.BAD_REQUEST)
+ .send({ message: HttpMsg.MANAGER_DEOS_NOT_EXIST });
+ // res.send(HttpMsg.MANAGER_DEOS_NOT_EXIST);
}
-
+ }
} catch (err) {
if (err instanceof Error) {
// If 'err' is an instance of Error, send the error message
@@ -360,64 +449,68 @@ router.put("/join-team", async (req: Request, res: Response) => {
}
});
-
-
// Endpoint to get Team Analytics
-router.get("/analytics-summary/:duration", async (req: Request, res: Response) => {
- const managerEmail = req.body.userName;
- const teamId = req.body.teamId;
- // check the request comes from the manager
- if (req.body.role != ROLES.MANAGER) {
- console.log(HttpMsg.UNAUTHORIZED);
- res.status(HttpCode.UNAUTHORIZED).send({ message: HttpMsg.BAD_REQUEST });
- return;
- }
+router.get(
+ "/analytics-summary/:duration",
+ async (req: Request, res: Response) => {
+ const managerEmail = req.body.userName;
+ const teamId = req.body.teamId;
+ // check the request comes from the manager
+ if (req.body.role != ROLES.MANAGER) {
+ console.log(HttpMsg.UNAUTHORIZED);
+ res.status(HttpCode.UNAUTHORIZED).send({ message: HttpMsg.BAD_REQUEST });
+ return;
+ }
- if (!managerEmail) {
- console.log(HttpMsg.BAD_REQUEST);
- res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
- return;
- }
+ if (!managerEmail) {
+ console.log(HttpMsg.BAD_REQUEST);
+ res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ return;
+ }
- try {
- const managerExists = await managerController.checkManagerExistsInTeam(
- managerEmail,
- teamId
- );
+ try {
+ const managerExists = await managerController.checkManagerExistsInTeam(
+ managerEmail,
+ teamId
+ );
- if (managerExists) {
- const teamAnalyticsResponse =
- await managerController.getTeamAnalytics(teamId, req.params.duration);
- res.send(teamAnalyticsResponse);
- } else {
- throw new Error(HttpMsg.MANAGER_DEOS_NOT_EXIST);
- }
- } catch (err) {
- if (err instanceof Error) {
- // If 'err' is an instance of Error, send the error message
- res.status(HttpCode.BAD_REQUEST).send({ message: err.message });
- } else {
- // If 'err' is of unknown type, send a generic error message
- res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ if (managerExists) {
+ const teamAnalyticsResponse = await managerController.getTeamAnalytics(
+ teamId,
+ req.params.duration
+ );
+ res.send(teamAnalyticsResponse);
+ res.status(HttpCode.OK);
+ } else {
+ throw new Error(HttpMsg.MANAGER_DEOS_NOT_EXIST);
+ }
+ } catch (err) {
+ if (err instanceof Error) {
+ // If 'err' is an instance of Error, send the error message
+ res.status(HttpCode.BAD_REQUEST).send({ message: err.message });
+ } else {
+ // If 'err' is of unknown type, send a generic error message
+ res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ }
}
}
-});
+);
// Endpoint Accept Invitation
router.get("/accept-invitation/token/:token", async (req, res) => {
const token = req.params.token;
- const manager = await ManagerModel.findOne({ invitationToken: token });
- const managerInTeam = await ManagerModel.findOne({ invitationToken: token });
- if (manager && (manager.isVerified == "pending")) {
+ const manager = await ManagerModel.findOne({ invitationToken: token });
+ const managerInTeam = await ManagerModel.findOne({ invitationToken: token });
+ if (manager && manager.isVerified == "pending") {
// Update manager status
manager.isVerified = "verified";
await manager.save();
res.send("Invitation accepted successfully!");
- } else if (managerInTeam && (managerInTeam.isVerified == "pending")){
+ } else if (managerInTeam && managerInTeam.isVerified == "pending") {
// Update manager status
managerInTeam.isVerified = "verified";
await managerInTeam.save();
- } else{
+ } else {
res.status(400).send("Invalid or expired token.");
}
});
diff --git a/code/backend/src/routes/player.route.ts b/code/backend/src/routes/player.route.ts
index 9db1ab8a..08c0fa43 100644
--- a/code/backend/src/routes/player.route.ts
+++ b/code/backend/src/routes/player.route.ts
@@ -5,7 +5,10 @@ import { validateEmail } from "../utils/utils";
import playerController from "../controllers/player.controller";
import PlayerModel from "../db/player.schema";
import PlayerTeamModel from "../db/players.in.team.schema";
-import { PlayerInTeamResponse, PlayerTeamRequest } from "../models/player.model";
+import {
+ PlayerInTeamResponse,
+ PlayerTeamRequest,
+} from "../models/player.model";
// Create an instance of the Express Router
const router = Router();
@@ -26,7 +29,7 @@ router.post("/add", async (req: Request, res: Response) => {
}
// Validate email format
- if (!validateEmail(newPlayerEmail)) {
+ if (newPlayerEmail !== "" && !validateEmail(newPlayerEmail)) {
console.log(HttpMsg.INVALID_EMAIL);
res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.INVALID_EMAIL });
return;
@@ -38,7 +41,7 @@ router.post("/add", async (req: Request, res: Response) => {
fullName,
newPlayerEmail,
teamId,
- managerEmail,
+ managerEmail
);
// This is just for adding playes with verification status
@@ -51,12 +54,10 @@ router.post("/add", async (req: Request, res: Response) => {
// isVerified: isVerified,
// });
-
// Save the manager to the database
// const savedManager = await playerTeamInstance.save();
res.send(playerInTeamResponse);
-
} catch (err) {
if (err instanceof Error) {
// If 'err' is an instance of Error, send the error message
@@ -89,13 +90,12 @@ router.post("/", async (req: Request, res: Response) => {
}
try {
- const playerResponse = await playerController.createPlayer( email, password);
+ const playerResponse = await playerController.createPlayer(email, password);
if (playerResponse) {
res.send(playerResponse);
} else {
res.send({ message: "Player create new account failed" });
}
-
} catch (err) {
if (err instanceof Error) {
// If 'err' is an instance of Error, send the error message
@@ -116,9 +116,7 @@ router.get("/", async (req: Request, res: Response) => {
}
try {
// Get Player details
- const playerResponse = await playerController.getPlayer(
- req.body.userName
- );
+ const playerResponse = await playerController.getPlayer(req.body.userName);
res.send(playerResponse);
} catch (err) {
@@ -138,18 +136,18 @@ router.put("/update", async (req: Request, res: Response) => {
const jerseyId = req.body.jerseyId;
const fullName = req.body.fullName;
const managerEmail = req.body.userName; // extract from middleware
- const teamId = req.body.teamId; // extract from middleware
+ const teamId = req.body.teamId; // extract from middleware
// Check if any required field is missing
- if (!jerseyId || !fullName || !newPlayerEmail ) {
+ if (!jerseyId || !fullName || !newPlayerEmail) {
const missingFields = [];
- if (!jerseyId) missingFields.push("jerseyId");
- if (!fullName) missingFields.push("fullName");
- if (!newPlayerEmail) missingFields.push("newPlayerEmail");
+ if (!jerseyId) missingFields.push("jerseyId");
+ if (!fullName) missingFields.push("fullName");
+ if (!newPlayerEmail) missingFields.push("newPlayerEmail");
- const errorMessage = `Missing required fields: ${missingFields.join(", ")}`;
- console.log(errorMessage);
- res.status(HttpCode.BAD_REQUEST).send({ message: errorMessage });
+ const errorMessage = `Missing required fields: ${missingFields.join(", ")}`;
+ console.log(errorMessage);
+ res.status(HttpCode.BAD_REQUEST).send({ message: errorMessage });
}
// Validate email format
@@ -160,11 +158,13 @@ router.put("/update", async (req: Request, res: Response) => {
}
try {
- const player = await PlayerTeamModel.find({
- jesryId: jerseyId,
- teamId: teamId });
+ // console.log(jerseyId, teamId);
+ const player = await PlayerTeamModel.findOne({
+ teamId: teamId,
+ jerseyId: jerseyId,
+ });
- console.log(player );
+ // console.log(player);
const playerTeamRequest = new PlayerTeamRequest(
newPlayerEmail,
@@ -172,15 +172,16 @@ router.put("/update", async (req: Request, res: Response) => {
fullName
);
-
- let playerInTeamResponse;
+ // console.log(playerTeamRequest);
- if (player){
+ let playerInTeamResponse;
+ if (player) {
playerInTeamResponse = await playerController.updatePlayer(
- playerTeamRequest,
- managerEmail,
- teamId);
+ playerTeamRequest,
+ managerEmail,
+ teamId
+ );
// if (player.playerEmail != newPlayerEmail) {
// // Player with the same email already exists, update the existing player
@@ -197,16 +198,13 @@ router.put("/update", async (req: Request, res: Response) => {
// res.send({ message: "Player created successfully", playerInTeamResponse });
// }
-
- res.send({ message: "Player updated successfully", playerInTeamResponse });
-
- }else{
+ res.send({
+ message: "Player updated successfully",
+ playerInTeamResponse,
+ });
+ } else {
throw new Error(HttpMsg.PLAYER_NOT_EXISTS_IN_TEAM);
}
-
-
-
-
} catch (err) {
if (err instanceof Error) {
// If 'err' is an instance of Error, send the error message
@@ -219,44 +217,45 @@ router.put("/update", async (req: Request, res: Response) => {
});
// Endpoint to remove player from team
-router.delete("/remove",async (req:Request, res: Response) => {
- const jerseyId = req.body.jerseyId;
- const teamId = req.body.teamId;
- const managerEmail = req.body.userName;
-
- // Check if any required field is missing
- if (!jerseyId) {
-
- console.log(HttpMsg.BAD_REQUEST);
- res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
- return;
- }
-
- try{
- const isRemoved = await playerController.removePlayer(jerseyId, teamId, managerEmail);
+router.delete("/remove", async (req: Request, res: Response) => {
+ const jerseyId = req.body.jerseyId;
+ const teamId = req.body.teamId;
+ const managerEmail = req.body.userName;
- if (isRemoved) {
- return res.send({ message: "Player removed from team successfully" });
- } else {
- throw new Error(HttpMsg.PLAYER_REMOVE_FAILED);
- }
+ // Check if any required field is missing
+ if (!jerseyId) {
+ console.log(HttpMsg.BAD_REQUEST);
+ res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ return;
+ }
- } catch (err) {
- if (err instanceof Error) {
- // If 'err' is an instance of Error, send the error message
- res.status(HttpCode.BAD_REQUEST).send({ message: err.message });
- } else {
- // If 'err' is of unknown type, send a generic error message
- res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
- }
+ try {
+ const isRemoved = await playerController.removePlayer(
+ jerseyId,
+ teamId,
+ managerEmail
+ );
+
+ if (isRemoved) {
+ return res.send({ message: "Player removed from team successfully" });
+ } else {
+ throw new Error(HttpMsg.PLAYER_REMOVE_FAILED);
}
+ } catch (err) {
+ if (err instanceof Error) {
+ // If 'err' is an instance of Error, send the error message
+ res.status(HttpCode.BAD_REQUEST).send({ message: err.message });
+ } else {
+ // If 'err' is of unknown type, send a generic error message
+ res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ }
+ }
});
// Endpoint to get all the teams of Player
router.get("/myTeams", async (req, res) => {
const playerEmail = req.body.userName;
try {
-
const teams = await playerController.getTeamsForPlayer(playerEmail);
if (teams.length > 0) {
@@ -265,7 +264,6 @@ router.get("/myTeams", async (req, res) => {
res.send({ message: "Player is not part of any teams" });
}
} catch (err) {
-
if (err instanceof Error) {
// If 'err' is an instance of Error, send the error message
res.status(HttpCode.BAD_REQUEST).send({ message: err.message });
@@ -277,65 +275,75 @@ router.get("/myTeams", async (req, res) => {
});
// Endpoint to get analytics summary
-router.get("/analytics-summary/:duration",async (req:Request, res: Response) => {
- if (!req.body.userName) {
- console.log(HttpMsg.BAD_REQUEST);
- res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
- return;
- }
- try {
-
- const playerEmail = req.body.userName; // player email is retrieved from the request body
+router.get(
+ "/analytics-summary/:duration",
+ async (req: Request, res: Response) => {
+ if (!req.body.userName) {
+ console.log(HttpMsg.BAD_REQUEST);
+ res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.BAD_REQUEST });
+ return;
+ }
+ try {
+ const playerEmail = req.body.userName; // player email is retrieved from the request body
+ console.log(playerEmail);
- // Check if player exists
- const playerExists = await playerController.checkPlayerExists(playerEmail);
+ // Check if player exists
+ const playerExists = await playerController.checkPlayerExists(
+ playerEmail
+ );
- if (!playerExists) {
- throw new Error(HttpMsg.PLAYER_DOES_NOT_EXIST);
- }
+ if (!playerExists) {
+ throw new Error(HttpMsg.PLAYER_DOES_NOT_EXIST);
+ }
- // Assuming 'getAnalyticsSummary' is a function in your playerController
- // const analyticsSummary = await playerController.getAnalyticsSummary(playerEmail, req.params.duration);
- const analyticsSummary = await playerController.getAnalyticsSummary(playerEmail, req.params.duration);
- res.send({ analyticsSummary });
-
- } catch (error) {
- console.error(error);
- res.status(500).json({ message: "Internal Server Error" });
+ // Assuming 'getAnalyticsSummary' is a function in your playerController
+ // const analyticsSummary = await playerController.getAnalyticsSummary(playerEmail, req.params.duration);
+ const analyticsSummary = await playerController.getAnalyticsSummary(
+ playerEmail,
+ req.params.duration
+ );
+ res.send({ analyticsSummary });
+ } catch (error) {
+ console.error(error);
+ res.status(500).json({ message: "Internal Server Error" });
+ }
}
-});
+);
// Endpoint Accept Invitation
router.get("/accept-invitation/token/:token", async (req, res) => {
const token = req.params.token;
- // const player = await PlayerModel.findOne({ invitationToken: token });
- const playerInTeam = await PlayerTeamModel.findOne({ invitationToken: token });
+ // const player = await PlayerModel.findOne({ invitationToken: token });
+ const playerInTeam = await PlayerTeamModel.findOne({
+ invitationToken: token,
+ });
if (playerInTeam && playerInTeam.isVerified == "pending") {
// Update player status
playerInTeam.isVerified = "verified";
await playerInTeam.save();
res.send("Invitation accepted successfully!");
- }
- else{
+ } else {
res.status(400).send("Invalid or expired token.");
}
});
// Endpoint verify email
-router.get("/verify-email/token/:token", async (req: Request, res: Response) => {
- const token = req.params.token;
- const player = await PlayerModel.findOne({ invitationToken: token });
- // const playerInTeam = await PlayerTeamModel.findOne({ invitationToken: token });
- if (player && player.isVerified == "pending") {
- // Update player status
- player.isVerified = "verified";
- await player.save();
- res.send("Invitation accepted successfully!");
- }
- else{
- res.status(400).send("Invalid or expired token.");
+router.get(
+ "/verify-email/token/:token",
+ async (req: Request, res: Response) => {
+ const token = req.params.token;
+ const player = await PlayerModel.findOne({ invitationToken: token });
+ // const playerInTeam = await PlayerTeamModel.findOne({ invitationToken: token });
+ if (player && player.isVerified == "pending") {
+ // Update player status
+ player.isVerified = "verified";
+ await player.save();
+ res.send("Invitation accepted successfully!");
+ } else {
+ res.status(400).send("Invalid or expired token.");
+ }
}
-});
+);
// Endpoint accept or denied invitation from user profile
router.get("/accept-invite/:teamId/:isAccepted", async (req, res) => {
@@ -346,7 +354,10 @@ router.get("/accept-invite/:teamId/:isAccepted", async (req, res) => {
console.log(playerEmail, teamId, isAccepted, typeof isAccepted);
try {
- const playerInTeam = await PlayerTeamModel.findOne({ playerEmail: playerEmail, teamId: teamId });
+ const playerInTeam = await PlayerTeamModel.findOne({
+ playerEmail: playerEmail,
+ teamId: teamId,
+ });
if (playerInTeam) {
if (isAccepted == "1" && playerInTeam.isVerified == "pending") {
// Update player status
@@ -359,7 +370,7 @@ router.get("/accept-invite/:teamId/:isAccepted", async (req, res) => {
playerInTeam.isVerified = "rejected";
await playerInTeam.save();
res.send("Invitation denied successfully!");
- }else{
+ } else {
res.send("Invitation already accepted or denied!");
}
} else {
diff --git a/code/backend/src/routes/team.route.ts b/code/backend/src/routes/team.route.ts
index e872a552..78f8a643 100644
--- a/code/backend/src/routes/team.route.ts
+++ b/code/backend/src/routes/team.route.ts
@@ -48,7 +48,8 @@ router.get("/exists/teamId/:id", async (req: Request, res: Response) => {
});
// Endpoint to validate both Team ID and email existence
-router.get("/exists",
+router.get(
+ "/exists",
async (req: Request<{}, {}, {}, TeamManagerInterface>, res: Response) => {
// Extract Team ID and email from query parameters
const teamId = req.query.teamId;
@@ -175,6 +176,8 @@ router.post("/manager", async (req, res) => {
teamId
);
+ // console.log(exists);
+
if (exists) {
console.log(HttpMsg.MANAGER_EXISTS);
res.status(HttpCode.BAD_REQUEST).send({ message: HttpMsg.MANAGER_EXISTS });
@@ -194,8 +197,6 @@ router.post("/manager", async (req, res) => {
"pending"
);
-
-
// Create the Team and get the response
const teamResponse: TeamResponse | undefined =
await teamController.createTeam(team);
@@ -279,6 +280,5 @@ router.get("/:id", async (req: Request, res: Response) => {
}
});
-
// Export the router for use in other files
export default router;
diff --git a/code/backend/src/services/managers.in.team.service.ts b/code/backend/src/services/managers.in.team.service.ts
index 94cf02dd..e083da11 100644
--- a/code/backend/src/services/managers.in.team.service.ts
+++ b/code/backend/src/services/managers.in.team.service.ts
@@ -2,9 +2,17 @@ import ManagerModel from "../db/manager.schema";
// import ManagerTeamModel from "../db/managers.in.team.schema";
import PlayerTeamModel from "../db/players.in.team.schema";
import SessionModel from "../db/session.schema";
-import { ManagerTeamResponse } from "../models/manager.model";
+import {
+ ManagerTeamResponse,
+ ManagersArrayResponse,
+} from "../models/manager.model";
import { Impact, SessionResponse } from "../models/session.model";
-import { AnalyticsSummaryTeam, ImpactStats, TeamPlayerResponse, ImpactDirection} from "../types/types";
+import {
+ AnalyticsSummaryTeam,
+ ImpactStats,
+ TeamPlayerResponse,
+ ImpactDirection,
+} from "../types/types";
class ManagersInTeamService {
// create team manager instance
@@ -32,7 +40,6 @@ class ManagersInTeamService {
invitationToken: invitationToken,
});
-
// Save the manager to the database
const savedManager = await managerInstance.save();
@@ -54,15 +61,16 @@ class ManagersInTeamService {
teamId: string
): Promise {
try {
+ console.log(managerEmail, teamId);
// check entry exists
- const managerTeam = await ManagerModel.findOne({
+ const managerTeam = await ManagerModel.find({
email: managerEmail,
teamId: teamId,
});
-
- if (managerTeam) {
+ console.log(managerTeam);
+ if (managerTeam.length !== 0) {
return true;
- }else{
+ } else {
return false;
}
} catch (error) {
@@ -103,71 +111,123 @@ class ManagersInTeamService {
//{ [jerseyId: number]: TeamPlayerResponse }
// get the players in the team
- async getPlayersInTeam(teamId: string):Promise<{ [jerseyId: number]: TeamPlayerResponse }>{
-
+ async getPlayersInTeam(
+ teamId: string
+ ): Promise<{ [jerseyId: number]: TeamPlayerResponse }> {
const teamPlayers: { [jerseyId: number]: TeamPlayerResponse } = {};
- try{
-
+ try {
// Get the player teams for the given team ID
- const playerTeams = await PlayerTeamModel.find({ teamId: teamId}, 'jerseyId -_id');
+ const playerTeams = await PlayerTeamModel.find(
+ { teamId: teamId },
+ "jerseyId -_id"
+ );
// For each player team, get the player details
for (const playerTeam of playerTeams) {
- const player = await PlayerTeamModel.findOne({ jerseyId: playerTeam.jerseyId, teamId: teamId }, 'fullName playerEmail isVerified -_id');
+ const player = await PlayerTeamModel.findOne(
+ { jerseyId: playerTeam.jerseyId, teamId: teamId },
+ "fullName playerEmail isVerified -_id"
+ );
- if (player){
+ if (player) {
// Add the player details to the team players object
teamPlayers[playerTeam.jerseyId] = {
name: player.fullName,
email: player.playerEmail,
- verification: player.isVerified
+ verification: player.isVerified,
};
}
}
return teamPlayers;
-
} catch (error) {
console.error(error);
throw error;
}
+ }
+
+ // get the players in the team
+ async getManagersInTeam(
+ teamId: string
+ ): Promise> {
+ const managers: Array = [];
+ try {
+ // Get the player teams for the given team ID
+ const managerTeams = await ManagerModel.find(
+ { teamId: teamId },
+ "teamId email -_id"
+ );
+
+ // For each player team, get the player details
+ for (const managerTeam of managerTeams) {
+ const manager = await ManagerModel.findOne(
+ { email: managerTeam.email, teamId: teamId },
+ "email isVerified firstName lastName -_id"
+ );
+
+ if (manager) {
+ // Check if the manager has a first and last name
+ if (manager.firstName && manager.lastName) {
+ // Add the manager details to the managers array with the full name
+ managers.push({
+ name: manager.firstName + " " + manager.lastName,
+ email: manager.email,
+ verification: manager.isVerified,
+ });
+ } else {
+ // Add the manager details to the managers array with only the email and verification status
+ managers.push({
+ email: manager.email,
+ verification: manager.isVerified,
+ });
+ }
+ }
+ }
+
+ return managers;
+ } catch (error) {
+ console.error(error);
+ throw error;
+ }
}
//get the team analytics
- async getTeamAnalytics(teamId: string, duration: number): Promise {
-
+ async getTeamAnalytics(
+ teamId: string,
+ duration: number
+ ): Promise {
// Initialize variable to store data
let analyticsSummary: AnalyticsSummaryTeam = {
summaryData: [
{
title: "Sessions",
value: 0,
- trend: 0,
+ trend: "--",
},
{
title: "Impacts Recorded",
value: 0,
- trend: 0,
+ trend: "--",
},
{
title: "Contributing Players",
value: 0,
- trend: 0,
+ trend: "--",
},
{
title: "Highest Contributor",
- value: 0
- }
+ value: "--",
+ },
],
- tableData: []
+ tableData: [],
};
-
+
try {
// Find the all the sessions for the team
const sessions = await SessionModel.find({ teamId: teamId });
- // console.log(sessions);
+ console.log(sessions);
//get all the playrs of the team (players in team)
const teamPlayers = await this.getPlayersInTeam(teamId);
@@ -177,7 +237,6 @@ class ManagersInTeamService {
// For calculations of trends (previous)
let tableDataPrev = [] as AnalyticsSummaryTeam["tableData"];
-
// Table data with player name
analyticsSummary.tableData = jerseyIds.map((jerseyId) => {
return {
@@ -186,12 +245,15 @@ class ManagersInTeamService {
impacts_recorded: 0,
average_impact: 0,
highest_impact: 0,
- dominant_direction: 'none',
+ dominant_direction: "none",
cumulative_impact: 0,
- concussions: 0
+ concussions: 0,
};
});
+ console.log("analyticsSummary.tableData:");
+ console.log(analyticsSummary.tableData);
+
tableDataPrev = jerseyIds.map((jerseyId) => {
return {
jersey_number: jerseyId,
@@ -199,60 +261,80 @@ class ManagersInTeamService {
impacts_recorded: 0,
average_impact: 0,
highest_impact: 0,
- dominant_direction: 'none',
+ dominant_direction: "none",
cumulative_impact: 0,
- concussions: 0
+ concussions: 0,
};
});
-
// Get Time period need to be get analytics
- const now = Date.now();
- const previous= now - (2 * duration); // timestamp of 2 * duration ago
- const current= now - (duration); // timestamp of 2 * duration ago
+ const now = Date.now();
+ const previous = now - 2 * duration; // timestamp of 2 * duration ago
+ const current = now - duration; // timestamp of 2 * duration ago
// In previous time period, no of sessions
- let prevSessions : number= 0;
+ let prevSessions: number = 0;
let filteredSessionsPrevious: SessionResponse[] = [];
// Sessions in previous time period
- if (previous>=0){
- filteredSessionsPrevious = sessions.filter(session => {
+ if (previous >= 0) {
+ filteredSessionsPrevious = sessions.filter((session) => {
const createdAt = new Date(session.createdAt).getTime();
return createdAt >= previous && createdAt <= current;
});
- // console.log(filteredSessionsPrevious);
- await this.calculationForSessions(filteredSessionsPrevious, tableDataPrev);
+ console.log("filteredSessionsPrevious:");
+ console.log(filteredSessionsPrevious);
+ await this.calculationForSessions(
+ filteredSessionsPrevious,
+ tableDataPrev
+ );
// Get the number of sessions
- prevSessions = filteredSessionsPrevious.length
+ prevSessions = filteredSessionsPrevious.length;
}
-
// Sessions in cuurent period
- const filteredSessionsCurrent = sessions.filter(session => {
+ const filteredSessionsCurrent = sessions.filter((session) => {
const createdAt = new Date(session.createdAt).getTime();
return createdAt >= current && createdAt <= now;
});
+ console.log("filteredSessionsCurrent:");
+ console.log(filteredSessionsCurrent);
// Get the number of sessions
- const numberOfSessions = filteredSessionsCurrent.length
+ const numberOfSessions = filteredSessionsCurrent.length;
analyticsSummary.summaryData[0].value = numberOfSessions;
- analyticsSummary.summaryData[0].trend = Math.round(((numberOfSessions - prevSessions)*100/prevSessions));
+ if (prevSessions > 0) {
+ analyticsSummary.summaryData[0].trend = Math.round(
+ ((numberOfSessions - prevSessions) * 100) / prevSessions
+ );
+ } else {
+ analyticsSummary.summaryData[0].trend = "--";
+ }
// Fill up table data
- await this.calculationForSessions(filteredSessionsCurrent, analyticsSummary.tableData);
- await this.calculationForSessions(filteredSessionsPrevious, tableDataPrev);
-
- // console.log("analyticsSummary.tableData:");
- // console.log(analyticsSummary.tableData);
- // console.log("tableDataPrev:");
- // console.log(tableDataPrev);
- // console.log(filteredSessionsCurrent);
-
- await this.calculationSummaryData(tableDataPrev, analyticsSummary.tableData, analyticsSummary.summaryData, jerseyIds);
+ await this.calculationForSessions(
+ filteredSessionsCurrent,
+ analyticsSummary.tableData
+ );
+ await this.calculationForSessions(
+ filteredSessionsPrevious,
+ tableDataPrev
+ );
+ console.log("analyticsSummary.tableData:");
+ console.log(analyticsSummary.tableData);
+ console.log("tableDataPrev:");
+ console.log(tableDataPrev);
+ console.log(filteredSessionsCurrent);
+
+ await this.calculationSummaryData(
+ tableDataPrev,
+ analyticsSummary.tableData,
+ analyticsSummary.summaryData,
+ jerseyIds
+ );
console.log("analyticsSummary:");
console.log(analyticsSummary);
@@ -268,9 +350,8 @@ class ManagersInTeamService {
async calculationForSessions(
sessions: SessionResponse[],
tableData: AnalyticsSummaryTeam["tableData"]
- ): Promise {
- try{
-
+ ): Promise {
+ try {
for (const playerData of tableData) {
// console.log(Number(jerseyId));
// let playerData = tableData[jerseyId];
@@ -280,29 +361,28 @@ class ManagersInTeamService {
// } else {
// continue;
// }
-
+
// console.log(playerData);
let directionCount: {
- front: number,
- back: number,
- left: number,
- right: number
+ Front: number;
+ Back: number;
+ Left: number;
+ Right: number;
} = {
- front: 0,
- back: 0,
- left: 0,
- right: 0
+ Front: 0,
+ Back: 0,
+ Left: 0,
+ Right: 0,
};
-
+
// For each session
for (const session of sessions) {
// console.log("Session: " + session.sessionId);
// console.log(session.impactHistory);
for (const impactPlayer of session.impactHistory) {
// console.log(impactPlayer.jerseyId, Number(jerseyId));
- if (impactPlayer.jerseyId === playerData.jersey_number ){
-
+ if (impactPlayer.jerseyId === playerData.jersey_number) {
// For each impact in the impact Player
for (const impact of impactPlayer.impact) {
playerData.impacts_recorded += 1;
@@ -311,8 +391,12 @@ class ManagersInTeamService {
playerData.highest_impact = impact.magnitude;
}
- playerData.average_impact = playerData.cumulative_impact / playerData.impacts_recorded;
- directionCount[impact.direction as keyof typeof directionCount] += 1;
+ playerData.average_impact =
+ playerData.cumulative_impact / playerData.impacts_recorded;
+
+ directionCount[
+ impact.direction as keyof typeof directionCount
+ ] += 1;
// console.log(playerData)
// console.log(directionCount);
@@ -329,16 +413,25 @@ class ManagersInTeamService {
playerData.average_impact = Math.round(playerData.average_impact);
if (playerData.impacts_recorded > 0) {
- // Find the dominant direction
+ // Find the dominant direction
const maxValueCurr = Math.max(...Object.values(directionCount));
- const maxKeyCurr = Object.keys(directionCount).find(key => directionCount[key as keyof typeof directionCount] === maxValueCurr);
+ const maxKeyCurr = Object.keys(directionCount).find(
+ (key) =>
+ directionCount[key as keyof typeof directionCount] ===
+ maxValueCurr
+ );
playerData.dominant_direction = maxKeyCurr as ImpactDirection;
+ console.log("maxValueCurr: " + maxValueCurr);
+ console.log("maxKeyCurr: " + maxKeyCurr);
+ console.log(
+ "playerData.dominant_direction: " + playerData.dominant_direction
+ );
}
-
- // console.log(playerData);
+ console.log("playerData:");
+ console.log(playerData);
}
- }catch (error) {
+ } catch (error) {
console.error(error);
throw new Error("Error while fetching teams for player");
}
@@ -349,11 +442,10 @@ class ManagersInTeamService {
tableData: AnalyticsSummaryTeam["tableData"],
summaryData: AnalyticsSummaryTeam["summaryData"],
jerseyIds: number[]
- ): Promise {
- try{
-
+ ): Promise {
+ try {
let highestImpactsRecorded = 0;
- let playerNameWithHighestImpactsRecorded = '';
+ let playerNameWithHighestImpactsRecorded = "";
let summaryDataPrev = [
{
title: "Sessions",
@@ -372,23 +464,28 @@ class ManagersInTeamService {
},
{
title: "Highest Contributor",
- value: 0
- }
+ value: 0,
+ },
];
// Fill up values for summary data;
for (const jerseyId of jerseyIds) {
-
- const playerData = tableData.find((entry) => entry.jersey_number === jerseyId);
- const playerDataPrev = tableDataPrev.find((entry) => entry.jersey_number === jerseyId);
+ const playerData = tableData.find(
+ (entry: { jersey_number: number }) => entry.jersey_number === jerseyId
+ );
+ const playerDataPrev = tableDataPrev.find(
+ (entry: { jersey_number: number }) => entry.jersey_number === jerseyId
+ );
// Fill up summary data value ==> Sessions (already filled earlier)
// Fill up summary data value ==> Impacts Recorded
if (playerData) {
- summaryData[1].value = Number(summaryData[1].value) + playerData.impacts_recorded;
+ summaryData[1].value =
+ Number(summaryData[1].value) + playerData.impacts_recorded;
}
if (playerDataPrev) {
- summaryDataPrev[1].value = Number(summaryDataPrev[1].value) + playerDataPrev.impacts_recorded;
+ summaryDataPrev[1].value =
+ Number(summaryDataPrev[1].value) + playerDataPrev.impacts_recorded;
}
// Fill up summary data value ==> Contributors
@@ -401,15 +498,16 @@ class ManagersInTeamService {
}
// Fill up summary data value ==> Highest Contributor
- if (playerData && playerData.impacts_recorded > highestImpactsRecorded) {
+ if (
+ playerData &&
+ playerData.impacts_recorded > highestImpactsRecorded
+ ) {
highestImpactsRecorded = playerData.impacts_recorded;
playerNameWithHighestImpactsRecorded = playerData.name;
}
summaryData[3].value = playerNameWithHighestImpactsRecorded;
-
}
-
// Fill up trends
// // Fill up summary data trend ==> Sessions
@@ -418,20 +516,24 @@ class ManagersInTeamService {
// }
// Fill up summary data trend ==> Impacts Recorded
- if (summaryDataPrev[1].value > 0){
- summaryData[1].trend = Math.round(((Number(summaryData[1].value) - summaryDataPrev[1].value)*100/summaryDataPrev[1].value));
+ if (summaryDataPrev[1].value > 0) {
+ summaryData[1].trend = Math.round(
+ ((Number(summaryData[1].value) - summaryDataPrev[1].value) * 100) /
+ summaryDataPrev[1].value
+ );
}
// Fill up summary data trend ==> Contributors
- if (summaryDataPrev[2].value > 0){
- summaryData[2].trend = Math.round(((Number(summaryData[2].value) - summaryDataPrev[2].value)*100/summaryDataPrev[2].value));
+ if (summaryDataPrev[2].value > 0) {
+ summaryData[2].trend = Math.round(
+ ((Number(summaryData[2].value) - summaryDataPrev[2].value) * 100) /
+ summaryDataPrev[2].value
+ );
}
-
- }catch (error) {
+ } catch (error) {
console.error(error);
throw new Error("Error while calculation summary data");
}
}
-
}
export default new ManagersInTeamService();
diff --git a/code/backend/src/services/player.service.ts b/code/backend/src/services/player.service.ts
index 7a436b34..ee290b72 100644
--- a/code/backend/src/services/player.service.ts
+++ b/code/backend/src/services/player.service.ts
@@ -1,10 +1,18 @@
import PlayerModel from "../db/player.schema";
import authService from "./auth.service";
import { PlayerRequestBody, PlayerResponse } from "../models/player.model";
-import { TeamResponseWithIsVerified, TeamResponseWithJerseyId } from "../models/team.model";
+import {
+ TeamResponseWithIsVerified,
+ TeamResponseWithJerseyId,
+} from "../models/team.model";
import PlayerTeamModel from "../db/players.in.team.schema";
import TeamModel from "../db/team.schema";
-import { AnalyticsSummary, ImpactStats, ImpactDirection, SessionAnalytics } from "../types/types";
+import {
+ AnalyticsSummary,
+ ImpactStats,
+ ImpactDirection,
+ SessionAnalytics,
+} from "../types/types";
import { Impact, ImpactPlayer, SessionResponse } from "../models/session.model";
import SessionModel from "../db/session.schema";
@@ -38,16 +46,13 @@ class PlayerService {
}
// Is this use?
- async addPlayer(
- firstName: string,
- lastName: string,
- email: string,) {
+ async addPlayer(firstName: string, lastName: string, email: string) {
try {
const playerInstanceNoPassword = new PlayerModel({
firstName: firstName,
lastName: lastName,
email: email,
- password: null
+ password: null,
});
// Save the player to the database
@@ -58,52 +63,50 @@ class PlayerService {
console.error(error);
throw new Error("Error adding player");
}
-
}
async createPlayer(
- email: string,
+ email: string,
password: string,
invitationToken: string
- ): Promise {
- try {
- const playerInstance = new PlayerModel({
- email: email,
- invitationToken: invitationToken,
- isVerified: "pending",
- });
-
- // Save the player to the database
- const savedPlayer = await playerInstance.save();
+ ): Promise {
+ try {
+ const playerInstance = new PlayerModel({
+ email: email,
+ invitationToken: invitationToken,
+ isVerified: "pending",
+ });
- await authService.createAuth(
- email,
- password,
- );
+ // Save the player to the database
+ const savedPlayer = await playerInstance.save();
+
+ await authService.createAuth(email, password);
// Create a PalyerResponse object
const playerResponse: PlayerResponse = new PlayerResponse(
playerInstance.email,
- playerInstance.isVerified,
+ playerInstance.isVerified
);
-
- return playerResponse;
- } catch (error) {
- console.error(error);
- throw new Error("Error adding player");
- }
-
+
+ return playerResponse;
+ } catch (error) {
+ console.error(error);
+ throw new Error("Error adding player");
+ }
}
- async updatePlayerPassword(email: string, password: string): Promise {
- const player = await PlayerModel.findOne({ email: email });
-
- if (player) {
- const playerResponse = await authService.createAuth(
- player.email,
- password,
- );
- return playerResponse;
- }
- return false;
+ async updatePlayerPassword(
+ email: string,
+ password: string
+ ): Promise {
+ const player = await PlayerModel.findOne({ email: email });
+
+ if (player) {
+ const playerResponse = await authService.createAuth(
+ player.email,
+ password
+ );
+ return playerResponse;
+ }
+ return false;
}
async getPlayer(email: string): Promise {
try {
@@ -118,7 +121,7 @@ class PlayerService {
// Create a PlayerResponse object
const playerResponse = new PlayerResponse(
playerInstance.email,
- playerInstance.isVerified,
+ playerInstance.isVerified
);
return playerResponse;
@@ -128,29 +131,48 @@ class PlayerService {
}
}
- async getTeamsForPlayer(email: string): Promise> {
+ async getTeamsForPlayer(
+ email: string
+ ): Promise> {
try {
// Fetch playerTeams
- const playerTeams = await PlayerTeamModel.find({ playerEmail: email }, 'teamId isVerified');
-
+ const playerTeams = await PlayerTeamModel.find(
+ { playerEmail: email },
+ "teamId isVerified"
+ );
+
if (playerTeams.length === 0) {
return [];
}
- const teamIds = playerTeams.map(playerTeam => playerTeam.teamId);
-
+ const teamIds = playerTeams.map((playerTeam) => playerTeam.teamId);
+
// Fetch teams from TeamModel
- const teams = await TeamModel.find({ teamId: { $in: teamIds } }, 'teamId teamName isVerified -_id');
+ const teams = await TeamModel.find(
+ { teamId: { $in: teamIds } },
+ "teamId teamName isVerified -_id"
+ );
const teamsWithIsVerified: Array = teams
- .map(team => {
- const matchingPlayerTeam = playerTeams.find(playerTeam => playerTeam.teamId === team.teamId);
+ .map((team) => {
+ const matchingPlayerTeam = playerTeams.find(
+ (playerTeam) => playerTeam.teamId === team.teamId
+ );
return matchingPlayerTeam
- ? new TeamResponseWithIsVerified(team.teamId, team.teamName, matchingPlayerTeam.isVerified)
+ ? new TeamResponseWithIsVerified(
+ team.teamId,
+ team.teamName,
+ matchingPlayerTeam.isVerified
+ )
: null;
})
- .filter((teamWithIsVerified): teamWithIsVerified is TeamResponseWithIsVerified => teamWithIsVerified !== null);
-
+ .filter(
+ (
+ teamWithIsVerified
+ ): teamWithIsVerified is TeamResponseWithIsVerified =>
+ teamWithIsVerified !== null
+ );
+
console.log(teamsWithIsVerified);
return teamsWithIsVerified;
} catch (error) {
@@ -158,86 +180,101 @@ class PlayerService {
throw new Error("Error while fetching teams for player");
}
}
-
- async getAnalyticsSummary(email: string, duration:number): Promise{
+ async getAnalyticsSummary(
+ email: string,
+ duration: number
+ ): Promise {
let analyticsSummary: AnalyticsSummary = {
summaryData: [
{
title: "Cumulative Impacts",
value: 0,
- trend: '--',
+ trend: "--",
},
{
title: "Impacts Recorded",
value: 0,
- trend: '--',
+ trend: "--",
},
{
title: "Average Impact",
value: 0,
- trend: '--',
+ trend: "--",
},
{
title: "Highest Impact",
value: 0,
- trend: '--',
+ trend: "--",
},
{
title: "Dominant Direction",
- value: '--',
- trend: '--',
- }
+ value: "--",
+ trend: "--",
+ },
],
histogramData: {
- left: new Array(10).fill(0),
- right: new Array(10).fill(0),
- front: new Array(10).fill(0),
- back: new Array(10).fill(0),
+ Left: new Array(10).fill(0),
+ Right: new Array(10).fill(0),
+ Front: new Array(10).fill(0),
+ Back: new Array(10).fill(0),
},
criticalSessions: [],
};
- try{
-
+ try {
// Fetch playerTeams
- const playerTeams = await PlayerTeamModel.find({ playerEmail: email }, 'teamId jerseyId');
-
+ const playerTeams = await PlayerTeamModel.find(
+ { playerEmail: email },
+ "teamId jerseyId"
+ );
+
if (playerTeams.length === 0) {
// Should be change after finish this all
// return [];
console.log("No teams found for player");
}
- const teamIds = playerTeams.map(playerTeam => playerTeam.teamId);
-
+ const teamIds = playerTeams.map((playerTeam) => playerTeam.teamId);
+
// Fetch teams from TeamModel
- const teams = await TeamModel.find({ teamId: { $in: teamIds } }, 'teamId jerseyId -_id');
+ const teams = await TeamModel.find(
+ { teamId: { $in: teamIds } },
+ "teamId jerseyId -_id"
+ );
//Array of player's Team id and jerseyId in the team
const teamResponsesWithJerseyId: Array = teams
- .map(team => {
- const matchingPlayerTeam = playerTeams.find(playerTeam => playerTeam.teamId === team.teamId);
+ .map((team) => {
+ const matchingPlayerTeam = playerTeams.find(
+ (playerTeam) => playerTeam.teamId === team.teamId
+ );
return matchingPlayerTeam
- ? new TeamResponseWithJerseyId(team.teamId, matchingPlayerTeam.jerseyId)
+ ? new TeamResponseWithJerseyId(
+ team.teamId,
+ matchingPlayerTeam.jerseyId
+ )
: null;
})
- .filter((teamWithJerseyId): teamWithJerseyId is TeamResponseWithJerseyId => teamWithJerseyId !== null);
-
- // console.log(teamResponsesWithJerseyId);
-
+ .filter(
+ (teamWithJerseyId): teamWithJerseyId is TeamResponseWithJerseyId =>
+ teamWithJerseyId !== null
+ );
+
+ console.log(teamResponsesWithJerseyId);
+
// Initialize To store Impact stats for previous and current duration
let impactStatsPrev: ImpactStats = {
impactsCumulative: 0,
impactsRecorded: 0,
highestImpact: 0,
directionCount: {
- front: 0,
- back: 0,
- left: 0,
- right: 0
+ Front: 0,
+ Back: 0,
+ Left: 0,
+ Right: 0,
},
- sessionAnalytics: []
+ sessionAnalytics: [],
};
let impactStatsCurr: ImpactStats = {
@@ -245,22 +282,24 @@ class PlayerService {
impactsRecorded: 0,
highestImpact: 0,
directionCount: {
- front: 0,
- back: 0,
- left: 0,
- right: 0
+ Front: 0,
+ Back: 0,
+ Left: 0,
+ Right: 0,
},
- sessionAnalytics: []
+ sessionAnalytics: [],
};
// Flag to check whether player has at least one impact in the previous and current duration
- let flagPrev: boolean = false;
- let flagCurrent: boolean = false;
+ const flagsObject = {
+ flagPrev: false,
+ flagCurr: false,
+ };
// Get Time period need to be get analytics
- const now = Date.now();
- const previous= now - (2 * duration); // timestamp of 2 * duration ago
- const current= now - (duration); // timestamp of 2 * duration ago
+ const now = Date.now();
+ const previous = now - 2 * duration; // timestamp of 2 * duration ago
+ const current = now - duration; // timestamp of 2 * duration ago
//get sessions by teamId in teamResponsesWithJerseyId
for (const team of teamResponsesWithJerseyId) {
@@ -269,320 +308,369 @@ class PlayerService {
let sessions: Array = [];
sessions = sessions.concat(await getSessionsForTeam(team.teamId));
-
-
- // console.log(team.teamId, sessions );
+ console.log(team.teamId, sessions);
let filteredSessionsPrevious: Array = [];
-
- if (previous>=0){
- filteredSessionsPrevious = sessions.filter(session => {
+
+ if (previous >= 0) {
+ filteredSessionsPrevious = sessions.filter((session) => {
const createdAt = new Date(session.createdAt).getTime();
return createdAt >= previous && createdAt <= current;
});
- impactStatsPrev = await calculationForSessionsPrev(filteredSessionsPrevious, impactStatsPrev, team.jerseyId, flagPrev);
+ impactStatsPrev = await calculationForSessionsPrev(
+ filteredSessionsPrevious,
+ impactStatsPrev,
+ team.jerseyId,
+ flagsObject
+ );
// console.log("impactStatsPrev:", flagPrev);
}
- // console.log("Previous" + team.teamId );
- // console.log(filteredSessionsPrevious);
-
-
- const filteredSessionsCurrent = sessions.filter(session => {
+ console.log("Previous" + team.teamId);
+ console.log(filteredSessionsPrevious);
+
+ const filteredSessionsCurrent = sessions.filter((session) => {
const createdAt = new Date(session.createdAt).getTime();
return createdAt >= current && createdAt <= now;
});
- // console.log("Current" + team.teamId );
- // console.log(filteredSessionsCurrent);
-
-
-
+ console.log("Current" + team.teamId);
+ console.log(filteredSessionsCurrent);
impactStatsCurr = await calculationForSessions(
- filteredSessionsCurrent,
- impactStatsCurr,
- team.jerseyId,
+ filteredSessionsCurrent,
+ impactStatsCurr,
+ team.jerseyId,
analyticsSummary.histogramData,
analyticsSummary.criticalSessions,
- flagCurrent);
-
- // console.log("impactStatsCurr:", flagCurrent);
-
-
+ flagsObject
+ );
+ console.log("After calling calculationForSessions");
+ console.log("FLAGCurr:", flagsObject.flagCurr);
}
-
- if (flagPrev || flagCurrent){
+
+ console.log("FLAGPrev:", flagsObject.flagPrev);
+
+ if (flagsObject.flagPrev || flagsObject.flagCurr) {
+ console.log("flagPrev || flagCurrent");
// Fill up the analytics summary from impact stats ==> values
- analyticsSummary.summaryData[0].value = impactStatsCurr.impactsCumulative;
+ analyticsSummary.summaryData[0].value =
+ impactStatsCurr.impactsCumulative;
analyticsSummary.summaryData[1].value = impactStatsCurr.impactsRecorded;
- analyticsSummary.summaryData[2].value = Math.round(impactStatsCurr.impactsCumulative / impactStatsCurr.impactsRecorded);
+ analyticsSummary.summaryData[2].value = Math.round(
+ impactStatsCurr.impactsCumulative / impactStatsCurr.impactsRecorded
+ );
analyticsSummary.summaryData[3].value = impactStatsCurr.highestImpact;
-
- const allValuesZero = Object.values(impactStatsCurr.directionCount).every((value) => value === 0);
-
- if (!allValuesZero){
- const maxValueCurr = Math.max(...Object.values(impactStatsCurr.directionCount));
- const maxKeyCurr = Object.keys(impactStatsCurr.directionCount).find(key => impactStatsCurr.directionCount[key as keyof typeof impactStatsCurr.directionCount] === maxValueCurr);
+ const allValuesZero = Object.values(
+ impactStatsCurr.directionCount
+ ).every((value) => value === 0);
+
+ if (!allValuesZero) {
+ const maxValueCurr = Math.max(
+ ...Object.values(impactStatsCurr.directionCount)
+ );
+ const maxKeyCurr = Object.keys(impactStatsCurr.directionCount).find(
+ (key) =>
+ impactStatsCurr.directionCount[
+ key as keyof typeof impactStatsCurr.directionCount
+ ] === maxValueCurr
+ );
analyticsSummary.summaryData[4].value = maxKeyCurr as string;
}
-
// All time no need of trend
- if (previous>=0){
-
-
+ if (previous >= 0 && flagsObject.flagPrev) {
// Fill up the analytics summary from impact stats ==> trends
- analyticsSummary.summaryData[0].trend = Math.round((impactStatsCurr.impactsCumulative - impactStatsPrev.impactsCumulative)*100/impactStatsPrev.impactsCumulative);
- analyticsSummary.summaryData[1].trend = Math.round((impactStatsCurr.impactsRecorded - impactStatsPrev.impactsRecorded)*100/impactStatsPrev.impactsRecorded);
-
- const averageImpactPrev = impactStatsPrev.impactsCumulative / impactStatsPrev.impactsRecorded;
- const averageImpactCurr = impactStatsCurr.impactsCumulative / impactStatsCurr.impactsRecorded;
- analyticsSummary.summaryData[2].trend = Math.round((averageImpactCurr - averageImpactPrev)*100/averageImpactPrev);
- analyticsSummary.summaryData[3].trend = Math.round((impactStatsCurr.highestImpact - impactStatsPrev.highestImpact)*100/impactStatsPrev.highestImpact);
-
- const allValuesZero = Object.values(impactStatsCurr.directionCount).every((value) => value === 0);
-
- if (!allValuesZero){
-
- const maxValuePrev = Math.max(...Object.values(impactStatsPrev.directionCount));
- const maxKeyPrev = Object.keys(impactStatsPrev.directionCount).find(key => impactStatsPrev.directionCount[key as keyof typeof impactStatsPrev.directionCount] === maxValuePrev);
- analyticsSummary.summaryData[4].trend = maxKeyPrev as ImpactDirection;
+ analyticsSummary.summaryData[0].trend = Math.round(
+ ((impactStatsCurr.impactsCumulative -
+ impactStatsPrev.impactsCumulative) *
+ 100) /
+ impactStatsPrev.impactsCumulative
+ );
+ analyticsSummary.summaryData[1].trend = Math.round(
+ ((impactStatsCurr.impactsRecorded -
+ impactStatsPrev.impactsRecorded) *
+ 100) /
+ impactStatsPrev.impactsRecorded
+ );
+
+ const averageImpactPrev =
+ impactStatsPrev.impactsCumulative / impactStatsPrev.impactsRecorded;
+ const averageImpactCurr =
+ impactStatsCurr.impactsCumulative / impactStatsCurr.impactsRecorded;
+ analyticsSummary.summaryData[2].trend = Math.round(
+ ((averageImpactCurr - averageImpactPrev) * 100) / averageImpactPrev
+ );
+ analyticsSummary.summaryData[3].trend = Math.round(
+ ((impactStatsCurr.highestImpact - impactStatsPrev.highestImpact) *
+ 100) /
+ impactStatsPrev.highestImpact
+ );
+
+ const allValuesZero = Object.values(
+ impactStatsCurr.directionCount
+ ).every((value) => value === 0);
+
+ if (!allValuesZero) {
+ const maxValuePrev = Math.max(
+ ...Object.values(impactStatsPrev.directionCount)
+ );
+ const maxKeyPrev = Object.keys(impactStatsPrev.directionCount).find(
+ (key) =>
+ impactStatsPrev.directionCount[
+ key as keyof typeof impactStatsPrev.directionCount
+ ] === maxValuePrev
+ );
+ analyticsSummary.summaryData[4].trend =
+ maxKeyPrev as ImpactDirection;
// console.log("maxKey:");
// console.log(maxKeyPrev, maxValuePrev);
-
- // Sort the critical sessions array by cumulative impact in descending order
- analyticsSummary["criticalSessions"].sort((a, b) => b.cumulative - a.cumulative);
+ // Sort the critical sessions array by cumulative impact in descending order
+ analyticsSummary["criticalSessions"].sort(
+ (a, b) => b.cumulative - a.cumulative
+ );
}
// console.log( analyticsSummary["criticalSessions"]);
// console.log("analyticsSummary:");
// console.log(analyticsSummary);
-
-
- }else{
- analyticsSummary.summaryData[0].trend = '--';
- analyticsSummary.summaryData[1].trend = '--';
- analyticsSummary.summaryData[2].trend = '--';
- analyticsSummary.summaryData[3].trend = '--';
- analyticsSummary.summaryData[4].trend = '--';
+ } else {
+ analyticsSummary.summaryData[0].trend = "--";
+ analyticsSummary.summaryData[1].trend = "--";
+ analyticsSummary.summaryData[2].trend = "--";
+ analyticsSummary.summaryData[3].trend = "--";
+ analyticsSummary.summaryData[4].trend = "--";
}
-
- }else{
+ } else {
analyticsSummary.criticalSessions = [];
}
-
+ console.log("analyticsSummary:");
return analyticsSummary;
-}catch (error) {
+ } catch (error) {
console.error(error);
throw new Error("Error while fetching teams for player");
}
- }
+ }
}
- // Map the sessions to SessionResponse objects
- async function getSessionsForTeam(teamId: string): Promise> {
- try {
- // Fetch sessions from the database
- const sessions = await SessionModel.find({ teamId });
-
- // Map the sessions to SessionResponse objects
- const sessionResponses = sessions.map(session => {
- return new SessionResponse(
- session.teamId,
- session.sessionId,
- session.sessionName,
- session.createdAt,
- session.updatedAt,
- session.impactHistory.map(player => {
- return new ImpactPlayer(
- player.jerseyId,
- player.impact.map(impact => {
- return new Impact(
- impact.magnitude,
- impact.direction,
- impact.timestamp,
- impact.isConcussion
- );
- })
- );
- })
- );
- });
-
- return sessionResponses;
- } catch (error) {
- console.error(error);
- throw new Error("Error while fetching sessions for team");
- }
+// Map the sessions to SessionResponse objects
+async function getSessionsForTeam(
+ teamId: string
+): Promise> {
+ try {
+ // Fetch sessions from the database
+ const sessions = await SessionModel.find({ teamId });
+
+ // Map the sessions to SessionResponse objects
+ const sessionResponses = sessions.map((session) => {
+ return new SessionResponse(
+ session.teamId,
+ session.sessionId,
+ session.sessionName,
+ session.createdAt,
+ session.updatedAt,
+ session.impactHistory.map((player) => {
+ return new ImpactPlayer(
+ player.jerseyId,
+ player.impact.map((impact) => {
+ return new Impact(
+ impact.magnitude,
+ impact.direction,
+ impact.timestamp,
+ impact.isConcussion
+ );
+ })
+ );
+ })
+ );
+ });
+
+ return sessionResponses;
+ } catch (error) {
+ console.error(error);
+ throw new Error("Error while fetching sessions for team");
}
+}
- //Calculate the analytics for each sesseions
- async function calculationForSessions(
- sessions: Array,
- stats: ImpactStats,
- jerseyId: Number,
- histogramData: AnalyticsSummary["histogramData"],
- criticalSessions: AnalyticsSummary["criticalSessions"],
- flagCurrent: boolean
- ): Promise {
- try{
-
- // console.log("Curr#####");
- // For each session
- for (const session of sessions) {
- // console.log("Session: " + session.sessionId);
-
- //For storing session analytics
- let sessionAnalyticsItem: SessionAnalytics = {
- name: session.sessionName,
- date: new Date(session.createdAt).toLocaleDateString("en-US", {
-
- day: "numeric",
- month: "short",
- year: "numeric",
- }),
- cumulative: 0,
- average: 0,
- highest: 0,
- };
-
- let impactCountForSession:number = 0;
- for (const impactPlayer of session.impactHistory) {
-
- // console.log(impactPlayer.jerseyId, jerseyId)
- if (impactPlayer.jerseyId === jerseyId) {
-
- // Player has at least one impact in the current duration
- flagCurrent = true;
-
- // For each impact in the impact Player
- for (const impact of impactPlayer.impact) {
-
- //Session Analytics
- impactCountForSession += 1;
- // console.log("impactCountForSession: " + impactCountForSession);
-
- sessionAnalyticsItem.cumulative += impact.magnitude;
- // console.log("sessionAnalyticsItem.cumulative: " + sessionAnalyticsItem.cumulative);
-
- if (sessionAnalyticsItem.highest < impact.magnitude){
- sessionAnalyticsItem.highest = impact.magnitude;
- // console.log("sessionAnalyticsItem.highest: " + sessionAnalyticsItem.highest);
- }
-
- sessionAnalyticsItem.average = sessionAnalyticsItem.cumulative/impactCountForSession;
- // console.log("sessionAnalyticsItem.average: " + sessionAnalyticsItem.average);
-
- // console.log("sessionAnalyticsItem###########3:")
- // console.log(sessionAnalyticsItem);
-
- // Update the impact stats
- stats.impactsCumulative += impact.magnitude;
- // console.log("stats.impactsCumulative: " + stats.impactsCumulative);
-
- stats.impactsRecorded += 1;
- // console.log("stats.impactsRecorded: " + stats.impactsRecorded);
- if (stats.highestImpact < impact.magnitude) {
-
- stats.highestImpact = impact.magnitude;
- // console.log("stats.highestImpact: " + stats.highestImpact);
- }
- stats.directionCount[impact.direction as keyof typeof stats.directionCount] += 1;
- // console.log("stats.directionCount: " + stats.directionCount);
-
- const index = Math.floor(impact.magnitude / 20);
- // console.log("index: " + index);
-
- histogramData[impact.direction as keyof typeof histogramData][index] += 1;
- // console.log("histogramData:");
- // console.log(impact.magnitude, impact.direction);
- // console.log(histogramData);
-
-
- // console.log(stats)
+//Calculate the analytics for each sesseions
+async function calculationForSessions(
+ sessions: Array,
+ stats: ImpactStats,
+ jerseyId: Number,
+ histogramData: AnalyticsSummary["histogramData"],
+ criticalSessions: AnalyticsSummary["criticalSessions"],
+ flagsObject: { flagCurr: boolean; flagPrev: boolean }
+): Promise {
+ try {
+ console.log("Curr#####");
+ // For each session
+ for (const session of sessions) {
+ // console.log("Session: " + session.sessionId);
+
+ //For storing session analytics
+ let sessionAnalyticsItem: SessionAnalytics = {
+ name: session.sessionName,
+ date: new Date(session.createdAt).toLocaleDateString("en-US", {
+ day: "numeric",
+ month: "short",
+ year: "numeric",
+ }),
+ cumulative: 0,
+ average: 0,
+ highest: 0,
+ };
+
+ let impactCountForSession: number = 0;
+ for (const impactPlayer of session.impactHistory) {
+ console.log(impactPlayer.jerseyId, jerseyId);
+ if (impactPlayer.jerseyId === jerseyId) {
+ // Player has at least one impact in the current duration
+ console.log("impactPlayer.jerseyId, jerseyId Current");
+
+ flagsObject.flagCurr = true;
+ console.log("flagCurrebt:" + flagsObject.flagCurr);
+ // For each impact in the impact Player
+ for (const impact of impactPlayer.impact) {
+ //Session Analytics
+ impactCountForSession += 1;
+ // console.log("impactCountForSession: " + impactCountForSession);
+
+ sessionAnalyticsItem.cumulative += impact.magnitude;
+ // // console.log(
+ // "sessionAnalyticsItem.cumulative: " +
+ // sessionAnalyticsItem.cumulative
+ // );
+
+ if (sessionAnalyticsItem.highest < impact.magnitude) {
+ sessionAnalyticsItem.highest = impact.magnitude;
+ // console.log(
+ // "sessionAnalyticsItem.highest: " + sessionAnalyticsItem.highest
+ // );
}
- // console.log("End of each impact in the impact Player Loop");
- // Round off the average impact
-
- }
+ sessionAnalyticsItem.average =
+ sessionAnalyticsItem.cumulative / impactCountForSession;
+ console.log(
+ "sessionAnalyticsItem.average: " + sessionAnalyticsItem.average
+ );
+ console.log("sessionAnalyticsItem###########3:");
+ // console.log(sessionAnalyticsItem);
- }
+ // Update the impact stats
+ stats.impactsCumulative += impact.magnitude;
+ // console.log("stats.impactsCumulative: " + stats.impactsCumulative);
- sessionAnalyticsItem.average = Math.round(sessionAnalyticsItem.average);
- // console.log("sessionAnalyticsItem.average: " + sessionAnalyticsItem.average);
+ stats.impactsRecorded += 1;
+ // console.log("stats.impactsRecorded: " + stats.impactsRecorded);
+ if (stats.highestImpact < impact.magnitude) {
+ stats.highestImpact = impact.magnitude;
+ // console.log("stats.highestImpact: " + stats.highestImpact);
+ }
+ stats.directionCount[
+ impact.direction as keyof typeof stats.directionCount
+ ] += 1;
+ console.log("stats.directionCount: " + stats.directionCount);
+
+ const index = Math.floor(impact.magnitude / 20);
+ // console.log("index: " + index);
+ // console.log(impact.direction as keyof typeof histogramData);
+
+ histogramData[impact.direction as keyof typeof histogramData][
+ index
+ ] += 1;
+ // console.log(histogramData);
+ // console.log("histogramData:");
+ // console.log(impact.magnitude, impact.direction);
+ // console.log(histogramData);
+
+ // console.log(stats);
+ }
+ console.log("End of each impact in the impact Player Loop");
+ console.log("flagCurrebt:" + flagsObject.flagCurr);
+ // Round off the average impact
+ }
+ }
- // console.log("End of each impactPlayer in the session Loop");
-
- // If length of crirtical sessions<3 => directly push to the critical sessions
- // Else: sort by cumulative impact => remove the least one and push only if least directly push to the critical sessions
+ // Else: sort by cumulative impact => remove the least one and push only if least b.cumulative - a.cumulative);
+ console.log(sessionAnalyticsItem);
+
+ if (
+ sessionAnalyticsItem.cumulative >
+ criticalSessions[criticalSessions.length - 1].cumulative
+ ) {
+ criticalSessions.pop();
criticalSessions.push(sessionAnalyticsItem);
-
- }else {
- // Sort the critical sessions array by cumulative impact in descending order
- criticalSessions.sort((a, b) => b.cumulative - a.cumulative);
- //console.log(sessionAnalyticsItem);
-
- if (sessionAnalyticsItem.cumulative > criticalSessions[criticalSessions.length - 1].cumulative) {
- criticalSessions.pop();
- criticalSessions.push(sessionAnalyticsItem);
- }
}
}
- // console.log(criticalSessions);
}
- return stats;
- }catch (error) {
- console.error(error);
- throw new Error("Error while fetching teams for player");
+ // console.log(criticalSessions);
}
+ return stats;
+ } catch (error) {
+ console.error(error);
+ throw new Error("Error while fetching teams for player");
}
+}
- //Calculate the analytics for each sesseions for previous
- async function calculationForSessionsPrev(
- sessions: Array,
- stats: ImpactStats,
- jerseyId: Number,
- flagPrev: boolean
- ): Promise {
- try{
- // console.log("Previous##")
- // console.log(sessions);
- for (const session of sessions) {
- // console.log("Session: " + session.sessionId);
- for (const impactPlayer of session.impactHistory) {
- if (impactPlayer.jerseyId === jerseyId) {
-
- // Player has at least one impact in the previous duration
- flagPrev = true;
- // For each impact in the impact Player
- for (const impact of impactPlayer.impact) {
-
- // Update the impact stats
- stats.impactsCumulative += impact.magnitude;
- stats.impactsRecorded += 1;
- if (stats.highestImpact < impact.magnitude) {
- stats.highestImpact = impact.magnitude;
- }
- stats.directionCount[impact.direction as keyof typeof stats.directionCount] += 1;
-
-
- // console.log(stats)
+//Calculate the analytics for each sesseions for previous
+async function calculationForSessionsPrev(
+ sessions: Array,
+ stats: ImpactStats,
+ jerseyId: Number,
+ flagsObject: { flagCurr: boolean; flagPrev: boolean }
+): Promise {
+ try {
+ // console.log("Previous##")
+ // console.log(sessions);
+ for (const session of sessions) {
+ // console.log("Session: " + session.sessionId);
+ for (const impactPlayer of session.impactHistory) {
+ console.log("impactPlayer.jerseyId, jerseyId");
+ console.log(impactPlayer.jerseyId, jerseyId);
+ if (impactPlayer.jerseyId === jerseyId) {
+ // Player has at least one impact in the previous duration
+ flagsObject.flagPrev = true;
+ // For each impact in the impact Player
+ for (const impact of impactPlayer.impact) {
+ // Update the impact stats
+ stats.impactsCumulative += impact.magnitude;
+ stats.impactsRecorded += 1;
+ if (stats.highestImpact < impact.magnitude) {
+ stats.highestImpact = impact.magnitude;
}
+ stats.directionCount[
+ impact.direction as keyof typeof stats.directionCount
+ ] += 1;
+
+ // console.log(stats)
}
}
}
- return stats;
- }catch (error) {
- console.error(error);
- throw new Error("Error while fetching teams for player");
}
+ return stats;
+ } catch (error) {
+ console.error(error);
+ throw new Error("Error while fetching teams for player");
}
+}
export default new PlayerService();
diff --git a/code/backend/src/services/players.in.team.service.ts b/code/backend/src/services/players.in.team.service.ts
index 33f39d1d..9bd31fe2 100644
--- a/code/backend/src/services/players.in.team.service.ts
+++ b/code/backend/src/services/players.in.team.service.ts
@@ -1,6 +1,9 @@
import PlayerModel from "../db/player.schema";
import PlayerTeamModel from "../db/players.in.team.schema";
-import { PlayerInTeamResponse, PlayerTeamRequest } from "../models/player.model";
+import {
+ PlayerInTeamResponse,
+ PlayerTeamRequest,
+} from "../models/player.model";
class PlayerInTeamService {
// create team player instance
@@ -10,7 +13,6 @@ class PlayerInTeamService {
jerseyId: number,
fullName: string,
invitationToken: string
-
): Promise {
try {
// check entry exists in player in teams
@@ -32,7 +34,6 @@ class PlayerInTeamService {
isVerified: "pending",
});
-
// Save the manager to the database
const savedManager = await playerTeamInstance.save();
const playerInTeamResponse = new PlayerInTeamResponse(
@@ -40,7 +41,7 @@ class PlayerInTeamService {
teamId,
jerseyId,
fullName,
- "pending",
+ "pending"
);
return playerInTeamResponse;
@@ -50,8 +51,6 @@ class PlayerInTeamService {
}
}
-
-
async checkPlayerExistsInTeam(
jerseyId: number,
teamId: string
@@ -73,59 +72,56 @@ class PlayerInTeamService {
return false;
}
async updatePlayerInTeam(
- playerTeamRequest : PlayerTeamRequest
- ): Promise{
- const existingPlayer = await PlayerTeamModel.findOne({
- jerseyId: playerTeamRequest.jerseyId});
-
- if (existingPlayer) {
- // Update properties based on your requirements
- // existingPlayer.playerEmail = playerTeamRequest.playerEmail;
- existingPlayer.jerseyId = playerTeamRequest.jerseyId;
- existingPlayer.fullName = playerTeamRequest.fullName;
-
-
- await existingPlayer.save();
+ playerTeamRequest: PlayerTeamRequest,
+ teamId: string
+ ): Promise {
+ const existingPlayer = await PlayerTeamModel.findOne({
+ teamId: teamId,
+ jerseyId: playerTeamRequest.jerseyId,
+ });
- const playerInTeamResponse = new PlayerInTeamResponse(
- existingPlayer.playerEmail,
- existingPlayer.teamId,
- existingPlayer.jerseyId,
- existingPlayer.fullName,
- existingPlayer.isVerified,
- );
- return playerInTeamResponse;
+ // console.log(existingPlayer);
+ if (existingPlayer) {
+ // Update properties based on your requirements
+ // existingPlayer.playerEmail = playerTeamRequest.playerEmail;
+ existingPlayer.jerseyId = playerTeamRequest.jerseyId;
+ existingPlayer.fullName = playerTeamRequest.fullName;
+ existingPlayer.playerEmail = playerTeamRequest.playerEmail;
- } else {
- // Handle case where player is not found
- throw new Error("Player not found");
+ await existingPlayer.save();
- }
+ const playerInTeamResponse = new PlayerInTeamResponse(
+ existingPlayer.playerEmail,
+ existingPlayer.teamId,
+ existingPlayer.jerseyId,
+ existingPlayer.fullName,
+ existingPlayer.isVerified
+ );
+ return playerInTeamResponse;
+ } else {
+ // Handle case where player is not found
+ throw new Error("Player not found");
+ }
}
- async removePlayerInTeam(
- jerseyId: number,
- teamId: string
- ): Promise{
- try{
-
+ async removePlayerInTeam(jerseyId: number, teamId: string): Promise {
+ try {
const playerInTeam = await PlayerTeamModel.findOne({
teamId: teamId,
- jerseyId: jerseyId
- })
+ jerseyId: jerseyId,
+ });
- if (playerInTeam != null){
+ if (playerInTeam != null) {
await playerInTeam.deleteOne();
return true;
- }else{
- return false
- }
-
- }catch (error) {
- console.error(error);
- throw error;
+ } else {
+ return false;
}
- return false;
+ } catch (error) {
+ console.error(error);
+ throw error;
+ }
+ return false;
}
}
export default new PlayerInTeamService();
diff --git a/code/backend/src/services/team.service.ts b/code/backend/src/services/team.service.ts
index 743bb77b..10d827f0 100644
--- a/code/backend/src/services/team.service.ts
+++ b/code/backend/src/services/team.service.ts
@@ -9,9 +9,14 @@ Team;
import TeamModel from "../db/team.schema";
// import ManagerTeamModel from "../db/managers.in.team.schema";
import managersInTeamService from "./managers.in.team.service";
-import { AnalyticsSummaryTeam, ImpactStats, ImpactDirection } from "../types/types";
+import {
+ AnalyticsSummaryTeam,
+ ImpactStats,
+ ImpactDirection,
+} from "../types/types";
import SessionModel from "../db/session.schema";
import ManagerModel from "../db/manager.schema";
+import authService from "./auth.service";
class TeamService {
// delete team
@@ -43,11 +48,11 @@ class TeamService {
// Save the manager to the database
const savedTeam = await teamInstance.save();
- await managersInTeamService.addManagerToTeam(
- team.teamManager,
- team.teamId,
- "accessToken"
- );
+ // await managersInTeamService.addManagerToTeam(
+ // team.teamManager,
+ // team.teamId,
+ // "accessToken"
+ // );
// Create a TeamResponse object
const teamResponse = new TeamResponse({
@@ -103,18 +108,14 @@ class TeamService {
// }
// Initialize response with both flags set to false
- const teamIdEmailExistsResponseWithIsVerified = new TeamIdEmailExistsResponseWithIsVerified(
- false,
- false,
- "pending"
- );
+ const teamIdEmailExistsResponseWithIsVerified =
+ new TeamIdEmailExistsResponseWithIsVerified(false, false, "pending");
try {
// Check if team exists
// const team = await TeamModel.findOne({ teamId: teamId , managerEmail: email});
// console.log(team, email, teamId);
-
// const teams = await ManagerModel.find({ email: email });
// const team = teams.find(team => team.teamId === teamId);
@@ -123,7 +124,7 @@ class TeamService {
if (team) {
console.log(team);
} else {
- console.log('Team not found');
+ console.log("Team not found");
}
if (team) {
teamIdEmailExistsResponseWithIsVerified.teamExists = true;
@@ -133,9 +134,19 @@ class TeamService {
email: email,
teamId: teamId,
});
+ const managerAuth = await authService.checkAuthExistsForManager(
+ email,
+ teamId
+ );
+
if (manager) {
- teamIdEmailExistsResponseWithIsVerified.managerExists = true;
- teamIdEmailExistsResponseWithIsVerified.isVerified = manager.isVerified;
+ if (!managerAuth) {
+ teamIdEmailExistsResponseWithIsVerified.managerExists = false;
+ } else {
+ teamIdEmailExistsResponseWithIsVerified.managerExists = true;
+ }
+ teamIdEmailExistsResponseWithIsVerified.isVerified =
+ manager.isVerified;
}
}
} catch (error) {
@@ -165,7 +176,5 @@ class TeamService {
return teamIdExistsResponse;
}
-
-
}
export default new TeamService();
diff --git a/code/backend/src/types/types.ts b/code/backend/src/types/types.ts
index 4391b069..55b291fd 100644
--- a/code/backend/src/types/types.ts
+++ b/code/backend/src/types/types.ts
@@ -1,25 +1,25 @@
export type AnalyticsSummary = {
- summaryData: Array<{
- title: string;
- value: string | number;
- trend: number | ImpactDirection | '--';
- }>;
- histogramData: {
- left: number[];
- right: number[];
- front: number[];
- back: number[];
- };
- criticalSessions: Array<{
- name: string;
- date: string;
- cumulative: number;
- average: number;
- highest: number;
- }>;
+ summaryData: Array<{
+ title: string;
+ value: string | number;
+ trend: number | ImpactDirection | "--";
+ }>;
+ histogramData: {
+ Left: number[];
+ Right: number[];
+ Front: number[];
+ Back: number[];
};
-
-export type ImpactDirection = 'left' | 'right' | 'front' | 'back'| 'none';
+ criticalSessions: Array<{
+ name: string;
+ date: string;
+ cumulative: number;
+ average: number;
+ highest: number;
+ }>;
+};
+
+export type ImpactDirection = "Left" | "Right" | "Front" | "Back" | "none";
export type SessionAnalytics = {
name: string;
@@ -30,17 +30,17 @@ export type SessionAnalytics = {
};
export type ImpactStats = {
- impactsCumulative: number;
- impactsRecorded: number;
- highestImpact: number;
- directionCount: {
- front: number;
- back: number;
- left: number;
- right: number;
- };
- sessionAnalytics: SessionAnalytics[];
+ impactsCumulative: number;
+ impactsRecorded: number;
+ highestImpact: number;
+ directionCount: {
+ Front: number;
+ Back: number;
+ Left: number;
+ Right: number;
};
+ sessionAnalytics: SessionAnalytics[];
+};
export type TeamPlayerResponse = {
name: string;
@@ -52,19 +52,16 @@ export type AnalyticsSummaryTeam = {
summaryData: Array<{
title: string;
value: string | number;
- trend?: string | number | '--';
+ trend?: string | number | "--";
}>;
tableData: Array<{
- jersey_number: number;
- name: string;
- impacts_recorded: number;
- average_impact: number;
- highest_impact: number;
- dominant_direction: ImpactDirection;
- cumulative_impact: number;
- concussions: number;
- }>;
+ jersey_number: number;
+ name: string;
+ impacts_recorded: number;
+ average_impact: number;
+ highest_impact: number;
+ dominant_direction: ImpactDirection;
+ cumulative_impact: number;
+ concussions: number;
+ }>;
};
-
-
-
\ No newline at end of file
diff --git a/code/backend/swagger.json b/code/backend/swagger.json
index ccd3356d..f66e4d18 100644
--- a/code/backend/swagger.json
+++ b/code/backend/swagger.json
@@ -19,7 +19,7 @@
"url": "http://localhost:5000"
},
{
- "url": "http://13.235.86.11:5000"
+ "url": "http://16.170.235.219:5000"
}
],
@@ -397,11 +397,43 @@
}
}
},
+
+ "/manager/remove": {
+ "delete": {
+ "tags": ["ManagerEndpoints"],
+ "summary": "Remove a manager from a team by email and Team ID - Access Token required (Only Manager can access)",
+ "requestBody": {
+ "$ref": "#/components/requestBodies/ManagerRemoveRequest"
+ },
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "example": {
+ "message": "Manager removed from team successfully"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request",
+ "content": {
+ "application/json": {
+ "example": {
+ "message": "Bad Request"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/manager/getTeamPlayers": {
"get": {
"tags": ["ManagerEndpoints"],
"summary": "Get all players of a team - Access Token required",
-
+
"responses": {
"200": {
"description": "Success",
@@ -490,9 +522,34 @@
}
}
},
+ "/manager/getTeamManagers": {
+ "get": {
+ "tags": ["ManagerEndpoints"],
+ "summary": "Get all managers of a team - Access Token required",
+ "responses": {
+ "200": {
+ "description": "Success",
+ "content": {
+ "application/json": {
+ "$ref": "#/components/schemas/TeamManagersResponse"
+ }
+ }
+ },
+ "400": {
+ "description": "Bad Request",
+ "content": {
+ "application/json": {
+ "example": {
+ "message": "Bad Request"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
-
"/player": {
"post": {
"tags": ["PlayerEndpoints"],
@@ -524,7 +581,7 @@
"get": {
"tags": ["PlayerEndpoints"],
"summary": "Get player details",
-
+
"responses": {
"200": {
"description": "Success",
@@ -546,7 +603,6 @@
}
}
}
-
},
"/player/myTeams": {
@@ -576,7 +632,7 @@
}
}
},
-
+
"/player/analytics-summary/{duration}": {
"get": {
"tags": ["PlayerEndpoints"],
@@ -658,7 +714,6 @@
"content": {
"application/json": {
"$ref": "#/components/schemas/PlayerResponse"
-
}
}
},
@@ -674,7 +729,7 @@
}
}
}
- },
+ },
"/player/remove": {
"delete": {
"tags": ["PlayerEndpoints"],
@@ -756,11 +811,6 @@
}
}
},
-
-
-
-
-
"/hub/credetials": {
"post": {
@@ -880,7 +930,7 @@
}
}
},
-
+
"/login/player": {
"post": {
"tags": ["LoginEndpoints"],
@@ -1002,16 +1052,10 @@
"type": "string"
},
"value": {
- "anyOf": [
- { "type": "string" },
- { "type": "number" }
- ]
+ "anyOf": [{ "type": "string" }, { "type": "number" }]
},
"trend": {
- "anyOf": [
- { "type": "string" },
- { "type": "number" }
- ]
+ "anyOf": [{ "type": "string" }, { "type": "number" }]
}
}
}
@@ -1019,32 +1063,30 @@
"tableData": {
"type": "object",
"properties": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
- },
- "impactsRecorded": {
- "type": "number"
- },
- "cumulativeImpact": {
- "type": "number"
- },
- "highestImpact": {
- "type": "number"
- },
- "averageImpact": {
- "type": "number"
- },
- "dominantDirection": {
- "type": "number"
- },
- "concussions": {
- "type": "number"
- }
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "impactsRecorded": {
+ "type": "number"
+ },
+ "cumulativeImpact": {
+ "type": "number"
+ },
+ "highestImpact": {
+ "type": "number"
+ },
+ "averageImpact": {
+ "type": "number"
+ },
+ "dominantDirection": {
+ "type": "number"
+ },
+ "concussions": {
+ "type": "number"
}
-
-
+ }
}
}
},
@@ -1077,31 +1119,28 @@
}
],
"tableData": {
- "69": {
- "name": "Angelo Mathews",
- "impactsRecorded": 50,
- "cumulativeImpact": 850,
- "highestImpact": 25,
- "averageImpact": 20,
- "dominantDirection": "Left",
- "concussions": 2
- },
- "55": {
- "name": "Kusal Perera",
- "impactsRecorded": 50,
- "cumulativeImpact": 850,
- "highestImpact": 25,
- "averageImpact": 20,
- "dominantDirection": "Left",
- "concussions": 2
- }
-
+ "69": {
+ "name": "Angelo Mathews",
+ "impactsRecorded": 50,
+ "cumulativeImpact": 850,
+ "highestImpact": 25,
+ "averageImpact": 20,
+ "dominantDirection": "Left",
+ "concussions": 2
+ },
+ "55": {
+ "name": "Kusal Perera",
+ "impactsRecorded": 50,
+ "cumulativeImpact": 850,
+ "highestImpact": 25,
+ "averageImpact": 20,
+ "dominantDirection": "Left",
+ "concussions": 2
+ }
}
-
}
- },
+ },
-
"SessionRequest": {
"type": "object",
"properties": {
@@ -1150,7 +1189,7 @@
}
}
},
-
+
"HubRequest": {
"type": "object",
"properties": {
@@ -1249,9 +1288,29 @@
"email": "kusal_perera@gmail.com",
"verification": "verified"
}
-
}
},
+ "TeamManagersResponse": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "schemas": {
+ "$ref": "#/components/schemas/ManagersResponse"
+ }
+ },
+ "example": [
+ {
+ "name": "Angelo Mathews",
+ "email": "angelomathews@gmail.com",
+ "verification": "verified"
+ },
+ {
+ "name": "Kusal Perera",
+ "email": "kusal_perera@gmail.com",
+ "verification": "verified"
+ }
+ ]
+ },
"Player": {
"type": "object",
@@ -1271,140 +1330,136 @@
}
},
-
"AnalyticsSummary": {
- "type": "object",
- "properties": {
- "summaryData": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "title": {
- "type": "string"
- },
- "value": {
- "anyOf": [
- { "type": "string" },
- { "type": "number" }
- ]
- },
- "trend": {
- "anyOf": [
- { "type": "number" },
- { "$ref": "#/components/schemas/ImpactDirection" }
- ]
- }
- }
- }
- },
- "histogramData": {
+ "type": "object",
+ "properties": {
+ "summaryData": {
+ "type": "array",
+ "items": {
"type": "object",
"properties": {
- "left": {
- "type": "array",
- "items": {
- "type": "number"
- }
- },
- "right": {
- "type": "array",
- "items": {
- "type": "number"
- }
+ "title": {
+ "type": "string"
},
- "front": {
- "type": "array",
- "items": {
- "type": "number"
- }
+ "value": {
+ "anyOf": [{ "type": "string" }, { "type": "number" }]
},
- "back": {
- "type": "array",
- "items": {
- "type": "number"
- }
- }
- }
- },
- "criticalSessions": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "session_name": {
- "type": "string"
- },
- "session_date": {
- "type": "string"
- },
- "cumulative_impact": {
- "type": "number"
- },
- "average_impact": {
- "type": "number"
- },
- "largest_impact": {
- "type": "number"
- }
+ "trend": {
+ "anyOf": [
+ { "type": "number" },
+ { "$ref": "#/components/schemas/ImpactDirection" }
+ ]
}
}
}
},
- "example": {
- "summaryData": [
- {
- "title": "Cumulative Impacts",
- "value": "850 g",
- "trend": -20
+ "histogramData": {
+ "type": "object",
+ "properties": {
+ "left": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
},
- {
- "title": "Impacts Recorded",
- "value": "50",
- "trend": 20
+ "right": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
},
- {
- "title": "Average Impact",
- "value": "43 g",
- "trend": 40
+ "front": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
},
- {
- "title": "Dominant Direction",
- "value": "Left",
- "trend": 10
+ "back": {
+ "type": "array",
+ "items": {
+ "type": "number"
+ }
}
- ],
- "histogramData": {
- "left": [0, 1, 4, 0, 0, 0, 0, 0, 0, 0],
- "right": [0, 1, 4, 0, 0, 0, 0, 0, 0, 0],
- "front": [0, 1, 4, 0, 0, 0, 0, 0, 0, 0],
- "back": [0, 1, 4, 0, 0, 0, 0, 0, 0, 0]
- },
- "criticalSessions": [
- {
- "session_name": "Session 1",
- "session_date": "2024-01-22",
- "cumulative_impact": 50,
- "average_impact": 20,
- "largest_impact": 25
- },
- {
- "session_name": "Session 2",
- "session_date": "2024-01-23",
- "cumulative_impact": 70,
- "average_impact": 20,
- "largest_impact": 20
- },
- {
- "session_name": "Session 3",
- "session_date": "2024-01-24",
- "cumulative_impact": 90,
- "average_impact": 20,
- "largest_impact": 25
+ }
+ },
+ "criticalSessions": {
+ "type": "array",
+ "items": {
+ "type": "object",
+ "properties": {
+ "session_name": {
+ "type": "string"
+ },
+ "session_date": {
+ "type": "string"
+ },
+ "cumulative_impact": {
+ "type": "number"
+ },
+ "average_impact": {
+ "type": "number"
+ },
+ "largest_impact": {
+ "type": "number"
+ }
}
- ]
+ }
}
- },
+ },
+ "example": {
+ "summaryData": [
+ {
+ "title": "Cumulative Impacts",
+ "value": "850 g",
+ "trend": -20
+ },
+ {
+ "title": "Impacts Recorded",
+ "value": "50",
+ "trend": 20
+ },
+ {
+ "title": "Average Impact",
+ "value": "43 g",
+ "trend": 40
+ },
+ {
+ "title": "Dominant Direction",
+ "value": "Left",
+ "trend": 10
+ }
+ ],
+ "histogramData": {
+ "left": [0, 1, 4, 0, 0, 0, 0, 0, 0, 0],
+ "right": [0, 1, 4, 0, 0, 0, 0, 0, 0, 0],
+ "front": [0, 1, 4, 0, 0, 0, 0, 0, 0, 0],
+ "back": [0, 1, 4, 0, 0, 0, 0, 0, 0, 0]
+ },
+ "criticalSessions": [
+ {
+ "session_name": "Session 1",
+ "session_date": "2024-01-22",
+ "cumulative_impact": 50,
+ "average_impact": 20,
+ "largest_impact": 25
+ },
+ {
+ "session_name": "Session 2",
+ "session_date": "2024-01-23",
+ "cumulative_impact": 70,
+ "average_impact": 20,
+ "largest_impact": 20
+ },
+ {
+ "session_name": "Session 3",
+ "session_date": "2024-01-24",
+ "cumulative_impact": 90,
+ "average_impact": 20,
+ "largest_impact": 25
+ }
+ ]
+ }
+ },
"ImpactDirection": {
"type": "string",
@@ -1423,7 +1478,7 @@
"jerseyId": 80
}
},
-
+
"PlayerRemoveResponse": {
"type": "object",
"properties": {
@@ -1438,14 +1493,13 @@
"PlayerTeamRequest": {
"type": "object",
"properties": {
-
"jerseyId": {
"type": "number"
},
"fullName": {
"type": "string"
},
-
+
"playerEmail": {
"type": "string"
}
@@ -1459,18 +1513,17 @@
"PlayerTeamResponse": {
"type": "object",
"properties": {
-
"jerseyId": {
"type": "number"
},
"fullName": {
"type": "string"
},
-
+
"playerEmail": {
"type": "string"
},
- "teamId":{
+ "teamId": {
"type": "string"
}
},
@@ -1552,10 +1605,7 @@
}
}
},
-
-
-
"LoginResponse": {
"type": "object",
"properties": {
@@ -1632,6 +1682,37 @@
"email": "example@example.com"
}
},
+ "ManagersResponse": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "email": {
+ "type": "string"
+ },
+ "verification": {
+ "type": "string"
+ }
+ },
+ "example": {
+ "name": "John Doe",
+ "email": "example@example.com",
+ "verification": "verified"
+ }
+ },
+ "ManagerRemoveRequest": {
+ "type": "object",
+ "properties": {
+ "email": {
+ "type": "string"
+ }
+ },
+ "required": ["email"],
+ "example": {
+ "email": "example@example.com"
+ }
+ },
"TeamIdExistsResponse": {
"type": "object",
@@ -1711,10 +1792,6 @@
}
},
-
-
-
-
"SessionDetailsResponse": {
"type": "object",
"properties": {
@@ -1756,9 +1833,8 @@
"players": ["player1", "player2"]
}
}
-
- },
-
+ },
+
"requestBodies": {
"TeamCreateRequest": {
"content": {
@@ -1805,6 +1881,15 @@
}
}
},
+ "ManagerRemoveRequest": {
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/ManagerRemoveRequest"
+ }
+ }
+ }
+ },
"ManagerTeamRequest": {
"content": {
diff --git a/code/buddy-firmware/impax-buddy-firmware/src/sensors/combinedOutput.cpp b/code/buddy-firmware/impax-buddy-firmware/src/sensors/combinedOutput.cpp
index 05092a56..486ed31a 100644
--- a/code/buddy-firmware/impax-buddy-firmware/src/sensors/combinedOutput.cpp
+++ b/code/buddy-firmware/impax-buddy-firmware/src/sensors/combinedOutput.cpp
@@ -82,9 +82,9 @@ String CombinedOutput::getDirection()
else if (std::abs(aY) >= std::abs(aX) && std::abs(aY) >= std::abs(aZ))
{
if (aY > 0)
- return "Top";
+ return "Front"; // TOP
else
- return "Bottom";
+ return "Back"; // BOTTOM
}
else
{
diff --git a/code/client/impax/electron-builder.json5 b/code/client/impax/electron-builder.json5
index d9b7ea07..6714f878 100644
--- a/code/client/impax/electron-builder.json5
+++ b/code/client/impax/electron-builder.json5
@@ -13,6 +13,7 @@
extraResources: ["src/assets"],
mac: {
target: ["dmg"],
+ icon: "public/Icon.ico",
artifactName: "${productName}-Mac-${version}-Installer.${ext}",
},
win: {
@@ -35,7 +36,8 @@
deleteAppDataOnUninstall: false,
},
linux: {
- target: ["AppImage"],
+ icon: "public/Icon.png",
+ target: ["deb"],
artifactName: "${productName}-Linux-${version}.${ext}",
},
}
diff --git a/code/client/impax/package.json b/code/client/impax/package.json
index ab33ffd3..1d542e60 100644
--- a/code/client/impax/package.json
+++ b/code/client/impax/package.json
@@ -6,10 +6,12 @@
},
"description": "Impax is an head impact tracking and monitoring system for athletes",
"private": true,
- "version": "1.0.0",
+ "version": "1.0.1",
+ "homepage": "./",
"scripts": {
"dev": "vite",
"build": "tsc && vite build && electron-builder",
+ "build-linux": "tsc && vite build && electron-builder --linux",
"lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
diff --git a/code/client/impax/public/Icon.png b/code/client/impax/public/Icon.png
new file mode 100644
index 00000000..7c2753a0
Binary files /dev/null and b/code/client/impax/public/Icon.png differ
diff --git a/code/client/impax/src/App.tsx b/code/client/impax/src/App.tsx
index aa6e589c..13a4317f 100644
--- a/code/client/impax/src/App.tsx
+++ b/code/client/impax/src/App.tsx
@@ -6,17 +6,19 @@ import { HashRouter, Route, Routes } from "react-router-dom";
import routes from "./routes/routeConfig";
import { useAppState } from "./states/appState";
import { getPlayers, uploadSession } from "./services/httpClient";
+import { useSignupState } from "./states/formState";
function App() {
MqttClient.getInstance();
const setIsInternetAvailable = useAppState(
(state) => state.setIsInternetAvailable
);
+ const isLoggedInManager = useSignupState((state) => state.isLoggedInManager);
return (
{
- if (online) {
+ if (online && isLoggedInManager) {
uploadSession();
getPlayers();
console.log("Back Online...");
diff --git a/code/client/impax/src/components/Analytics/ImpactSummaryCard.module.scss b/code/client/impax/src/components/Analytics/ImpactSummaryCard.module.scss
index 084a21a3..aebe8f12 100644
--- a/code/client/impax/src/components/Analytics/ImpactSummaryCard.module.scss
+++ b/code/client/impax/src/components/Analytics/ImpactSummaryCard.module.scss
@@ -27,11 +27,11 @@
}
&.longText {
- font-size: 3em;
+ font-size: 2.4em;
}
&.longlongText {
- font-size: 2.4em;
+ font-size: 2em;
line-height: 0.9;
letter-spacing: 0.8;
}
diff --git a/code/client/impax/src/components/Analytics/ImpactSummaryCard.tsx b/code/client/impax/src/components/Analytics/ImpactSummaryCard.tsx
index f128c43d..3ed424f6 100644
--- a/code/client/impax/src/components/Analytics/ImpactSummaryCard.tsx
+++ b/code/client/impax/src/components/Analytics/ImpactSummaryCard.tsx
@@ -34,12 +34,13 @@ const ImpactSummaryCard: React.FC<{ metric: Metric; timeSpan: TimeSpan }> = ({
(String(metric.value).length > 10 && cardStyles.longText)
}`}
>
- {metric.value}
+ {metric.value === "" ? "--" : metric.value}
+ {/* This was a backend bug, fixed in the front end */}
{metric.metaUnits && (
{metric.metaUnits}
)}
- {timeSpan != "All Time" && metric.trend && (
+ {timeSpan != "All Time" && metric.trend !== undefined && (
{trendElement}
{timeSpan}
diff --git a/code/client/impax/src/components/Analytics/PlayerAnalytics/PlayerAnalytics.module.scss b/code/client/impax/src/components/Analytics/PlayerAnalytics/PlayerAnalytics.module.scss
index d26b7a46..6b488514 100644
--- a/code/client/impax/src/components/Analytics/PlayerAnalytics/PlayerAnalytics.module.scss
+++ b/code/client/impax/src/components/Analytics/PlayerAnalytics/PlayerAnalytics.module.scss
@@ -142,6 +142,9 @@ $button-bg: rgb(14, 61, 127);
font-size: 1.2em;
margin-left: 1em;
}
+ .noSessions {
+ margin-left: 1.2em;
+ }
.criticalSessionContainer {
margin-top: 1em;
}
@@ -162,8 +165,8 @@ $button-bg: rgb(14, 61, 127);
.spinnerContainer {
display: flex;
- justify-content: start;
- align-items: start;
+ justify-content: center;
+ align-items: center;
height: 10em;
width: 100%;
}
diff --git a/code/client/impax/src/components/Analytics/PlayerAnalytics/PlayerAnalytics.tsx b/code/client/impax/src/components/Analytics/PlayerAnalytics/PlayerAnalytics.tsx
index de39b6d4..f4a08488 100644
--- a/code/client/impax/src/components/Analytics/PlayerAnalytics/PlayerAnalytics.tsx
+++ b/code/client/impax/src/components/Analytics/PlayerAnalytics/PlayerAnalytics.tsx
@@ -15,8 +15,10 @@ import { useAppState } from "../../../states/appState";
import NoInternetConnection from "../../StatusScreens/NoInternetConnection";
import ImpactSummarySkeleton from "../ImpactSummarySkeleton";
import Spinner from "../../StatusScreens/Spinner";
+import { useLoginState } from "../../../states/profileState";
const PlayerAnalytics = () => {
const [timeSpan, setTimeSpan] = useState("Last Week");
+ const loginInfo = useLoginState((state) => state.loginInfo);
const { data: AnalyticsSummaryPlayer, isLoading } = useQuery({
queryFn: () => fetchAnalyticsSummaryPlayer(),
@@ -53,13 +55,15 @@ const PlayerAnalytics = () => {
}
}
+ console.log(AnalyticsSummaryPlayer);
+
return (
-
John Doe's Individual Analytics
{" "}
- 0 marked concussion
+ Analyze your Individual Impacts
{" "}
+ {loginInfo.email}
@@ -122,22 +126,24 @@ const PlayerAnalytics = () => {
Critical Sessions
{AnalyticsSummaryPlayer?.criticalSessions?.length == 0 && (
-
No sessions recorded
+
No sessions recorded
)}
- {AnalyticsSummaryPlayer?.criticalSessions?.map((session) => (
-
-
-
- ))}
+ {AnalyticsSummaryPlayer?.criticalSessions
+ ?.sort((a, b) => b.cumulative - a.cumulative)
+ .map((session) => (
+
+
+
+ ))}
>
diff --git a/code/client/impax/src/components/Analytics/PlayerAnalytics/StackedBarChart.tsx b/code/client/impax/src/components/Analytics/PlayerAnalytics/StackedBarChart.tsx
index 56c1735b..56df3414 100644
--- a/code/client/impax/src/components/Analytics/PlayerAnalytics/StackedBarChart.tsx
+++ b/code/client/impax/src/components/Analytics/PlayerAnalytics/StackedBarChart.tsx
@@ -4,10 +4,10 @@ import { ChartOptions } from "chart.js";
import { HistogramData } from "../../../types";
export const StackedBarChart: React.FC
= ({
- left,
- right,
- front,
- back,
+ Left,
+ Right,
+ Front,
+ Back,
}) => {
const xVals = [10, 30, 50, 70, 90, 110, 130, 150, 170, 190];
@@ -24,10 +24,10 @@ export const StackedBarChart: React.FC = ({
// Math.floor(Math.random() * 50)
// );
- const dataLeft = xVals.map((k, i) => ({ x: k, y: left[i] }));
- const dataRight = xVals.map((k, i) => ({ x: k, y: right[i] }));
- const dataFront = xVals.map((k, i) => ({ x: k, y: front[i] }));
- const dataBack = xVals.map((k, i) => ({ x: k, y: back[i] }));
+ const dataLeft = xVals.map((k, i) => ({ x: k, y: Left[i] }));
+ const dataRight = xVals.map((k, i) => ({ x: k, y: Right[i] }));
+ const dataFront = xVals.map((k, i) => ({ x: k, y: Front[i] }));
+ const dataBack = xVals.map((k, i) => ({ x: k, y: Back[i] }));
const backgroundColorLeft = Array(xVals.length).fill(
"rgba(255, 99, 180, 0.2)"
diff --git a/code/client/impax/src/components/Analytics/TeamAnalytics/TeamAnalytics.tsx b/code/client/impax/src/components/Analytics/TeamAnalytics/TeamAnalytics.tsx
index 218dad66..fff8dfbb 100644
--- a/code/client/impax/src/components/Analytics/TeamAnalytics/TeamAnalytics.tsx
+++ b/code/client/impax/src/components/Analytics/TeamAnalytics/TeamAnalytics.tsx
@@ -11,6 +11,7 @@ import {
// TeamAnalyticsColumns,
TimeSpan,
TeamAnalyticsSummary,
+ Metric,
} from "../../../types";
// import TeamAnalyticsTable from "./TeamAnalyticsTable";
import { useQuery } from "@tanstack/react-query";
@@ -51,7 +52,7 @@ const TeamAnalytics = () => {
const responseData = await response.json();
return responseData;
}
-
+ console.log(AnalyticsSummaryManager);
const isInternetAvailable = useAppState((state) => state.isInternetAvailable);
if (!isInternetAvailable) {
//show no internet connection component
@@ -115,7 +116,7 @@ const TeamAnalytics = () => {
) : (
<>
- {AnalyticsSummaryManager?.summaryData?.map((metric) => (
+ {AnalyticsSummaryManager?.summaryData?.map((metric: Metric) => (
{
))}
- {AnalyticsSummaryManager?.tableData ? (
+ {AnalyticsSummaryManager?.tableData &&
+ AnalyticsSummaryManager?.tableData.length > 0 ? (
) : (
-
No Data
+
No Player Data Available
)}
>
diff --git a/code/client/impax/src/components/PlayerManagement/PlayerManagement.tsx b/code/client/impax/src/components/PlayerManagement/PlayerManagement.tsx
index 56795b0e..3aaaeebd 100644
--- a/code/client/impax/src/components/PlayerManagement/PlayerManagement.tsx
+++ b/code/client/impax/src/components/PlayerManagement/PlayerManagement.tsx
@@ -173,6 +173,7 @@ const PlayerManagement = () => {
return;
}
+ console.log(data);
const response = await fetch(`${BASE_URL}/player/add`, {
method: "POST",
body: JSON.stringify({
@@ -253,13 +254,13 @@ const PlayerManagement = () => {
placeholder="Johnathan Doe"
/>
{
// console.log(data);
console.log(request);
// TODO: Change the URL to the backend
- const response = await fetch(`${BASE_URL}/%%%%%`, {
- method: "POST",
+ const response = await fetch(`${BASE_URL}/manager/join-team`, {
+ method: "PUT",
body: JSON.stringify(request),
headers: {
"Content-Type": "application/json",
diff --git a/code/client/impax/src/components/Profile/LoginManager.tsx b/code/client/impax/src/components/Profile/LoginManager.tsx
index 716f0412..e128cc81 100644
--- a/code/client/impax/src/components/Profile/LoginManager.tsx
+++ b/code/client/impax/src/components/Profile/LoginManager.tsx
@@ -32,7 +32,7 @@ const LoginManager = () => {
},
});
const responseData = await response.json();
- return responseData.teamName;
+ return responseData.team_name;
} catch (error) {
console.log(error);
}
@@ -60,7 +60,7 @@ const LoginManager = () => {
});
const teamName = await getTeamInfo(teamId, responseData.accessToken);
- setLoginInfo({ teamId, teamName: teamName, email });
+ setLoginInfo({ teamId, teamName, email });
// FETCH PLAYERS array and store it in local storage
diff --git a/code/client/impax/src/components/Profile/ManagerProfile/ManagerActions.tsx b/code/client/impax/src/components/Profile/ManagerProfile/ManagerActions.tsx
index 45bb3c81..0a9534b9 100644
--- a/code/client/impax/src/components/Profile/ManagerProfile/ManagerActions.tsx
+++ b/code/client/impax/src/components/Profile/ManagerProfile/ManagerActions.tsx
@@ -4,12 +4,40 @@ import styles from "./ManagerActions.module.scss";
import Btn from "../../Buttons/Btn";
import AlertModal from "../../Modal/AlertModal";
+import { BASE_URL } from "../../../config/config";
+import { renewAccessToken } from "../../../services/authService";
-const ManagerActions: React.FC<{ name: string; email: string }> = ({
+const ManagerActions: React.FC<{
+ name: string;
+ email: string;
+ handleAction: () => void;
+}> = ({
// name,
email,
+ handleAction,
}) => {
// const [openEdit, setOpenEdit] = useState(false);
+ const removeManager = async () => {
+ // react Delete request
+ renewAccessToken();
+ const response = await fetch(`${BASE_URL}/manager/remove`, {
+ method: "DELETE",
+ body: JSON.stringify({
+ email: email,
+ }),
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${localStorage.getItem("accessToken")}`,
+ },
+ });
+ const responseData = await response.json();
+ if (response.ok) {
+ // for debugging
+ handleAction();
+ console.log("response OK", responseData);
+ }
+ };
+
return (
{/* = ({
buttonStyle="secondary"
Icon={FaTrash}
iconSizeEm={1}
+ onClick={() => removeManager()}
>
Remove
diff --git a/code/client/impax/src/components/Profile/ManagerProfile/ManagerProfile.module.scss b/code/client/impax/src/components/Profile/ManagerProfile/ManagerProfile.module.scss
index 795966c0..3bbf77e1 100644
--- a/code/client/impax/src/components/Profile/ManagerProfile/ManagerProfile.module.scss
+++ b/code/client/impax/src/components/Profile/ManagerProfile/ManagerProfile.module.scss
@@ -31,3 +31,11 @@
.addManagerForm {
@include modalInnerForm;
}
+
+.spinnerContainer {
+ width: 100%;
+ height: 40dvh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
diff --git a/code/client/impax/src/components/Profile/ManagerProfile/ManagerProfile.tsx b/code/client/impax/src/components/Profile/ManagerProfile/ManagerProfile.tsx
index 0fd5912c..11f3e217 100644
--- a/code/client/impax/src/components/Profile/ManagerProfile/ManagerProfile.tsx
+++ b/code/client/impax/src/components/Profile/ManagerProfile/ManagerProfile.tsx
@@ -12,6 +12,13 @@ import { useState } from "react";
import { useNavigate } from "react-router-dom";
import NoInternetConnection from "../../StatusScreens/NoInternetConnection";
import { useAppState } from "../../../states/appState";
+import { useQuery } from "@tanstack/react-query";
+import { renewAccessToken } from "../../../services/authService";
+import { BASE_URL } from "../../../config/config";
+import Spinner from "../../StatusScreens/Spinner";
+import { Manager } from "../../../types";
+import { FieldValues, useForm } from "react-hook-form";
+import { showErrorPopup } from "../../../utils/popup";
const ManagerProfile = () => {
// Get team-id
@@ -27,6 +34,63 @@ const ManagerProfile = () => {
const [addManagerOpen, setAddManagerOpen] = useState(false);
const isInternetAvailable = useAppState((state) => state.isInternetAvailable);
+
+ const {
+ data: managerProfileData,
+ isLoading,
+ refetch: refetchManagers,
+ } = useQuery({
+ queryFn: () => fetchManagersTableData(),
+ queryKey: ["data"],
+ });
+ async function fetchManagersTableData(): Promise {
+ // Renew access Token
+ await renewAccessToken();
+ const response = await fetch(`${BASE_URL}/manager/getTeamManagers`, {
+ // Use the constructed URL with query params
+ method: "GET", // Change the method to GET
+ headers: {
+ Authorization: `Bearer ${localStorage.getItem("accessToken")}`,
+ "Content-Type": "application/json", // Keep the Content-Type header for consistency
+ },
+ });
+ const responseData = await response.json();
+ console.log(responseData);
+ return responseData;
+ }
+
+ const {
+ register,
+ handleSubmit,
+ formState: { isSubmitting },
+ reset,
+ } = useForm();
+
+ const onSubmit = async (data: FieldValues) => {
+ renewAccessToken();
+ const response = await fetch(`${BASE_URL}/manager/add`, {
+ method: "POST",
+ body: JSON.stringify({
+ managerEmail: data.email,
+ }),
+ headers: {
+ "Content-Type": "application/json",
+ Authorization: `Bearer ${localStorage.getItem("accessToken")}`,
+ },
+ });
+ // const responseData = await response.json();
+ setAddManagerOpen(false);
+ if (response.ok) {
+ // for debugging
+ console.log("response OK", response);
+ refetchManagers();
+ } else {
+ await showErrorPopup("Error", "Please Try Again!");
+ }
+
+ reset();
+ };
+
if (!isInternetAvailable) {
//show no internet connection component
if (!isInternetAvailable) {
@@ -84,10 +148,7 @@ const ManagerProfile = () => {
>
-
+ {isLoading || managerProfileData === undefined ? (
+
+
+
+ ) : (
+
+ )}
diff --git a/code/client/impax/src/components/Profile/ManagerProfile/ManagersTable.tsx b/code/client/impax/src/components/Profile/ManagerProfile/ManagersTable.tsx
index 5fc36b90..e6c2876f 100644
--- a/code/client/impax/src/components/Profile/ManagerProfile/ManagersTable.tsx
+++ b/code/client/impax/src/components/Profile/ManagerProfile/ManagersTable.tsx
@@ -15,56 +15,61 @@ import { FaSort } from "react-icons/fa";
import { Manager } from "../../../types";
import { Verification } from "../../PlayerManagement/PlayersTable/Verification/Verification";
import ManagerActions from "./ManagerActions";
-import { managers } from "./managersData";
-const columns: ColumnDef[] = [
- {
- //TODO:Until verified manager will not have a name
- accessorKey: "name",
- size: 100,
- header: ({ column }) => {
- return (
-
- );
+const ManagersTable: React.FC<{
+ managerProfileData: Manager[];
+ handleAction: () => void;
+}> = ({ managerProfileData, handleAction }) => {
+ const columns: ColumnDef[] = [
+ {
+ //TODO:Until verified manager will not have a name
+ accessorKey: "name",
+ size: 100,
+ header: ({ column }) => {
+ return (
+
+ );
+ },
+ cell: ({ row }) => {
+ return (
+ row.getValue("name") ?? ---
+ );
+ },
},
- cell: ({ row }) => {
- return row.getValue("name") ?? ---;
- },
- },
- {
- accessorKey: "email",
- header: "Email",
- id: "email",
- size: 100,
- },
+ {
+ accessorKey: "email",
+ header: "Email",
+ id: "email",
+ size: 100,
+ },
- {
- accessorKey: "verification",
- header: "Verification",
- id: "verification",
- size: 10,
- cell: ({ row }) => ,
- },
- {
- accessorKey: "edit",
- header: "",
- id: "edit",
- size: 3,
- cell: ({ row }) => (
-
- ),
- },
-];
-const ManagersTable = () => {
- const [data] = React.useState(() => [...managers]);
+ {
+ accessorKey: "verification",
+ header: "Verification",
+ id: "verification",
+ size: 10,
+ cell: ({ row }) => ,
+ },
+ {
+ accessorKey: "edit",
+ header: "",
+ id: "edit",
+ size: 3,
+ cell: ({ row }) => (
+
+ ),
+ },
+ ];
+ const [data] = React.useState(() => [...managerProfileData]);
const [sorting, setSorting] = React.useState([]);
const [columnFilters, setColumnFilters] = React.useState(
[]
diff --git a/code/client/impax/src/components/Profile/PlayerProfile/MyTeamsTable.tsx b/code/client/impax/src/components/Profile/PlayerProfile/MyTeamsTable.tsx
index 4787c46e..10ad7d72 100644
--- a/code/client/impax/src/components/Profile/PlayerProfile/MyTeamsTable.tsx
+++ b/code/client/impax/src/components/Profile/PlayerProfile/MyTeamsTable.tsx
@@ -13,47 +13,52 @@ import {
} from "@tanstack/react-table";
import { MyTeam } from "../../../types";
import { Verification } from "../../PlayerManagement/PlayersTable/Verification/Verification";
-import { myTeams } from "./myTeams";
import TeamActions from "./TeamsActions";
-const columns: ColumnDef[] = [
- {
- accessorKey: "team_id",
- size: 60,
- id: "team_id",
- header: "Team ID",
- },
+const MyTeamsTable: React.FC<{
+ playerProfileTable: MyTeam[];
+ handleActions: () => void;
+}> = ({ playerProfileTable, handleActions }) => {
+ const columns: ColumnDef[] = [
+ {
+ accessorKey: "team_id",
+ size: 60,
+ id: "team_id",
+ header: "Team ID",
+ },
- {
- accessorKey: "team_name",
- header: "Team Name",
- id: "team_name",
- size: 80,
- },
+ {
+ accessorKey: "team_name",
+ header: "Team Name",
+ id: "team_name",
+ size: 80,
+ },
- {
- accessorKey: "verification",
- header: "Verification",
- id: "verification",
- size: 10,
- cell: ({ row }) => ,
- },
- {
- accessorKey: "edit",
- header: "",
- id: "edit",
- size: 20,
- cell: ({ row }) => (
-
- ),
- },
-];
-const MyTeamsTable = () => {
- const [data] = React.useState(() => [...myTeams]);
+ {
+ accessorKey: "verification",
+ header: "Verification",
+ id: "verification",
+ size: 10,
+ cell: ({ row }) => ,
+ },
+ {
+ accessorKey: "edit",
+ header: "",
+ id: "edit",
+ size: 20,
+ cell: ({ row }) => (
+
+ ),
+ },
+ ];
+ const [data] = React.useState(() => [...playerProfileTable]);
const [sorting, setSorting] = React.useState([]);
const [columnFilters, setColumnFilters] = React.useState(
[]
@@ -71,6 +76,7 @@ const MyTeamsTable = () => {
columnFilters,
},
});
+
return (
diff --git a/code/client/impax/src/components/Profile/PlayerProfile/PlayerProfile.module.scss b/code/client/impax/src/components/Profile/PlayerProfile/PlayerProfile.module.scss
index 6670e2e6..fe7c691a 100644
--- a/code/client/impax/src/components/Profile/PlayerProfile/PlayerProfile.module.scss
+++ b/code/client/impax/src/components/Profile/PlayerProfile/PlayerProfile.module.scss
@@ -36,3 +36,11 @@
margin-left: 1em;
}
}
+
+.spinnerContainer {
+ width: 100%;
+ height: 60dvh;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
diff --git a/code/client/impax/src/components/Profile/PlayerProfile/PlayerProfile.tsx b/code/client/impax/src/components/Profile/PlayerProfile/PlayerProfile.tsx
index f8fe7f65..c69ba41b 100644
--- a/code/client/impax/src/components/Profile/PlayerProfile/PlayerProfile.tsx
+++ b/code/client/impax/src/components/Profile/PlayerProfile/PlayerProfile.tsx
@@ -9,6 +9,11 @@ import MyTeamsTable from "./MyTeamsTable";
import { useNavigate } from "react-router-dom";
import { useAppState } from "../../../states/appState";
import NoInternetConnection from "../../StatusScreens/NoInternetConnection";
+import { useQuery } from "@tanstack/react-query";
+import { renewAccessToken } from "../../../services/authService";
+import { BASE_URL } from "../../../config/config";
+import { MyTeam } from "../../../types";
+import Spinner from "../../StatusScreens/Spinner";
const PlayerProfile = () => {
// Get team-id
@@ -21,6 +26,29 @@ const PlayerProfile = () => {
const setLoginInfo = useLoginState((state) => state.setLoginInfo);
const navigate = useNavigate();
+ const {
+ data: myTeamsData,
+ isLoading,
+ refetch: refetchPlayers,
+ } = useQuery({
+ queryFn: () => fetchplayerProfileTableData(),
+ queryKey: ["data"],
+ });
+ async function fetchplayerProfileTableData(): Promise {
+ console.log("Fetching Profile Table...");
+ // Renew access Token
+ await renewAccessToken();
+ const response = await fetch(`${BASE_URL}/player/myTeams`, {
+ // Use the constructed URL with query params
+ method: "GET", // Change the method to GET
+ headers: {
+ Authorization: `Bearer ${localStorage.getItem("accessToken")}`,
+ "Content-Type": "application/json", // Keep the Content-Type header for consistency
+ },
+ });
+ const responseData = await response.json();
+ return responseData.teams;
+ }
const isInternetAvailable = useAppState((state) => state.isInternetAvailable);
if (!isInternetAvailable) {
//show no internet connection component
@@ -65,7 +93,17 @@ const PlayerProfile = () => {
My Teams
-
+ {isLoading || myTeamsData === undefined ? (
+
+
+
+ ) : (
+
+ )}
diff --git a/code/client/impax/src/components/Profile/PlayerProfile/TeamsActions.tsx b/code/client/impax/src/components/Profile/PlayerProfile/TeamsActions.tsx
index 22de9c28..6c297fb2 100644
--- a/code/client/impax/src/components/Profile/PlayerProfile/TeamsActions.tsx
+++ b/code/client/impax/src/components/Profile/PlayerProfile/TeamsActions.tsx
@@ -5,12 +5,63 @@ import styles from "./TeamsActions.module.scss";
import AlertModal from "../../Modal/AlertModal";
import { FaCheck } from "react-icons/fa6";
import { MyTeam } from "../../../types";
+import { renewAccessToken } from "../../../services/authService";
+import { BASE_URL } from "../../../config/config";
-const TeamActions: React.FC = ({
- // team_id,
- team_name,
- verification,
+const TeamActions: React.FC<{ myTeam: MyTeam; handleActions: () => void }> = ({
+ myTeam,
+ handleActions,
}) => {
+ const { team_id, team_name, verification } = myTeam;
+ const denyTeam = async () => {
+ // renew access Token
+ console.log("I am here");
+ renewAccessToken();
+
+ const token = localStorage.getItem("accessToken");
+
+ const response = await fetch(
+ `${BASE_URL}/player/accept-invite/${team_id}/${0}`,
+ {
+ method: "GET",
+ headers: {
+ Authorization: `Bearer ${token}`,
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ const responseData = await response.json();
+ if (response.ok) {
+ // for debugging
+ handleActions();
+ console.log("response OK", responseData);
+ }
+ console.log("Hello", response);
+ return response;
+ };
+
+ const acceptTeam = async () => {
+ console.log("Sending request to accept team");
+ // renew access Token
+ renewAccessToken();
+
+ const token = localStorage.getItem("accessToken");
+
+ const response = await fetch(
+ `${BASE_URL}/player/accept-invite/${team_id}/${1}`,
+ {
+ method: "GET",
+ headers: {
+ Authorization: `Bearer ${token}`,
+ "Content-Type": "application/json",
+ },
+ }
+ );
+ // const responseData = await response.json();
+ handleActions();
+ console.log("Hello", response);
+ };
+
return (
= ({
Icon={FaCheck}
iconSizeEm={1.2}
disabled={verification === "verified"}
+ onClick={() => acceptTeam()}
>
Accept
@@ -51,6 +103,7 @@ const TeamActions: React.FC = ({
bgColor="rgba(255,255,255,0)"
Icon={FaTrash}
iconSizeEm={1.2}
+ disabled={verification === "verified"}
>
Deny
@@ -74,6 +127,7 @@ const TeamActions: React.FC = ({
buttonStyle="secondary"
Icon={FaTrash}
iconSizeEm={1}
+ onClick={() => denyTeam()}
>
Deny
diff --git a/code/client/impax/src/components/Profile/SignupManager.tsx b/code/client/impax/src/components/Profile/SignupManager.tsx
index 7480331e..f64692e3 100644
--- a/code/client/impax/src/components/Profile/SignupManager.tsx
+++ b/code/client/impax/src/components/Profile/SignupManager.tsx
@@ -14,7 +14,6 @@ const SignupManager = () => {
handleSubmit,
formState: { errors, isSubmitting },
reset,
- setError,
} = useForm();
const onSubmit = async (data: FieldValues) => {
const { teamId, email } = data;
diff --git a/code/client/impax/src/components/StatusScreens/TeamExists.tsx b/code/client/impax/src/components/StatusScreens/TeamExists.tsx
index 697e45e7..d298555c 100644
--- a/code/client/impax/src/components/StatusScreens/TeamExists.tsx
+++ b/code/client/impax/src/components/StatusScreens/TeamExists.tsx
@@ -4,6 +4,8 @@ import styles from "./status.module.scss";
import Hero from "../Profile/Hero";
import { useSignupState } from "../../states/formState";
import { useNavigate } from "react-router-dom";
+import Btn from "../Buttons/Btn";
+import { FaRegCircleUser } from "react-icons/fa6";
const teamExists = () => {
const navigate = useNavigate();
@@ -15,16 +17,16 @@ const teamExists = () => {
You already have an account!
-
+
diff --git a/code/client/impax/src/services/httpClient.ts b/code/client/impax/src/services/httpClient.ts
index 097e842d..e0770dca 100644
--- a/code/client/impax/src/services/httpClient.ts
+++ b/code/client/impax/src/services/httpClient.ts
@@ -70,9 +70,12 @@ export const getPlayers = async () => {
Authorization: `Bearer ${token}`,
},
});
- const playersData: Players = await playersResponse.json();
- console.log("players data fetched: ", playersData);
- updatePlayersDetails(playersData);
+ if (!playersResponse.ok) return;
+ else {
+ const playersData: Players = await playersResponse.json();
+ console.log("players data fetched: ", playersData);
+ updatePlayersDetails(playersData);
+ }
} catch (error) {
console.log(error);
}
diff --git a/code/client/impax/src/services/mqttClient.ts b/code/client/impax/src/services/mqttClient.ts
index a7a31aa9..d1d2b00c 100644
--- a/code/client/impax/src/services/mqttClient.ts
+++ b/code/client/impax/src/services/mqttClient.ts
@@ -6,7 +6,7 @@ import {
setPlayerMap,
setSessionDetails,
updatePlayersImpactHistory,
- checkBuddiesAvailability,
+ // checkBuddiesAvailability,
flushStates,
validateTimestampAndSetPlayerDetails,
} from "../states/updateAppStates";
@@ -19,7 +19,7 @@ class MqttClient {
private topics: string[];
private constructor() {
- this.client = mqtt.connect("ws://127.0.0.1:8080/", {
+ this.client = mqtt.connect("ws://192.168.4.1:8080/", {
clientId: `impax-dashboard-${Date.now()}`,
reconnectPeriod: 2000,
keepalive: 60,
@@ -71,6 +71,9 @@ class MqttClient {
private handleMessage = (topic: string, message: Buffer) => {
console.log(`Received message on topic ${topic}: ${message}`);
+
+ // Zero Payload Ignore
+ if (message.toString().length === 0) return;
switch (true) {
case /^player_map$/.test(topic):
setPlayerMap(message.toString());
diff --git a/code/client/impax/src/states/appState.ts b/code/client/impax/src/states/appState.ts
index 98f3a415..18cfccb5 100644
--- a/code/client/impax/src/states/appState.ts
+++ b/code/client/impax/src/states/appState.ts
@@ -105,7 +105,8 @@ export const useAppState = create()((set) => ({
playersImpactHistory: {} as PlayerImpactHistory,
//TODO: Clashing of players with other dashbaords
- playerDetails: localStorage.getItem("players") as Players | {} as Players,
+ playerDetails: JSON.parse(localStorage.getItem("players") || '{"player": {}}')
+ .players as Players,
setPlayerDetails: (players: Players) => {
set({ playerDetails: players });
const timestamp = new Date().getTime();
diff --git a/code/client/impax/src/states/formState.ts b/code/client/impax/src/states/formState.ts
index 407c26d2..d4d22c5e 100644
--- a/code/client/impax/src/states/formState.ts
+++ b/code/client/impax/src/states/formState.ts
@@ -52,7 +52,7 @@ export const useSignupState = create()((set) => ({
},
isLoggedInManager: localStorage.getItem("isLoggedInManager") === "true",
- // isLoggedInManager: false,
+ // isLoggedInManager: true,
setIsLoggedInManager: (isLoggedInManager) => {
set({ isLoggedInManager: isLoggedInManager }),
diff --git a/code/client/impax/src/states/updateAppStates.ts b/code/client/impax/src/states/updateAppStates.ts
index 4b27d7f2..8aa2e17d 100644
--- a/code/client/impax/src/states/updateAppStates.ts
+++ b/code/client/impax/src/states/updateAppStates.ts
@@ -26,14 +26,18 @@ export const updateBuddy = (buddy_id: number, battery: number) => {
//updateSet
useAppState.setState((prevState) => {
const buddiesStatus = { ...prevState.buddiesStatus };
+ const playerMap = { ...prevState.playerMap };
if (battery === 0) {
delete buddiesStatus[buddy_id];
+ console.log("Deleted buddy", buddy_id);
+ delete playerMap[buddy_id];
+ MqttClient.getInstance().publishPlayerMap(playerMap);
} else {
buddiesStatus[buddy_id] = buddyStatus;
}
- return { buddiesStatus };
+ return { buddiesStatus, playerMap };
});
};
@@ -84,6 +88,7 @@ export const setSessionDetails = (sessionString: string) => {
//Parse sessionString and set sessionDetails
const session: Session = JSON.parse(sessionString);
if (session.active === false) {
+ console.log("Flushing States...");
useAppState.setState({ playersImpact: {} as PlayersImpact });
useAppState.setState({ playersImpactHistory: {} as PlayerImpactHistory });
useAppState.setState({ monitoringBuddies: new Set() as Set });
diff --git a/code/client/impax/src/types/index.d.ts b/code/client/impax/src/types/index.d.ts
index 5f3ccad7..95e0ef50 100644
--- a/code/client/impax/src/types/index.d.ts
+++ b/code/client/impax/src/types/index.d.ts
@@ -16,7 +16,7 @@ export type Role = "player" | "manager";
export type Impact = {
magnitude: number;
- direction: "left" | "right" | "front" | "back";
+ direction: "Left" | "Right" | "Front" | "Back";
timestamp: number;
isConcussion?: boolean;
};
@@ -74,7 +74,7 @@ export type SessionToBeUploaded = {
export type Metric = {
title: string;
value: string | number;
- trend?: number | Impact.direction;
+ trend?: number | Impact.direction | "--";
metaUnits?: string;
};
@@ -82,10 +82,10 @@ export type TimeSpan = "Last Week" | "Last Month" | "All Time";
//for player analytics
export type HistogramData = {
- left: number[];
- right: number[];
- front: number[];
- back: number[];
+ Left: number[];
+ Right: number[];
+ Front: number[];
+ Back: number[];
};
//for player critical sessions
@@ -109,10 +109,10 @@ export type TeamAnalyticsColumns = {
concussions: number;
};
-export type TeamAnalyticsSummary ={
+export type TeamAnalyticsSummary = {
summaryData: Metric[];
tableData: TeamAnalyticsColumns[];
-}
+};
export type PlayerAnalyticsSummary = {
summaryData: Metric[];
@@ -120,8 +120,6 @@ export type PlayerAnalyticsSummary = {
criticalSessions: CriticalSessionType[];
};
-
-
//Profile Managers
export type Manager =
| {
@@ -151,5 +149,4 @@ export type LoginInfo = {
teamId?: string;
teamName?: string;
email: string;
-
-}
+};
diff --git a/code/client/impax/src/utils/utils.ts b/code/client/impax/src/utils/utils.ts
index d8ae8c54..b120ac9f 100644
--- a/code/client/impax/src/utils/utils.ts
+++ b/code/client/impax/src/utils/utils.ts
@@ -12,6 +12,7 @@ export function generateStringId(input: string): string {
const words = input.split(" ");
const id = words.map((word) => word[0]).join("");
const currentDate = new Date().toISOString().split("T")[0];
- const stringId = `${id}-${currentDate}`;
+ const timestamp = Date.now().toString().split("").slice(0, 5).join("");
+ const stringId = `${id}-${currentDate}-${timestamp}`;
return stringId;
}
diff --git a/code/client/impax/tests/dashboard_load_test/mqtt_load.py b/code/client/impax/tests/dashboard_load_test/mqtt_load.py
index 2beea598..acfb2982 100644
--- a/code/client/impax/tests/dashboard_load_test/mqtt_load.py
+++ b/code/client/impax/tests/dashboard_load_test/mqtt_load.py
@@ -3,11 +3,11 @@
import random
# MQTT broker settings
-broker_address = "localhost"
+broker_address = "192.168.4.1"
broker_port = 1883
# Number of buddy devices
-num_buddies = 5
+num_buddies = 30
# Impact frequency (chance for a buddy to publish an impact each cycle)
impact_frequency = 10
@@ -58,7 +58,7 @@ def on_connect(client, userdata, flags, rc):
if random.random() < impact_frequency:
magnitude = random.randint(14, 100)
direction = random.choice(
- ["left", "right", "front", "back", "top", "bottom"])
+ ["left", "right", "front", "back", "top", "bottom"]).capitalize()
topic = f"buddy/{client_id_str.split('_')[1]}/impact"
client.publish(
topic, f"{magnitude} {direction}", retain=True)
diff --git a/code/hub-firmware/hub-client/old_client.py b/code/hub-firmware/hub-client/old_client.py
index e5334bb1..3ce19a09 100644
--- a/code/hub-firmware/hub-client/old_client.py
+++ b/code/hub-firmware/hub-client/old_client.py
@@ -128,6 +128,8 @@ def on_message(client, userdata, msg):
impact["isConcussion"] = True
break
+ client.publish(f'player/{player_id}/impact_history',
+ json.dumps(data_buffer[int(player_id)]), retain=True)
except Exception as e:
print(f"Error in handling concussion data: {str(e)}")
@@ -158,6 +160,13 @@ def end_session():
global session_started, start_time, data_buffer, player_device_mapping
session_started = False
+ # zero payload messages to clear retained messages
+ for player_id in data_buffer:
+ impact_topic = f'player/{player_id}/impact_with_timestamp'
+ impact_history_topic = f'player/{player_id}/impact_history'
+ client.publish(impact_topic, "", retain=True)
+ client.publish(impact_history_topic, "", retain=True)
+
# for entry in data_buffer:
# client.publish(session_data, json.dumps(entry), retain=True)
diff --git a/docs/assets/css/style.css b/docs/assets/css/style.css
index 5a77bfa3..73e1c0d2 100644
--- a/docs/assets/css/style.css
+++ b/docs/assets/css/style.css
@@ -1455,4 +1455,4 @@ section {
#footer .footer-top .footer-info {
margin: -20px 0 30px 0;
}
-}
\ No newline at end of file
+}
diff --git a/docs/assets/img/3D-buddy-img.jpg b/docs/assets/img/3D-buddy-img.jpg
new file mode 100644
index 00000000..907edf4a
Binary files /dev/null and b/docs/assets/img/3D-buddy-img.jpg differ
diff --git a/docs/assets/img/3D-hub-img.jpg b/docs/assets/img/3D-hub-img.jpg
new file mode 100644
index 00000000..3d73c76e
Binary files /dev/null and b/docs/assets/img/3D-hub-img.jpg differ
diff --git a/docs/assets/img/3d-buddy.mp4 b/docs/assets/img/3d-buddy.mp4
new file mode 100644
index 00000000..7c0c696b
Binary files /dev/null and b/docs/assets/img/3d-buddy.mp4 differ
diff --git a/docs/assets/img/3d-hub.mp4 b/docs/assets/img/3d-hub.mp4
new file mode 100644
index 00000000..ef4f89ce
Binary files /dev/null and b/docs/assets/img/3d-hub.mp4 differ
diff --git a/docs/assets/img/Coach-feedback.jpg b/docs/assets/img/Coach-feedback.jpg
new file mode 100644
index 00000000..e4a87247
Binary files /dev/null and b/docs/assets/img/Coach-feedback.jpg differ
diff --git a/docs/assets/img/Demo.jpg b/docs/assets/img/Demo.jpg
new file mode 100644
index 00000000..2f2fb534
Binary files /dev/null and b/docs/assets/img/Demo.jpg differ
diff --git a/docs/assets/img/PXL_20240126_094654363.mp4 b/docs/assets/img/PXL_20240126_094654363.mp4
new file mode 100644
index 00000000..bf784324
Binary files /dev/null and b/docs/assets/img/PXL_20240126_094654363.mp4 differ
diff --git a/docs/assets/img/User-feedback.jpg b/docs/assets/img/User-feedback.jpg
new file mode 100644
index 00000000..cf81bb06
Binary files /dev/null and b/docs/assets/img/User-feedback.jpg differ
diff --git a/docs/assets/img/buck-booster.webp b/docs/assets/img/buck-booster.webp
new file mode 100644
index 00000000..c5399608
Binary files /dev/null and b/docs/assets/img/buck-booster.webp differ
diff --git a/docs/assets/img/buddy v1-1.avi b/docs/assets/img/buddy v1-1.avi
new file mode 100644
index 00000000..2f3b563a
Binary files /dev/null and b/docs/assets/img/buddy v1-1.avi differ
diff --git a/docs/assets/img/buddy-labled.jpg b/docs/assets/img/buddy-labled.jpg
new file mode 100644
index 00000000..6296f83b
Binary files /dev/null and b/docs/assets/img/buddy-labled.jpg differ
diff --git a/docs/assets/img/dashboard-screenshot.png b/docs/assets/img/dashboard-screenshot.png
new file mode 100644
index 00000000..ab75b250
Binary files /dev/null and b/docs/assets/img/dashboard-screenshot.png differ
diff --git a/docs/assets/img/hub-labled.jpg b/docs/assets/img/hub-labled.jpg
new file mode 100644
index 00000000..f33fd28a
Binary files /dev/null and b/docs/assets/img/hub-labled.jpg differ
diff --git a/docs/download.css b/docs/download.css
new file mode 100644
index 00000000..5c47b598
--- /dev/null
+++ b/docs/download.css
@@ -0,0 +1,117 @@
+body {
+ font-family: "Raleway", sans-serif;
+ margin: 0;
+ padding: 0;
+}
+
+.container {
+ width: 100%;
+ margin: 0 auto;
+ padding: 120px;
+ padding-top: 10em;
+}
+
+.container .mockup-container {
+ overflow: hidden;
+ height: auto;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+
+.container .mockup-container .mockup-img {
+ height: 60dvh;
+ margin-top: -2em;
+ object-fit: contain;
+}
+.logo {
+ display: block;
+ margin: 0 auto;
+ width: 200px;
+}
+
+.title {
+ text-align: center;
+ font-size: 24px;
+ font-weight: bold;
+ margin-top: 20px;
+}
+
+.subtitle {
+ text-align: center;
+ font-size: 18px;
+ margin-bottom: 20px;
+}
+
+.requirements {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 2em;
+ margin-bottom: 20px;
+}
+
+.requirement {
+ padding: 16px;
+ border: 1px solid #eee;
+ background-color: #fbfbfb;
+ border-radius: 10px;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ /* box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.1); */
+}
+
+.requirement h3 {
+ text-align: left;
+ font-size: 20px;
+ font-weight: 600;
+ margin-top: 0;
+ display: flex;
+ align-items: center;
+ gap: 10px;
+}
+
+.requirement h3 img {
+ width: 20px;
+}
+
+.requirement ul {
+ list-style: none;
+ padding: 0;
+ margin: 0;
+}
+
+.requirement li {
+ margin: 10px 0;
+ font-weight: 500;
+ font-size: 1em;
+}
+
+.requirement li span {
+ display: block;
+ margin-top: 0.2em;
+ font-weight: 400;
+ font-size: 0.8em;
+}
+
+.download-link {
+ width: 100%;
+}
+.button {
+ width: 100%;
+ margin-top: 2em;
+ border: none;
+ border-radius: 8px;
+ padding: 1em 1em;
+ background-color: #2a2a2a;
+ color: white;
+ font-size: 16px;
+ font-weight: 400;
+ font-family: "Raleway", sans-serif;
+ cursor: pointer;
+ transition: all 150ms ease-in-out;
+}
+
+.button:hover {
+ background-color: #882626;
+}
diff --git a/docs/download.html b/docs/download.html
new file mode 100644
index 00000000..34dd8b51
--- /dev/null
+++ b/docs/download.html
@@ -0,0 +1,178 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Windows
+ - Supported Operating Systems: Windows 7 and later (x86 and amd64)
+ - Minimum RAM: 512 MB
+ - Processor: Pentium 4 or later with SSE2 support
+
+
+
+
+
+ macOS
+ - Supported Operating Systems: macOS 10.10 and later (64-bit)
+ - Minimum RAM: 512 MB
+ - Processor: x64, Apple Silicon
+
+
+
+
+
+ Linux
+ - Supported Distributions: Ubuntu 12.04 and later, Fedora 21, Debian 8 (ia32/i686 and x64/amd64)
+ - Minimum RAM: 512 MB
+ - Processor: Intel Pentium 4 or later with SSE2 support
+
+
+
+
+
+
+
+
+
+