subscribe + unsubscribe + edt
This commit is contained in:
@@ -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<SessionDTO> 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<Integer> 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<Integer> athleteIds = new ArrayList<>();
|
||||
for (Athlete athlete : s.getAthletes()) {
|
||||
athleteIds.add(athlete.getId());
|
||||
}
|
||||
dto.setAthleteIds(athleteIds);
|
||||
|
||||
// Map other fields as necessary
|
||||
athleteSessions.add(dto);
|
||||
}
|
||||
|
||||
@@ -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<Void> 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<Void> 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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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<SessionDTO[]>(`/athletes/athlete/${athleteId}/session`),
|
||||
getSessionsForAthlete: (athleteId: number | null) => api.get<SessionDTO[]>(`/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<ActiviteDTO[]>(`/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 = {
|
||||
|
||||
@@ -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<Activite[]>([]);
|
||||
const [activiteNom, setActiviteNom] = useState("");
|
||||
@@ -41,6 +42,7 @@ export function CreateActivite({ returnActivite }: CreateActiciteProps){
|
||||
<Modal isOpen={true} onClose={() => cancel()}>
|
||||
<div className="create_activite_modal">
|
||||
<h2>Nouvelle Activité :</h2>
|
||||
<div>Session : {session.name}</div>
|
||||
<div>
|
||||
Nom de l'activité:
|
||||
</div>
|
||||
|
||||
@@ -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(
|
||||
<div className="edt">
|
||||
<div className="edt_header">
|
||||
<button className="edt_button_week_select" onClick={() =>handlePrev()}>Prev</button>
|
||||
<button onClick={()=>refresh()}>Actualiser</button>
|
||||
<button className="edt_button_week_select" onClick={() => handleNext()}>Next</button>
|
||||
</div>
|
||||
<div className="edt_colonnes">
|
||||
<div className="top_left_loading">{loading && <Loading/>}</div>
|
||||
{week_days_nums.map((num,index)=>(
|
||||
<div className="edt_colonne">
|
||||
<div className={`edt_colonne ${sameDay(getNextDay(week, index), new Date()) ? "today" : ""}`}>
|
||||
<div className="edt_day_header">
|
||||
<div> {week_days[index]} </div>
|
||||
<div className="edt_date"> {dateToString(getNextDay(week,index))} </div>
|
||||
|
||||
@@ -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 =() =>{
|
||||
<div>
|
||||
Nom : { user.nom}
|
||||
</div>
|
||||
{user instanceof Athlete && <div>Role : Athlete</div>}
|
||||
{user instanceof Coach && <div>Role : Coach</div>}
|
||||
{user instanceof Admin && <div>Role : Admin</div>}
|
||||
|
||||
</div>
|
||||
}
|
||||
|
||||
@@ -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<Activite[]>([]);
|
||||
const [open2, setOpen2] = useState<boolean>(false);
|
||||
const [loading,setLoading] = useState<boolean>(false);
|
||||
const [join,setJoin] = useState<boolean>(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(
|
||||
<Modal isOpen={open} onClose={() => setOpen(false)}>
|
||||
<div className="object_modal">
|
||||
<h2>{session.name}</h2>
|
||||
<div>{hoursToString(sDate)}</div>
|
||||
<div>{dateToString(sDate)}</div>
|
||||
{user instanceof Athlete &&
|
||||
<div>
|
||||
{user.sessions.includes(session) ? <button onClick={()=>unsubscribeSession()}>quitter</button>
|
||||
:<button onClick={()=>subscribeSession()}>rejoindre</button>}
|
||||
</div>
|
||||
}
|
||||
|
||||
<Modal isOpen={open} onClose={() => setOpen(false)}>
|
||||
<div className="object_modal">
|
||||
<div>{session.name}</div>
|
||||
<div>{hoursToString(sDate)}</div>
|
||||
<div>{dateToString(sDate)}</div>
|
||||
<div>
|
||||
Activités :
|
||||
<div className="session_modal_activite_list">
|
||||
{activites.map((activite,index)=>(
|
||||
<div>
|
||||
{activite.nom}
|
||||
<button className="deleteButton" onClick={() => handleDeleteActivite(activite)}>x</button>
|
||||
</div>
|
||||
))}
|
||||
<button className="addButton" onClick={() => handleAddActivite()}>+</button>
|
||||
{loading && <div className='top_left_loading'><Loading/></div>}
|
||||
<div>
|
||||
Activités :
|
||||
<div className="session_modal_activite_list">
|
||||
{activites.map((activite,index)=>(
|
||||
<div>
|
||||
{activite.nom}
|
||||
<button className="deleteButton" onClick={() => handleDeleteActivite(activite)}>x</button>
|
||||
</div>
|
||||
))}
|
||||
<button className="addButton" onClick={() => handleAddActivite()}>+</button>
|
||||
{loading && <div className='top_left_loading'><Loading/></div>}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{open2 &&
|
||||
<CreateActivite returnActivite={(activite) => returnActivite(activite)}/>
|
||||
}
|
||||
</div>
|
||||
</Modal>
|
||||
|
||||
)
|
||||
</Modal>
|
||||
)
|
||||
}else{
|
||||
return(
|
||||
<CreateActivite returnActivite={(activite) => returnActivite(activite)} session={session}/>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default DetailSession;
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
margin: 0px;
|
||||
font-size: 20px;
|
||||
display: inline;
|
||||
border-color: var(--accent1);
|
||||
border-color: var(--green-A-primary);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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 */
|
||||
* {
|
||||
|
||||
@@ -135,7 +135,7 @@ export async function subscribeSessionAPI(user:User, session:Session):Promise<bo
|
||||
}
|
||||
}
|
||||
|
||||
export async function unsubscribeSessionAPI(user:User, session:Session):Promise<boolean>{
|
||||
export async function unsubscribeSessionAPI(user:Athlete, session:Session):Promise<boolean>{
|
||||
try {
|
||||
const session_id =session.id
|
||||
const user_id = user.id
|
||||
|
||||
Reference in New Issue
Block a user