diff --git a/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java b/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java index ba02050..8bca5ff 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/rest/AthleteResource.java @@ -40,6 +40,7 @@ import io.swagger.v3.oas.annotations.responses.ApiResponses; public class AthleteResource { @Autowired private AthleteDAO athleteDAO; + @Autowired private SessionDAO sessionDAO; @Operation(summary = "Crée un Athlète avec les informations fournies") @@ -161,7 +162,7 @@ public class AthleteResource { @ApiResponses(value = { @ApiResponse(responseCode = "200", description = "Récupération effectuée", content = @Content(mediaType = "application/json", schema = @Schema(implementation = SessionDTO.class))) }) - @GetMapping("/athlete/{id}/session") + @GetMapping("/athlete/{athleteId}/session") public List getSessionsAthlete(@PathVariable Integer athleteId) { // return pet System.out.println("ID A CHERCHER" + athleteId); @@ -171,7 +172,25 @@ public class AthleteResource { for (Session s : sessions) { if (s.getAthletes().contains(j.get())) { SessionDTO dto = new SessionDTO(); + + dto.setId(s.getId()); dto.setName(s.getName()); + dto.setCreneau(s.getCreneau()); + List activiteIDs = new ArrayList<>(); + for (Activite activite : s.getActivites()) { + activiteIDs.add(activite.getId()); + } + dto.setActiviteIds(activiteIDs); + dto.setCoachId(s.getCoach().getId()); + dto.setDuree(s.getDuree()); + dto.setGroupe(s.getGroupe()); + dto.setIsRecurrent(s.getIsRecurrent()); + List athleteIds = new ArrayList<>(); + for (Athlete athlete : s.getAthletes()) { + athleteIds.add(athlete.getId()); + } + dto.setAthleteIds(athleteIds); + // Map other fields as necessary athleteSessions.add(dto); } diff --git a/back_end/src/main/java/hackathon/FrisbYEE/rest/SessionResource.java b/back_end/src/main/java/hackathon/FrisbYEE/rest/SessionResource.java index e09b313..b37460d 100644 --- a/back_end/src/main/java/hackathon/FrisbYEE/rest/SessionResource.java +++ b/back_end/src/main/java/hackathon/FrisbYEE/rest/SessionResource.java @@ -114,6 +114,38 @@ public class SessionResource { return ResponseEntity.noContent().build(); } + + @PutMapping("/{id}/subscribe/{userId}") + @PreAuthorize("hasRole('admin') or hasRole('coach') or hasRole('athlete')") + public ResponseEntity subscribe(@PathVariable Integer id,@PathVariable Integer userId){ + Session session = sessionDAO.findById(id).orElseThrow(() -> new ResponseStatusException( + HttpStatus.NOT_FOUND, "Session not found with id " + id)); + Athlete athlete = athleteDAO.findById(userId).orElseThrow(() -> new ResponseStatusException( + HttpStatus.NOT_FOUND, "Athlete not found with id " + userId)); + + session.getAthletes().add(athlete); + sessionDAO.save(session); + + + return ResponseEntity.noContent().build(); + } + + @PutMapping("/{id}/unsubscribe/{userId}") + @PreAuthorize("hasRole('admin') or hasRole('coach') or hasRole('athlete')") + public ResponseEntity unsubscribe(@PathVariable Integer id,@PathVariable Integer userId){ + Session session = sessionDAO.findById(id).orElseThrow(() -> new ResponseStatusException( + HttpStatus.NOT_FOUND, "Session not found with id " + id)); + Athlete athlete = athleteDAO.findById(userId).orElseThrow(() -> new ResponseStatusException( + HttpStatus.NOT_FOUND, "Athlete not found with id " + userId)); + + session.getAthletes().remove(athlete); + sessionDAO.save(session); + + + return ResponseEntity.noContent().build(); + } + + @GetMapping("/{id}/activities") @PreAuthorize("hasRole('coach') or hasRole('athlete')") public ResponseEntity getActivitiesBySessionId(@PathVariable Integer id) { diff --git a/front_end/src/App.css b/front_end/src/App.css index 06b9594..c0547ce 100644 --- a/front_end/src/App.css +++ b/front_end/src/App.css @@ -8,9 +8,7 @@ --tint5: #373d48; --text: #FFFFFF; --text2: #000000; - --accent1: #10b981; - --accent2: #059669; - --disable: #047857; + --disable: #02291d; --green-primary: #10b981; --green-secondary: #059669; --green-dark: #047857; @@ -28,9 +26,7 @@ --tint5: #c6bab8; --text: #000000; --text2: #FFFFFF; - --accent1: #00ce89; - --accent2: #00a571; - --disable: #00825d; + --disable: #02291d; --green-primary: #00ce89; --green-secondary: #00a571; --green-dark: #00825d; @@ -147,6 +143,7 @@ input[type="number"], input[type="date"], input[type="time"], input[type="search"], +input[type="datetime-local"], textarea { background-color: var(--tint2); color: var(--text); diff --git a/front_end/src/api.ts b/front_end/src/api.ts index 1282c72..da4b445 100644 --- a/front_end/src/api.ts +++ b/front_end/src/api.ts @@ -45,7 +45,7 @@ export const athleteService = { delete: (id: number | string) => api.delete(`/athlete/${id}`), // session-related endpoints exposed by AthleteResource - getSessionsForAthlete: (athleteId: number | null) => api.get(`/athletes/athlete/${athleteId}/session`), + getSessionsForAthlete: (athleteId: number | null) => api.get(`/athlete/athlete/${athleteId}/session`), getAllSessions: () => api.get(`/athletes/session`), getActivitiesForSession: (sessionId: number | string) => api.get(`/athletes/session/${sessionId}/activities`), getSessionsAfterDate: (athleteId: number | string, date: string) => api.get(`/athletes/${athleteId}/session/after/${encodeURIComponent(date)}`), @@ -73,8 +73,8 @@ export const sessionService = { getActivities: (sessionId: number | null) => api.get(`/session/${sessionId}/activities`), addActivity: (sessionId: number | null, activityId: number) => api.post(`/session/${sessionId}/activities/${activityId}`), - subscribe: (sessionId: number | null, userId: number | string) => api.post(`/session/${sessionId}/subscribe`, { userId }), - unsubscribe: (sessionId: number | null, userId: number | string) => api.post(`/session/${sessionId}/unsubscribe`, { userId }), + subscribe: (sessionId: number | null, userId: number) => api.put(`/session/${sessionId}/subscribe/${userId}`), + unsubscribe: (sessionId: number | null, userId: number) => api.put(`/session/${sessionId}/unsubscribe/${userId}`), }; export const coachService = { diff --git a/front_end/src/components/createActivite.tsx b/front_end/src/components/createActivite.tsx index 820d99d..05aad59 100644 --- a/front_end/src/components/createActivite.tsx +++ b/front_end/src/components/createActivite.tsx @@ -4,10 +4,11 @@ import { Modal } from "./Modal"; type CreateActiciteProps = { returnActivite: (activite:Activite|null) => void + session: Session; } -export function CreateActivite({ returnActivite }: CreateActiciteProps){ +export function CreateActivite({ returnActivite,session }: CreateActiciteProps){ const [activities, setActivities] = useState([]); const [activiteNom, setActiviteNom] = useState(""); @@ -41,6 +42,7 @@ export function CreateActivite({ returnActivite }: CreateActiciteProps){ cancel()}>

Nouvelle Activité :

+
Session : {session.name}
Nom de l'activité:
diff --git a/front_end/src/components/edt.tsx b/front_end/src/components/edt.tsx index 281ddcb..e22286b 100644 --- a/front_end/src/components/edt.tsx +++ b/front_end/src/components/edt.tsx @@ -45,6 +45,7 @@ export const EDT =() =>{ } }); } + newWeek.sort((a, b) =>a.creneau.getHours() * 60 + a.creneau.getMinutes() -(b.creneau.getHours() * 60 + b.creneau.getMinutes())); setSessions(newWeek); } @@ -116,17 +117,29 @@ export const EDT =() =>{ return newDate; } + function sameDay(d1:Date,d2:Date):boolean{ + return ( + d1.getDate() === d2.getDate() && + d1.getMonth() === d2.getMonth() && + d1.getFullYear() === d2.getFullYear() + ); + } + + async function refresh() { + loadSessions(week) + } return(
+
{loading && }
{week_days_nums.map((num,index)=>( -
+
{week_days[index]}
{dateToString(getNextDay(week,index))}
diff --git a/front_end/src/components/login.tsx b/front_end/src/components/login.tsx index 34e3902..8f367f0 100644 --- a/front_end/src/components/login.tsx +++ b/front_end/src/components/login.tsx @@ -1,6 +1,6 @@ import { useKeycloak } from '@react-keycloak/web' import { useEffect } from 'react'; -import { Athlete, User } from '../classes'; +import { Admin, Athlete, Coach, User } from '../classes'; import { useLocalData } from '../context/useLocalData'; import { loginOrRegister, postAthlete } from '../requetes'; import { clearAuthToken, setAuthToken } from '../api'; @@ -80,6 +80,9 @@ export const Login =() =>{
Nom : { user.nom}
+ {user instanceof Athlete &&
Role : Athlete
} + {user instanceof Coach &&
Role : Coach
} + {user instanceof Admin &&
Role : Admin
}
} diff --git a/front_end/src/components/object/detailSession.tsx b/front_end/src/components/object/detailSession.tsx index 632d76a..7f04360 100644 --- a/front_end/src/components/object/detailSession.tsx +++ b/front_end/src/components/object/detailSession.tsx @@ -1,10 +1,11 @@ import { useEffect, useState } from "react"; -import { Activite, Session } from "../../classes"; +import { Activite, Athlete, Session } from "../../classes"; import { dateToString, hoursToString } from "../edt"; import { Modal } from "../Modal"; import CreateActivite from "../createActivite"; import Loading from "../loading"; -import { addActiviteToSession, createActivityAPI, delay, deletActiviteFromSession, getSessionOfActivite } from "../../requetes"; +import { addActiviteToSession, createActivityAPI, delay, deletActiviteFromSession, getSessionOfActivite, subscribeSessionAPI, unsubscribeSessionAPI } from "../../requetes"; +import { useLocalData } from "../../context/useLocalData"; type Props = { session:Session; @@ -14,9 +15,12 @@ type Props = { function DetailSession({session,open,setOpen}:Props){ + const {user,setUser} = useLocalData() + const [activites,setActivites] = useState([]); const [open2, setOpen2] = useState(false); const [loading,setLoading] = useState(false); + const [join,setJoin] = useState(user instanceof Athlete && user.sessions.includes(session)); const sDate = session.creneau; @@ -46,6 +50,22 @@ function DetailSession({session,open,setOpen}:Props){ } },[open]) + async function subscribeSession(){ + if(user instanceof Athlete){ + await subscribeSessionAPI(user,session); + user.sessions.push(session); + setJoin(true); + } + } + + async function unsubscribeSession(){ + if(user instanceof Athlete){ + await unsubscribeSessionAPI(user,session); + user.sessions = user.sessions.filter(s => s !== session); + setJoin(false); + } + } + async function returnActivite(activite: Activite|null){ if(activite!==null){ @@ -67,35 +87,43 @@ function DetailSession({session,open,setOpen}:Props){ } },[loading]) + if(!open2){ - return( + return( + setOpen(false)}> +
+

{session.name}

+
{hoursToString(sDate)}
+
{dateToString(sDate)}
+ {user instanceof Athlete && +
+ {user.sessions.includes(session) ? + :} +
+ } - setOpen(false)}> -
-
{session.name}
-
{hoursToString(sDate)}
-
{dateToString(sDate)}
-
- Activités : -
- {activites.map((activite,index)=>( -
- {activite.nom} - -
- ))} - - {loading &&
} +
+ Activités : +
+ {activites.map((activite,index)=>( +
+ {activite.nom} + +
+ ))} + + {loading &&
} +
+
- - {open2 && - returnActivite(activite)}/> - } -
- - - ) + + ) + }else{ + return( + returnActivite(activite)} session={session}/> + ) + } } export default DetailSession; diff --git a/front_end/src/components/style/SwitchThemeColor.css b/front_end/src/components/style/SwitchThemeColor.css index 931dbde..0779267 100644 --- a/front_end/src/components/style/SwitchThemeColor.css +++ b/front_end/src/components/style/SwitchThemeColor.css @@ -7,5 +7,5 @@ margin: 0px; font-size: 20px; display: inline; - border-color: var(--accent1); + border-color: var(--green-A-primary); } diff --git a/front_end/src/components/style/edt.css b/front_end/src/components/style/edt.css index fcb798c..f6c4d44 100644 --- a/front_end/src/components/style/edt.css +++ b/front_end/src/components/style/edt.css @@ -10,9 +10,9 @@ .edt_header{ justify-content: center; display: grid; - grid-template-columns: repeat(2, 0.5fr); + grid-template-columns: repeat(3, 0.5fr); padding-bottom: 10px; - gap: 30%; + gap: 5%; } .edt_colonnes { @@ -56,6 +56,10 @@ font-weight: 600; } +.today{ + border: 2px solid var(--green-primary) ; +} + .edt_day_content{ display: flex; flex-direction: column; diff --git a/front_end/src/components/style/objectList.css b/front_end/src/components/style/objectList.css index d9b464c..bd9e763 100644 --- a/front_end/src/components/style/objectList.css +++ b/front_end/src/components/style/objectList.css @@ -46,10 +46,3 @@ background-color: var(--tint3); border-radius: 10px; } - -.create_activite_modal{ - background-color: var(--tint3); - padding: 10px; - border-radius: 20px; - position: relative; -} \ No newline at end of file diff --git a/front_end/src/index.css b/front_end/src/index.css index 355219c..5e6ce35 100644 --- a/front_end/src/index.css +++ b/front_end/src/index.css @@ -1,37 +1,4 @@ -/* Variables de thème globales */ -[data-theme='dark'] { - --tint0: #000000; - --tint1: #0b0c0e; - --tint2: #16181d; - --tint3: #21252b; - --tint4: #2c313a; - --tint5: #373d48; - --text: #FFFFFF; - --text2: #000000; - --accent1: #44c1ee; - --accent2: #0b235f; - --disable: #030918; - --green-primary: #10b981; - --green-secondary: #059669; - --green-dark: #047857; -} -[data-theme='light'] { - --tint0: #FFFFFF; - --tint1: #f4f1f1; - --tint2: #e8e4e3; - --tint3: #ddd6d5; - --tint4: #d2c8c6; - --tint5: #c6bab8; - --text: #000000; - --text2: #FFFFFF; - --accent1: #44c1ee; - --accent2: #113388; - --disable: #061231; - --green-primary: #10b981; - --green-secondary: #059669; - --green-dark: #047857; -} /* Reset global */ * { diff --git a/front_end/src/requetes.tsx b/front_end/src/requetes.tsx index a204c49..d1a7098 100644 --- a/front_end/src/requetes.tsx +++ b/front_end/src/requetes.tsx @@ -135,7 +135,7 @@ export async function subscribeSessionAPI(user:User, session:Session):Promise{ +export async function unsubscribeSessionAPI(user:Athlete, session:Session):Promise{ try { const session_id =session.id const user_id = user.id