Merge remote-tracking branch 'refs/remotes/origin/main'
This commit is contained in:
@@ -27,4 +27,11 @@ npm install
|
||||
npm start
|
||||
|
||||
#### Docker
|
||||
sudo docker stop $(sudo docker ps -a -q)
|
||||
sudo docker stop $(sudo docker ps -a -q)
|
||||
|
||||
#### Pour acceder sur docker
|
||||
sudo docker exec -it frisbyee-postgres psql -U frisbyee_user -d frisbyee
|
||||
|
||||
#### Voir les données:
|
||||
\dt
|
||||
SELECT * FROM session;
|
||||
|
||||
@@ -14,7 +14,7 @@ import org.springframework.web.server.ResponseStatusException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@Controller
|
||||
@RestController
|
||||
@RequestMapping("/coach")
|
||||
public class CoachResource {
|
||||
@Autowired
|
||||
@@ -29,8 +29,8 @@ public class CoachResource {
|
||||
}
|
||||
|
||||
@GetMapping("/all")
|
||||
@PreAuthorize("hasRole('Admin') or hasRole('Coach')")
|
||||
public List<CoachDTO> getAll() {
|
||||
System.out.println("GET /coach/all called");
|
||||
List<Coach> coaches = coachDAO.findAll();
|
||||
List<CoachDTO> dtos = new ArrayList<>();
|
||||
for (Coach coach : coaches) {
|
||||
|
||||
@@ -7,5 +7,7 @@ spring.jpa.hibernate.ddl-auto=update
|
||||
spring.jpa.show-sql=true
|
||||
spring.jpa.database-platform=org.hibernate.dialect.PostgreSQLDialect
|
||||
server.port=8081
|
||||
server.servlet.context-path=/api
|
||||
|
||||
spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:8080/realms/Frisbyee_realm
|
||||
spring.security.oauth2.resourceserver.jwt.jwk-set-uri: http://localhost:8080/realms/Frisbyee_realm/protocol/openid-connect/certs
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import React from 'react';
|
||||
import './App.css';
|
||||
import { ReactKeycloakProvider } from '@react-keycloak/web'
|
||||
import keycloak from './keycloak'
|
||||
@@ -7,8 +7,15 @@ import { LocalDataProvider } from './provider/LocalDataProvider';
|
||||
import EDT from './components/edt';
|
||||
import SwitchThemeColor from './components/SwitchThemeColor';
|
||||
import CreateSession from './components/createSession'
|
||||
import EdtCoach from './components/edt_coach'
|
||||
import { Coach } from "./classes";
|
||||
import RessourcePanel from './components/ressourcePanel';
|
||||
import TestAPI from './components/test_api';
|
||||
|
||||
// Test
|
||||
const testCoach = new Coach();
|
||||
testCoach.id = 1;
|
||||
testCoach.nom = "Coach Test";
|
||||
|
||||
const keycloakInitOptions = {
|
||||
onLoad: 'login-required',
|
||||
@@ -29,6 +36,8 @@ function App() {
|
||||
<RessourcePanel/>
|
||||
<EDT/>
|
||||
<CreateSession/>
|
||||
|
||||
<TestAPI/>
|
||||
</div>
|
||||
</LocalDataProvider>
|
||||
</ReactKeycloakProvider>
|
||||
|
||||
@@ -135,8 +135,8 @@ export function getUserTest():User{
|
||||
s1.activites.push(act2);
|
||||
s2.activites.push(act3);
|
||||
s2.activites.push(act4);
|
||||
s3.activites.push(act5);
|
||||
s3.activites.push(act6);
|
||||
s2.activites.push(act5);
|
||||
s2.activites.push(act6);
|
||||
|
||||
user.sessions.push(s1);
|
||||
user.sessions.push(s2);
|
||||
|
||||
50
front_end/src/components/edt_coach.tsx
Normal file
50
front_end/src/components/edt_coach.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
import { useState } from "react";
|
||||
import { coachService } from "../api";
|
||||
|
||||
export default function EdtCoach() {
|
||||
const [name, setName] = useState("");
|
||||
const [error, setError] = useState("");
|
||||
const [statusCode, setStatusCode] = useState<number | null>(null);
|
||||
|
||||
const handleCreate = async () => {
|
||||
try {
|
||||
const response = await coachService.create({ name });
|
||||
console.log("Success:", response.status, response.data);
|
||||
alert(`Coach created! Status: ${response.status}`);
|
||||
setError("");
|
||||
setStatusCode(response.status);
|
||||
} catch (err: any) {
|
||||
if (err.response) {
|
||||
// This is the HTTP response from the server
|
||||
console.error("HTTP status:", err.response.status);
|
||||
console.error("Response data:", err.response.data);
|
||||
setError(`Failed to create coach: ${err.response.data}`);
|
||||
setStatusCode(err.response.status);
|
||||
} else if (err.request) {
|
||||
console.error("No response received", err.request);
|
||||
setError("No response from server!");
|
||||
setStatusCode(null);
|
||||
} else {
|
||||
console.error("Error", err.message);
|
||||
setError(err.message);
|
||||
setStatusCode(null);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Create Coach</h2>
|
||||
<input
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="Coach name"
|
||||
/>
|
||||
<button onClick={handleCreate}>Create</button>
|
||||
|
||||
{error && <p style={{ color: "red" }}>{error}</p>}
|
||||
{statusCode && <p>HTTP Status: {statusCode}</p>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -20,6 +20,16 @@ function EdtSession({session}:Props){
|
||||
setOpen(!open);
|
||||
}
|
||||
|
||||
function handleDeleteActivite(): void {
|
||||
session.activites.pop(); //TODO
|
||||
}
|
||||
|
||||
function handleAddActivite(): void {
|
||||
const newActivite = new Activite();
|
||||
//TODO
|
||||
session.activites.push(newActivite);
|
||||
}
|
||||
|
||||
async function updateActivites(){
|
||||
//TODO
|
||||
await delay(2000);
|
||||
@@ -46,19 +56,27 @@ function EdtSession({session}:Props){
|
||||
<div>{session.name}</div>
|
||||
</div>
|
||||
{open &&
|
||||
<Modal isOpen={open} onClose={() => setOpen(false)}>
|
||||
<div className="edt_session_modal">
|
||||
<div>{session.name}</div>
|
||||
<div>{hoursToString(sDate)}</div>
|
||||
<div>{dateToString(sDate)}</div>
|
||||
<Modal isOpen={open} onClose={() => setOpen(false)}>
|
||||
<div className="edt_session_modal">
|
||||
<div>{session.name}</div>
|
||||
<div>{hoursToString(sDate)}</div>
|
||||
<div>{dateToString(sDate)}</div>
|
||||
<div>
|
||||
Activités :
|
||||
<div className="ent_activite_list">
|
||||
{session.activites.map((activite,index)=>(
|
||||
<div>activite</div>
|
||||
<div>
|
||||
{activite.nom}
|
||||
<button className="deleteButton" onClick={() => handleDeleteActivite}>x</button>
|
||||
</div>
|
||||
))}
|
||||
<button className="addButton" onClick={() => handleAddActivite}>+</button>
|
||||
{loading && <div className='edt_loading'><Loading/></div>}
|
||||
</div>
|
||||
|
||||
</Modal>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import ListGroup from "react-bootstrap/ListGroup";
|
||||
import { Athlete, Activite } from "../classes";
|
||||
|
||||
type Props = {
|
||||
@@ -9,26 +8,22 @@ type Props = {
|
||||
|
||||
function AthleteList({ athletes }: Props) {
|
||||
return (
|
||||
<ListGroup>
|
||||
<ul className="AthleteList">
|
||||
{athletes.map((athlete) => (
|
||||
<ListGroup.Item key={athlete.id}>
|
||||
<div>
|
||||
<strong>Nom:</strong> {athlete.nom}
|
||||
</div>
|
||||
<div>
|
||||
<strong>Groupe:</strong> {athlete.groupe}
|
||||
</div>
|
||||
</ListGroup.Item>
|
||||
<li key={athlete.id}>
|
||||
<div><strong>Nom:</strong> {athlete.nom}</div>
|
||||
<div><strong>Groupe:</strong> {athlete.groupe}</div>
|
||||
</li>
|
||||
))}
|
||||
</ListGroup>
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
function ActiviteList({ activites }: Props) {
|
||||
return (
|
||||
<ListGroup>
|
||||
<ul className="ActiviteList">
|
||||
{activites.map((activite) => (
|
||||
<ListGroup.Item key={activite.id}>
|
||||
<li key={activite.id}>
|
||||
<div>
|
||||
<strong>Nom:</strong> {activite.nom}
|
||||
</div>
|
||||
@@ -38,9 +33,9 @@ function ActiviteList({ activites }: Props) {
|
||||
<div>
|
||||
<strong>Durée:</strong> {activite.duree} minutes
|
||||
</div>
|
||||
</ListGroup.Item>
|
||||
</li>
|
||||
))}
|
||||
</ListGroup>
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,8 +98,24 @@
|
||||
|
||||
.edt_session_modal{
|
||||
background-color: var(--tint2);
|
||||
padding: 20px;
|
||||
padding: 10px;
|
||||
border-radius: 20px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ent_activite_list{
|
||||
padding: 10px;
|
||||
background-color: var(--tint3);
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.deleteButton{
|
||||
background-color: #FF0000;
|
||||
border-color: #AA0000;
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.addButton{
|
||||
background-color: var(--tint5);
|
||||
border-radius: 10px;
|
||||
}
|
||||
16
front_end/src/components/test_api.tsx
Normal file
16
front_end/src/components/test_api.tsx
Normal file
@@ -0,0 +1,16 @@
|
||||
import { getUsersAPI } from "../requetes"
|
||||
|
||||
function TestAPI(){
|
||||
|
||||
function handleGetUsers(): void {
|
||||
getUsersAPI()
|
||||
}
|
||||
|
||||
return(
|
||||
<div style={{padding:30, backgroundColor:"#000000"}}>
|
||||
<button onClick={()=>handleGetUsers()}>getUsers</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default TestAPI
|
||||
@@ -2,7 +2,8 @@ import api from "./api";
|
||||
import { Activite, Athlete, Coach, Session, User } from "./classes";
|
||||
//import { useKeycloak } from '@react-keycloak/web'
|
||||
|
||||
//const { keycloak } = useKeycloak()
|
||||
import { useKeycloak } from '@react-keycloak/web'
|
||||
import { useAuthHeader } from "./hook/useAuthHeader";
|
||||
/*
|
||||
const useAuthHeader = () => {
|
||||
return keycloak?.token
|
||||
@@ -72,7 +73,7 @@ export async function subscribeSessionAPI(user:User, session:Session):Promise<bo
|
||||
|
||||
export async function unsubscribeSessionAPI(user:User, session:Session):Promise<boolean>{
|
||||
try {
|
||||
await api.post(`/sessions/${session.id}/unsubscribe`, { userId: user.id });
|
||||
await api.post(`/session/${session.id}/unsubscribe`, { userId: user.id });
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error("Error unsubscribing from session:", error);
|
||||
@@ -93,9 +94,9 @@ export async function updateAllUserAPI(){
|
||||
// POST /////////////////////////////////////////////////////////
|
||||
|
||||
// COACH ADMIN
|
||||
export async function createSessionAPI(newSession: Session): Promise<Session> {
|
||||
export async function createSessionAPI(sessionDTO: any): Promise<Session> {
|
||||
try {
|
||||
const response = await api.post<Session>("/sessions", newSession);
|
||||
const response = await api.post<Session>("/session/create", sessionDTO);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error("Error creating session:", error);
|
||||
@@ -105,7 +106,7 @@ export async function createSessionAPI(newSession: Session): Promise<Session> {
|
||||
|
||||
export async function postActivityAPI(session: Session, activity: Activite){
|
||||
try {
|
||||
const response = await api.post<Activite>(`/sessions/${session.id}/activities`, activity);
|
||||
const response = await api.post<Activite>(`/session/${session.id}/activities`, activity);
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error("Error creating activity:", error);
|
||||
@@ -131,7 +132,7 @@ export async function setSessionCreneauAPI(session: Session, date:Date){
|
||||
|
||||
export async function getSessionsAPI(): Promise<Session[]> {
|
||||
try {
|
||||
const response = await api.get<Session[]>("/sessions");
|
||||
const response = await api.get<Session[]>("/session");
|
||||
return response.data;
|
||||
} catch (error) {
|
||||
console.error("Error fetching sessions:", error);
|
||||
|
||||
Reference in New Issue
Block a user