add endpoint to frontend
This commit is contained in:
@@ -27,20 +27,3 @@ services:
|
|||||||
interval: 5s
|
interval: 5s
|
||||||
timeout: 5s
|
timeout: 5s
|
||||||
retries: 20
|
retries: 20
|
||||||
postgres:
|
|
||||||
image: postgres:16
|
|
||||||
container_name: frisbyee-postgres
|
|
||||||
ports:
|
|
||||||
- "5432:5432"
|
|
||||||
environment:
|
|
||||||
POSTGRES_DB: frisbyee
|
|
||||||
POSTGRES_USER: frisbyee_user
|
|
||||||
POSTGRES_PASSWORD: secret
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
|
|
||||||
version: "3.9"
|
|
||||||
|
|
||||||
|
|||||||
1883
front_end/package-lock.json
generated
1883
front_end/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -12,6 +12,8 @@
|
|||||||
"@types/node": "^16.18.126",
|
"@types/node": "^16.18.126",
|
||||||
"@types/react": "^19.2.7",
|
"@types/react": "^19.2.7",
|
||||||
"@types/react-dom": "^19.2.3",
|
"@types/react-dom": "^19.2.3",
|
||||||
|
"axios": "^1.13.2",
|
||||||
|
"keycloak-js": "^26.2.2",
|
||||||
"react": "^19.2.3",
|
"react": "^19.2.3",
|
||||||
"react-dom": "^19.2.3",
|
"react-dom": "^19.2.3",
|
||||||
"react-scripts": "5.0.1",
|
"react-scripts": "5.0.1",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import keycloak from './keycloak'
|
|||||||
import Login from './components/login';
|
import Login from './components/login';
|
||||||
import { LocalDataProvider } from './provider/LocalDataProvider';
|
import { LocalDataProvider } from './provider/LocalDataProvider';
|
||||||
import ENT from './components/ent';
|
import ENT from './components/ent';
|
||||||
|
import CreateSession from './components/createSession'
|
||||||
|
|
||||||
|
|
||||||
const keycloakInitOptions = {
|
const keycloakInitOptions = {
|
||||||
@@ -33,6 +34,7 @@ function App() {
|
|||||||
</a>
|
</a>
|
||||||
<Login/>
|
<Login/>
|
||||||
<ENT/>
|
<ENT/>
|
||||||
|
<CreateSession/>
|
||||||
</header>
|
</header>
|
||||||
</div>
|
</div>
|
||||||
</LocalDataProvider>
|
</LocalDataProvider>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export type Groupe = "Entrainement" | "Competition" | "Loisir";
|
export type Groupe = "Entrainement" | "Competition" | "Loisir"| "";
|
||||||
|
|
||||||
export class User{
|
export class User{
|
||||||
id!: number;
|
id!: number;
|
||||||
@@ -21,9 +21,10 @@ export class Coach extends User{
|
|||||||
|
|
||||||
export class Session{
|
export class Session{
|
||||||
id!: number;
|
id!: number;
|
||||||
|
name!: String;
|
||||||
activites!: Activite[];
|
activites!: Activite[];
|
||||||
isRecurent! : Boolean;
|
isRecurent! : Boolean;
|
||||||
Creneau!: Date;
|
creneau!: Date;
|
||||||
coach!: Coach;
|
coach!: Coach;
|
||||||
athletes!: Athlete[]
|
athletes!: Athlete[]
|
||||||
duree! : number;
|
duree! : number;
|
||||||
@@ -36,6 +37,6 @@ export class Activite{
|
|||||||
session!: Session;
|
session!: Session;
|
||||||
theme!: String;
|
theme!: String;
|
||||||
data!: Map<String,String>;
|
data!: Map<String,String>;
|
||||||
Duree!: number;
|
duree!: number;
|
||||||
|
|
||||||
}
|
}
|
||||||
106
front_end/src/components/createSession.tsx
Normal file
106
front_end/src/components/createSession.tsx
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
import { useState, useEffect } from "react";
|
||||||
|
import { Session, User, Coach, Activite, Groupe } from "../classes";
|
||||||
|
import { useLocalData } from "../context/useLocalData";
|
||||||
|
|
||||||
|
|
||||||
|
export const CreateSession = () => {
|
||||||
|
const {user} = useLocalData()
|
||||||
|
const [name,setName] = useState("");
|
||||||
|
const [groupe, setGroupe] = useState<Groupe>("");
|
||||||
|
const [creneau, setCreneau] = useState("");
|
||||||
|
const [duree, setDuree] = useState<number>(0);
|
||||||
|
const [activities, setActivities] = useState<Activite[]>([]);
|
||||||
|
const [activiteNom, setActiviteNom] = useState("");
|
||||||
|
const [activiteTheme, setActiviteTheme] = useState("");
|
||||||
|
const [activiteDuree, setActiviteDuree] = useState(0);
|
||||||
|
const [isRecurent, setIsRecurent] = useState(false);
|
||||||
|
|
||||||
|
function addAcitivte(){
|
||||||
|
if (!activiteNom) return;
|
||||||
|
|
||||||
|
const newActivite = new Activite();
|
||||||
|
newActivite.nom= activiteNom;
|
||||||
|
newActivite.theme=activiteTheme;
|
||||||
|
newActivite.duree= activiteDuree;
|
||||||
|
newActivite.data= new Map<String,String>();
|
||||||
|
setActivities([...activities, newActivite]);
|
||||||
|
|
||||||
|
setActiviteNom("");
|
||||||
|
setActiviteTheme("");
|
||||||
|
setActiviteDuree(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleCreateSession(){
|
||||||
|
const newSession = new Session();
|
||||||
|
newSession.name = name;
|
||||||
|
newSession.activites= activities;
|
||||||
|
newSession.groupe = groupe;
|
||||||
|
newSession.creneau = new Date(creneau);
|
||||||
|
newSession.duree= duree;
|
||||||
|
newSession.isRecurent= isRecurent;
|
||||||
|
newSession.coach= user as Coach;
|
||||||
|
newSession.athletes= [];
|
||||||
|
newSession.activites= activities;
|
||||||
|
|
||||||
|
try{
|
||||||
|
//reset
|
||||||
|
setName("");
|
||||||
|
setGroupe("");
|
||||||
|
setCreneau("");
|
||||||
|
setDuree(0);
|
||||||
|
setIsRecurent(false);
|
||||||
|
setActivities([]);
|
||||||
|
}catch (err){
|
||||||
|
console.error(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ent">
|
||||||
|
<h2>Activité</h2>
|
||||||
|
<label>
|
||||||
|
Name:
|
||||||
|
<input type="text" value={activiteNom} onChange={e => setActiviteNom(e.target.value)} />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Theme:
|
||||||
|
<input type="text" value={activiteTheme} onChange={e => setActiviteTheme(e.target.value)} />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Duree (minutes):
|
||||||
|
<input type="number" value={activiteDuree} onChange={e => setActiviteDuree(Number(e.target.value))} />
|
||||||
|
</label>
|
||||||
|
<button type="button" onClick={addAcitivte}>Add Activite</button>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{activities.map((act, idx) => (
|
||||||
|
<li key={idx}>{act.nom} - {act.theme} ({act.duree} min)</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<h2>Create Session</h2>
|
||||||
|
<label>
|
||||||
|
Name:
|
||||||
|
<input type="text" value={name} onChange={e => setName(e.target.value)} />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Groupe:
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Creneau:
|
||||||
|
<input type="datetime-local" value={creneau} onChange={e => setCreneau(e.target.value)} />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Duree (minutes):
|
||||||
|
<input type="number" value={duree} onChange={e => setDuree(Number(e.target.value))} />
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Recurrent:
|
||||||
|
<input type="checkbox" checked={isRecurent} onChange={e => setIsRecurent(e.target.checked)} />
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<button type="button" onClick={handleCreateSession}>Create Session</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CreateSession;
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import api from "./api";
|
||||||
import { Activite, Athlete, Coach, Session, User } from "./classes";
|
import { Activite, Athlete, Coach, Session, User } from "./classes";
|
||||||
/*import { useKeycloak } from '@react-keycloak/web'
|
/*import { useKeycloak } from '@react-keycloak/web'
|
||||||
|
|
||||||
@@ -16,50 +17,95 @@ const useAuthHeader = () => {
|
|||||||
/*
|
/*
|
||||||
retourne l'utilisateur lié à l'identifiant keyloack
|
retourne l'utilisateur lié à l'identifiant keyloack
|
||||||
*/
|
*/
|
||||||
export async function getUser(id:number): Promise<boolean>{
|
export async function getUser(id:number): Promise<User|null>{
|
||||||
//keycloak.id;
|
try {
|
||||||
return true;
|
const response = await api.get<User>(`/users/${id}`);
|
||||||
|
return response.data;
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error("Error fetching user:", error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
retourne toutes les Session dont l'user est inscrit
|
retourne toutes les Session dont l'user est inscrit
|
||||||
*/
|
*/
|
||||||
export async function updateSessionsOfUser(user:Coach|Athlete, min: Date|null, max: Date|null){
|
export async function updateSessionsOfUserAPI(user:Coach|Athlete, min: Date|null, max: Date|null){
|
||||||
//TODO
|
try {
|
||||||
|
const response = await api.get<Session[]>(`/users/${user.id}/sessions`, {
|
||||||
|
params: {
|
||||||
|
minDate: min ? min.toISOString() : undefined,
|
||||||
|
maxDate: max ? max.toISOString() : undefined
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching sessions for user:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateActivitiesOfSession(session:Session){
|
export async function updateActivitiesOfSessionAPI(session:Session){
|
||||||
//TODO
|
try {
|
||||||
|
const response = await api.get<Activite[]>(`/sessions/${session.id}/activities`);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching activities for session:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function subscribeSession(user:User, session:Session):Promise<boolean>{
|
export async function subscribeSessionAPI(user:User, session:Session):Promise<boolean>{
|
||||||
return true;
|
try {
|
||||||
|
await api.post(`/sessions/${session.id}/subscribe`, { userId: user.id });
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error subscribing to session:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function unsubscribeSession(user:User, session:Session):Promise<boolean>{
|
export async function unsubscribeSessionAPI(user:User, session:Session):Promise<boolean>{
|
||||||
return true;
|
try {
|
||||||
|
await api.post(`/sessions/${session.id}/unsubscribe`, { userId: user.id });
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error unsubscribing from session:", error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ADMIN :
|
// ADMIN :
|
||||||
|
|
||||||
export async function updateAllSession(min: Date, max: Date){
|
export async function updateAllSessionAPI(min: Date, max: Date){
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateAllUser(){
|
export async function updateAllUserAPI(){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// POST /////////////////////////////////////////////////////////
|
// POST /////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// COACH ADMIN
|
// COACH ADMIN
|
||||||
export async function postSession(session: Session){
|
export async function createSessionAPI(newSession: Session): Promise<Session> {
|
||||||
|
try {
|
||||||
|
const response = await api.post<Session>("/sessions", newSession);
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating session:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function postActivity(session: Session, activity: Activite){
|
export async function postActivityAPI(session: Session, activity: Activite){
|
||||||
//post nouvelle activitée
|
try {
|
||||||
|
const response = await api.post<Activite>(`/sessions/${session.id}/activities`, activity);
|
||||||
//associer la nouvelle activité à la session
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error creating activity:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function postUser(user: User):Promise<boolean>{
|
export async function postUser(user: User):Promise<boolean>{
|
||||||
@@ -69,11 +115,30 @@ export async function postUser(user: User):Promise<boolean>{
|
|||||||
// SET /////////////////////////////////////////////////////////
|
// SET /////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//ADMIN
|
//ADMIN
|
||||||
export async function setUserName(user: User, name: string){
|
export async function setUserNameAPI(user: User, name: string){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//COACH
|
//COACH
|
||||||
export async function setSessionCreneau(session: Session, date:Date){
|
export async function setSessionCreneauAPI(session: Session, date:Date){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getSessionsAPI(): Promise<Session[]> {
|
||||||
|
try {
|
||||||
|
const response = await api.get<Session[]>("/sessions");
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching sessions:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export async function getUsersAPI(): Promise<User[]> {
|
||||||
|
try {
|
||||||
|
const response = await api.get<User[]>("/users");
|
||||||
|
return response.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching users:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,11 +1,10 @@
|
|||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"target": "es5",
|
"target": "ES2020",
|
||||||
"lib": [
|
"lib": ["DOM", "DOM.Iterable", "ES2020"],
|
||||||
"dom",
|
"module": "ESNext",
|
||||||
"dom.iterable",
|
"moduleResolution": "bundler",
|
||||||
"esnext"
|
|
||||||
],
|
|
||||||
"allowJs": true,
|
"allowJs": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
@@ -13,14 +12,10 @@
|
|||||||
"strict": true,
|
"strict": true,
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"noFallthroughCasesInSwitch": true,
|
"noFallthroughCasesInSwitch": true,
|
||||||
"module": "esnext",
|
|
||||||
"moduleResolution": "node",
|
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noEmit": true,
|
"noEmit": true,
|
||||||
"jsx": "react-jsx"
|
"jsx": "react-jsx"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src"]
|
||||||
"src"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
94
package-lock.json
generated
94
package-lock.json
generated
@@ -2,5 +2,97 @@
|
|||||||
"name": "hackathon",
|
"name": "hackathon",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {}
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"dependencies": {
|
||||||
|
"react-router-dom": "^7.11.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/cookie": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/express"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react": {
|
||||||
|
"version": "19.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
|
||||||
|
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-dom": {
|
||||||
|
"version": "19.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
|
||||||
|
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peer": true,
|
||||||
|
"dependencies": {
|
||||||
|
"scheduler": "^0.27.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^19.2.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-router": {
|
||||||
|
"version": "7.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router/-/react-router-7.11.0.tgz",
|
||||||
|
"integrity": "sha512-uI4JkMmjbWCZc01WVP2cH7ZfSzH91JAZUDd7/nIprDgWxBV1TkkmLToFh7EbMTcMak8URFRa2YoBL/W8GWnCTQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cookie": "^1.0.1",
|
||||||
|
"set-cookie-parser": "^2.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"react-dom": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/react-router-dom": {
|
||||||
|
"version": "7.11.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.11.0.tgz",
|
||||||
|
"integrity": "sha512-e49Ir/kMGRzFOOrYQBdoitq3ULigw4lKbAyKusnvtDu2t4dBX4AGYPrzNvorXmVuOyeakai6FUPW5MmibvVG8g==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"react-router": "7.11.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": ">=18",
|
||||||
|
"react-dom": ">=18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/scheduler": {
|
||||||
|
"version": "0.27.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
|
||||||
|
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
|
"node_modules/set-cookie-parser": {
|
||||||
|
"version": "2.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz",
|
||||||
|
"integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user