This commit is contained in:
Amaël Kesteman
2026-01-07 18:03:59 +01:00
26 changed files with 255 additions and 184 deletions

View File

@@ -3,6 +3,8 @@ import lombok.Data;
@Data @Data
public class AdminDTO { public class AdminDTO {
private String id_keycloak;
private Integer id; private Integer id;
private String name; private String name;
private String prenom;
} }

View File

@@ -7,12 +7,12 @@ import java.util.List;
@Data @Data
public class AthleteDTO { public class AthleteDTO {
private Integer id; private String id_keycloak;
private String name; private String name;
private String prenom;
private String categorie; private String categorie;
private String niveau; private String niveau;
private List<String> groupes = new ArrayList<>(); private List<String> groupes = new ArrayList<>();
private List<Integer> sessionIds = new ArrayList<>(); private List<Integer> sessionIds = new ArrayList<>();
private Integer userId;
} }

View File

@@ -1,10 +1,13 @@
package hackathon.FrisbYEE.jpa.dto; package hackathon.FrisbYEE.jpa.dto;
import java.util.List;
import lombok.Data; import lombok.Data;
@Data @Data
public class CoachDTO { public class CoachDTO {
private Integer id; private String id_keycloak;
private String name; private String name;
private String prenom;
private List<Integer> sessionIds;
} }

View File

@@ -8,7 +8,6 @@ import java.util.List;
@Data @Data
public class SessionDTO { public class SessionDTO {
private Integer id;
private String name; private String name;
private Boolean isRecurrent; private Boolean isRecurrent;
private LocalDateTime creneau; private LocalDateTime creneau;

View File

@@ -5,8 +5,9 @@ import lombok.Data;
@Data @Data
public class UserDTO { public class UserDTO {
private Integer id; private String id_keycloak;
private String name; private String name;
private String prenom;
private String email; private String email;
private Role role; private Role role;
} }

View File

@@ -16,9 +16,10 @@ import jakarta.persistence.Entity;
public class Admin extends User{ public class Admin extends User{
public Admin(String name){ public Admin(String id_keycloak, String name, String prenom){
super(name); super(name, id_keycloak, prenom, Role.ADMIN );
} }
@Override @Override
public String toString() { public String toString() {
return "Admin [id=" + super.getId() + " , name=" + super.getName() + "]"; return "Admin [id=" + super.getId() + " , name=" + super.getName() + "]";

View File

@@ -28,15 +28,8 @@ public class Athlete extends User{
@ManyToMany(mappedBy = "athletes") @ManyToMany(mappedBy = "athletes")
private List<Session> sessions = new ArrayList<>(); // plusieurs sessions sont possibles private List<Session> sessions = new ArrayList<>(); // plusieurs sessions sont possibles
public Athlete(String name){ public Athlete(String name, String id_keycloak, String prenom){
super(name); super(name, id_keycloak, prenom, Role.ATHLETE);
}
public Athlete(String name, String categorie, String niveau, List<String> groupe){
super(name);
this.categorie = categorie;
this.niveau = niveau;
this.groupe = groupe;
} }
@Override @Override

View File

@@ -22,9 +22,10 @@ public class Coach extends User{
@OneToMany(mappedBy = "coach") @OneToMany(mappedBy = "coach")
private List<Session> sessions = new ArrayList<>(); // Un coach peut avoir plusieurs sessions private List<Session> sessions = new ArrayList<>(); // Un coach peut avoir plusieurs sessions
public Coach(String name){ public Coach(String name, String id_keycloak, String prenom){
super(name); super(name, id_keycloak, prenom, Role.COACH );
} }
@Override @Override
public String toString() { public String toString() {
return "Coach [id=" + super.getId() + " , name=" + super.getName() + "]"; return "Coach [id=" + super.getId() + " , name=" + super.getName() + "]";

View File

@@ -32,7 +32,7 @@ public class Session {
private String groupe; private String groupe;
@ManyToOne @ManyToOne
private User coach; // un coach par session private Coach coach; // un coach par session
@ManyToMany @ManyToMany
private List<Athlete> athletes = new ArrayList<>(); // plusieurs athlètes par session private List<Athlete> athletes = new ArrayList<>(); // plusieurs athlètes par session
@@ -56,4 +56,21 @@ public class Session {
public String toString() { public String toString() {
return "Session [id=" + id + " , name=" + name + "]"; return "Session [id=" + id + " , name=" + name + "]";
} }
public void setCoach(Coach coach) {
if (coach.getRole() != Role.COACH) {
throw new IllegalArgumentException("L'utilisateur n'est pas un coach");
}
this.coach = coach;
}
public void setAthletes(List<Athlete> athletes) {
for (Athlete athlete : athletes) {
if (athlete.getRole() != Role.ATHLETE) {
throw new IllegalArgumentException("L'utilisateur n'est pas un athlète");
}
}
this.athletes = athletes;
}
} }

View File

@@ -30,33 +30,18 @@ public class User implements Serializable {
private Integer id; private Integer id;
@Column(nullable = false, unique = true) @Column(nullable = false, unique = true)
private String id_keycloak; private String id_keycloak;
private String name; private String name;
@Column(nullable = false) private String prenom;
private String motDePasse;
private String email;
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
@Column(nullable = false) @Column(nullable = false)
private Role role; private Role role;
@OneToOne(cascade = CascadeType.ALL) public User(String name, String id_keycloak, String prenom, Role role) {
private Coach coach;
@OneToOne(cascade = CascadeType.ALL)
private Athlete athlete;
@OneToOne(cascade = CascadeType.ALL)
private Admin admin;
public User(String name) {
this.name = name; this.name = name;
} this.id_keycloak = id_keycloak;
this.prenom = prenom;
public User(String name, String motDePasse, String email, Role role) {
this.name = name;
this.motDePasse = motDePasse;
this.email = email;
this.role = role; this.role = role;
} }

View File

@@ -0,0 +1,10 @@
package hackathon.FrisbYEE.jpa.service;
import hackathon.FrisbYEE.jpa.metier.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;
@Repository
public interface UserDAO extends JpaRepository<User, Integer> {
}

View File

@@ -126,7 +126,7 @@ public class AthleteResource {
private AthleteDTO mapToDTO(Athlete athlete) { private AthleteDTO mapToDTO(Athlete athlete) {
AthleteDTO dto = new AthleteDTO(); AthleteDTO dto = new AthleteDTO();
dto.setId(athlete.getId()); dto.setId_keycloak(athlete.getId_keycloak());
dto.setName(athlete.getName()); dto.setName(athlete.getName());
dto.setCategorie(athlete.getCategorie()); dto.setCategorie(athlete.getCategorie());
dto.setNiveau(athlete.getNiveau()); dto.setNiveau(athlete.getNiveau());
@@ -135,10 +135,6 @@ public class AthleteResource {
private Athlete mapToEntity(AthleteDTO dto) { private Athlete mapToEntity(AthleteDTO dto) {
Athlete athlete = new Athlete(); Athlete athlete = new Athlete();
athlete.setId(dto.getId());
athlete.setName(dto.getName());
athlete.setCategorie(dto.getCategorie());
athlete.setNiveau(dto.getNiveau());
return athlete; return athlete;
} }
@@ -156,7 +152,6 @@ public class AthleteResource {
for (Session s : sessions) { for (Session s : sessions) {
if (s.getAthletes().contains(j.get())) { if (s.getAthletes().contains(j.get())) {
SessionDTO dto = new SessionDTO(); SessionDTO dto = new SessionDTO();
dto.setId(s.getId());
dto.setName(s.getName()); dto.setName(s.getName());
// Map other fields as necessary // Map other fields as necessary
athleteSessions.add(dto); athleteSessions.add(dto);
@@ -177,7 +172,6 @@ public class AthleteResource {
List<SessionDTO> sessionDTOs = new ArrayList<>(); List<SessionDTO> sessionDTOs = new ArrayList<>();
for (Session session : sessions) { for (Session session : sessions) {
SessionDTO dto = new SessionDTO(); SessionDTO dto = new SessionDTO();
dto.setId(session.getId());
dto.setName(session.getName()); dto.setName(session.getName());
// Map other fields as necessary // Map other fields as necessary
sessionDTOs.add(dto); sessionDTOs.add(dto);
@@ -229,7 +223,6 @@ public class AthleteResource {
// sympa les // sympa les
// dates // dates
SessionDTO dto = new SessionDTO(); SessionDTO dto = new SessionDTO();
dto.setId(session.getId());
dto.setName(session.getName()); dto.setName(session.getName());
// Map other fields as necessary // Map other fields as necessary
filteredSessions.add(dto); filteredSessions.add(dto);
@@ -259,7 +252,6 @@ public class AthleteResource {
&& session.getCreneau().isAfter(ChronoLocalDateTime.from(LocalDate.parse(startDate))) && session.getCreneau().isAfter(ChronoLocalDateTime.from(LocalDate.parse(startDate)))
&& session.getCreneau().isBefore(ChronoLocalDateTime.from(LocalDate.parse(endDate)))) { && session.getCreneau().isBefore(ChronoLocalDateTime.from(LocalDate.parse(endDate)))) {
SessionDTO dto = new SessionDTO(); SessionDTO dto = new SessionDTO();
dto.setId(session.getId());
dto.setName(session.getName()); dto.setName(session.getName());
// Map other fields as necessary // Map other fields as necessary
filteredSessions.add(dto); filteredSessions.add(dto);

View File

@@ -7,7 +7,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
@@ -71,14 +70,14 @@ public class CoachResource {
private CoachDTO mapToDTO(Coach coach) { private CoachDTO mapToDTO(Coach coach) {
CoachDTO dto = new CoachDTO(); CoachDTO dto = new CoachDTO();
dto.setId(coach.getId()); dto.setId_keycloak(coach.getId_keycloak());
dto.setName(coach.getName()); dto.setName(coach.getName());
return dto; return dto;
} }
private Coach mapToEntity(CoachDTO dto) { private Coach mapToEntity(CoachDTO dto) {
Coach coach = new Coach(); Coach coach = new Coach();
coach.setId(dto.getId()); coach.setId_keycloak(dto.getId_keycloak());
coach.setName(dto.getName()); coach.setName(dto.getName());
return coach; return coach;
} }

View File

@@ -9,6 +9,7 @@ import hackathon.FrisbYEE.jpa.service.ActiviteDAO;
import hackathon.FrisbYEE.jpa.service.AthleteDAO; import hackathon.FrisbYEE.jpa.service.AthleteDAO;
import hackathon.FrisbYEE.jpa.service.CoachDAO; import hackathon.FrisbYEE.jpa.service.CoachDAO;
import hackathon.FrisbYEE.jpa.service.SessionDAO; import hackathon.FrisbYEE.jpa.service.SessionDAO;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
@@ -109,7 +110,6 @@ public class SessionResource {
private SessionDTO maptoDTO(Session s) { private SessionDTO maptoDTO(Session s) {
SessionDTO dto = new SessionDTO(); SessionDTO dto = new SessionDTO();
dto.setId(s.getId());
dto.setName(s.getName()); dto.setName(s.getName());
dto.setIsRecurrent(s.getIsRecurrent()); dto.setIsRecurrent(s.getIsRecurrent());
dto.setCreneau(s.getCreneau()); dto.setCreneau(s.getCreneau());
@@ -140,7 +140,6 @@ public class SessionResource {
private Session maptoEntity(SessionDTO dto) { private Session maptoEntity(SessionDTO dto) {
Session session = new Session(); Session session = new Session();
session.setId(dto.getId());
session.setName(dto.getName()); session.setName(dto.getName());
session.setIsRecurrent(dto.getIsRecurrent()); session.setIsRecurrent(dto.getIsRecurrent());
session.setCreneau(dto.getCreneau()); session.setCreneau(dto.getCreneau());

View File

@@ -12,6 +12,7 @@ api.interceptors.request.use((config) => {
if (keycloak?.token) { if (keycloak?.token) {
// eslint-disable-next-line no-param-reassign // eslint-disable-next-line no-param-reassign
config.headers.Authorization = `Bearer ${keycloak.token}`; config.headers.Authorization = `Bearer ${keycloak.token}`;
console.log(config.headers.Authorization);
} }
return config; return config;
}); });

View File

@@ -5,6 +5,7 @@ export class User{
id!: number; id!: number;
nom!: String; nom!: String;
sessions: Session[] = []; //nb: Admin liaison non symétrique /!\ sessions: Session[] = []; //nb: Admin liaison non symétrique /!\
email!: String;
role!: Role; role!: Role;
} }

View File

@@ -0,0 +1,75 @@
import { useState, useEffect } from "react";
import { Session, User, Coach, Activite, Groupe } from "../classes";
import { Modal } from "./Modal";
type CreateActiciteProps = {
returnActivite: (activite:Activite|null) => void
}
export function CreateActivite({ returnActivite }: CreateActiciteProps){
const [activities, setActivities] = useState<Activite[]>([]);
const [activiteNom, setActiviteNom] = useState("");
const [activiteTheme, setActiviteTheme] = useState("");
const [activiteDuree, setActiviteDuree] = useState(0);
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);
returnActivite(newActivite);
}
function cancel(){
returnActivite(null);
}
return (
<Modal isOpen={true} onClose={() => cancel()}>
<div className="edt_activite_modal">
<h2>Nouvelle Activité :</h2>
<div>
Nom de l'activité:
</div>
<div>
<input type="text" value={activiteNom} onChange={e => setActiviteNom(e.target.value)} />
</div>
<div>
Theme:
</div>
<div>
<input type="text" value={activiteTheme} onChange={e => setActiviteTheme(e.target.value)} />
</div>
<div>
Duree (minutes):
</div>
<div>
<input type="number" value={activiteDuree} onChange={e => setActiviteDuree(Number(e.target.value))} />
</div>
<button type="button" onClick={()=>addAcitivte()}>Ajouter l'activite</button>
<button type="button" onClick={()=>cancel()}>Annuler</button>
<ul>
{activities.map((act, idx) => (
<li key={idx}>{act.nom} - {act.theme} ({act.duree} min)</li>
))}
</ul>
</div>
</Modal>
);
};
export default CreateActivite;

View File

@@ -15,7 +15,7 @@ export const CreateSession = () => {
const [activiteDuree, setActiviteDuree] = useState(0); const [activiteDuree, setActiviteDuree] = useState(0);
const [isRecurent, setIsRecurent] = useState(false); const [isRecurent, setIsRecurent] = useState(false);
function addAcitivte(){ async function addAcitivte(){
if (!activiteNom) return; if (!activiteNom) return;
const newActivite = new Activite(); const newActivite = new Activite();
@@ -23,11 +23,18 @@ export const CreateSession = () => {
newActivite.theme=activiteTheme; newActivite.theme=activiteTheme;
newActivite.duree= activiteDuree; newActivite.duree= activiteDuree;
newActivite.data= new Map<string,string>(); newActivite.data= new Map<string,string>();
setActivities([...activities, newActivite]); try{
await sessionService.create(newActivite);
console.log("Session créée");
setActiviteNom(""); setActivities([...activities, newActivite]);
setActiviteTheme("");
setActiviteDuree(0); setActiviteNom("");
setActiviteTheme("");
setActiviteDuree(0);
} catch (error) {
console.error("Erreur lors de la création de la session", error);
}
} }
async function handleCreateSession() { async function handleCreateSession() {

View File

@@ -42,10 +42,7 @@ export const EDT =() =>{
var newWeek: Session[] = [] var newWeek: Session[] = []
user.sessions.forEach(session => { user.sessions.forEach(session => {
if( session.isRecurrent ){ if((session.creneau >= date && session.creneau <= maxDate && !session.isRecurrent) || session.isRecurrent){
newWeek.push(session);
}
if(session.creneau >= date && session.creneau <= maxDate && !session.isRecurrent){
newWeek.push(session); newWeek.push(session);
} }
}); });

View File

@@ -5,6 +5,7 @@ import './style/edt.css';
import { Modal } from './Modal'; import { Modal } from './Modal';
import Loading from './loading'; import Loading from './loading';
import {delay} from "../requetes"; import {delay} from "../requetes";
import CreateActivite from './createActivite';
type Props = { type Props = {
@@ -13,21 +14,22 @@ type Props = {
function EdtSession({session}:Props){ function EdtSession({session}:Props){
const [open, setOpen] = useState<boolean>(false) const [open, setOpen] = useState<boolean>(false);
const [open2, setOpen2] = useState<boolean>(false);
const [loading,setLoading] = useState<boolean>(false); const [loading,setLoading] = useState<boolean>(false);
const [activites,setActivites] = useState<Activite[]>([]);
function handleOpen(): void { function handleOpen(): void {
setOpen(!open); setOpen(!open);
} }
function handleDeleteActivite(): void { function handleDeleteActivite(activite:Activite): void {
session.activites.pop(); //TODO session.activites.splice(session.activites.indexOf(activite), 1);
setActivites([...session.activites])
} }
function handleAddActivite(): void { function handleAddActivite(): void {
const newActivite = new Activite(); setOpen2(true)
//TODO
session.activites.push(newActivite);
} }
async function updateActivites(){ async function updateActivites(){
@@ -45,7 +47,24 @@ function EdtSession({session}:Props){
} }
},[open]) },[open])
useEffect(() => {
if(!loading){
setActivites([...session.activites])
}
},[loading])
const sDate = session.creneau; const sDate = session.creneau;
function returnActivite(activite: Activite|null){
if(activite!==null){
session.activites.push(activite);
setActivites([...session.activites])
}
setOpen2(false);
}
return( return(
<div> <div>
<div className="edt_session" onClick={() => handleOpen()}> <div className="edt_session" onClick={() => handleOpen()}>
@@ -64,16 +83,20 @@ function EdtSession({session}:Props){
<div> <div>
Activités : Activités :
<div className="ent_activite_list"> <div className="ent_activite_list">
{session.activites.map((activite,index)=>( {activites.map((activite,index)=>(
<div> <div>
{activite.nom} {activite.nom}
<button className="deleteButton" onClick={() => handleDeleteActivite}>x</button> <button className="deleteButton" onClick={() => handleDeleteActivite(activite)}>x</button>
</div> </div>
))} ))}
<button className="addButton" onClick={() => handleAddActivite}>+</button> <button className="addButton" onClick={() => handleAddActivite()}>+</button>
{loading && <div className='edt_loading'><Loading/></div>} {loading && <div className='edt_loading'><Loading/></div>}
</div> </div>
</div> </div>
{open2 &&
<CreateActivite returnActivite={(activite) => returnActivite(activite)}/>
}
</div> </div>
</Modal> </Modal>
} }

View File

@@ -29,8 +29,19 @@ export const Login =() =>{
return( return(
<div> <div>
<div> <div>
Authenticated : {keycloak.authenticated ? 'oui' : 'non'} Etat : {keycloak.authenticated ? 'connecté' : 'non connecté'}
</div> </div>
{keycloak.authenticated &&
<div>
<div>
Keycloak ID : { keycloak.tokenParsed?.sub}
</div>
<div>
User nom : { user.nom}
</div>
</div>
}
<button onClick={() => handleLogin()}> <button onClick={() => handleLogin()}>
Se connecter Se connecter
</button> </button>

View File

@@ -118,4 +118,11 @@
.addButton{ .addButton{
background-color: var(--tint5); background-color: var(--tint5);
border-radius: 10px; border-radius: 10px;
}
.edt_activite_modal{
background-color: var(--tint3);
padding: 10px;
border-radius: 20px;
position: relative;
} }

View File

@@ -1,14 +1,27 @@
import { getUsersAPI } from "../requetes" import { useKeycloak } from "@react-keycloak/web"
import { getCoachsAPI, getUsersAPI, postAdmin } from "../requetes"
import { Admin } from "../classes";
function TestAPI(){ function TestAPI(){
const { keycloak } = useKeycloak()
function handleGetUsers(): void { function handleGetUsers(): void {
getUsersAPI() getCoachsAPI();
}
function handleSendAdmin(): void {
const admin = new Admin;
admin.nom = "admin";
admin.email = "admin@gmail.com";
postAdmin(admin);
} }
return( return(
<div style={{padding:30, backgroundColor:"#000000"}}> <div style={{padding:30, backgroundColor:"#000000"}}>
<button onClick={()=>handleGetUsers()}>getUsers</button> <button onClick={()=>handleGetUsers()}>getUsers</button>
<button onClick={()=>handleSendAdmin()}>sendAdmin</button>
</div> </div>
) )
} }

View File

@@ -64,4 +64,11 @@ code {
to { to {
transform: rotate(360deg); transform: rotate(360deg);
} }
}
input{
background-color: var(--tint2);
color: var(--test);
border-color: var(--tint5);
border-radius: 8px;
} }

View File

@@ -1,15 +1,5 @@
import api from "./api"; import api from "./api";
import { Activite, Athlete, Coach, Session, User } from "./classes"; import { Activite, Admin, Athlete, Coach, Session, User } from "./classes";
//import { useKeycloak } from '@react-keycloak/web'
import { useKeycloak } from '@react-keycloak/web'
import { useAuthHeader } from "./hook/useAuthHeader";
/*
const useAuthHeader = () => {
return keycloak?.token
? { Authorization: `Bearer ${keycloak.token}` }
: {}
}*/
//debug: //debug:
export function delay(ms: number): Promise<void> { export function delay(ms: number): Promise<void> {
@@ -63,7 +53,7 @@ export async function updateActivitiesOfSessionAPI(session:Session){
export async function subscribeSessionAPI(user:User, session:Session):Promise<boolean>{ export async function subscribeSessionAPI(user:User, session:Session):Promise<boolean>{
try { try {
await api.post(`/sessions/${session.id}/subscribe`, { userId: user.id }); await api.post(`/sessions/${session.id}/subscribe`);
return true; return true;
} catch (error) { } catch (error) {
console.error("Error subscribing to session:", error); console.error("Error subscribing to session:", error);
@@ -73,7 +63,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:User, session:Session):Promise<boolean>{
try { try {
await api.post(`/session/${session.id}/unsubscribe`, { userId: user.id }); await api.post(`/session/${session.id}/unsubscribe`);
return true; return true;
} catch (error) { } catch (error) {
console.error("Error unsubscribing from session:", error); console.error("Error unsubscribing from session:", error);
@@ -114,8 +104,26 @@ export async function postActivityAPI(session: Session, activity: Activite){
} }
} }
export async function postUser(user: User):Promise<boolean>{ export async function postAthlete(athlete: Athlete):Promise<Athlete>{
return true; try {
const response = await api.post<Athlete>("/athlete/create/",athlete);
console.log(response);
return response.data;
} catch (error) {
console.error("Error fetching coachs:", error);
throw error;
}
}
export async function postAdmin(athlete: Admin):Promise<Admin>{
try {
const response = await api.post<Admin>("/admin/create/",athlete);
console.log(response);
return response.data;
} catch (error) {
console.error("Error fetching coachs:", error);
throw error;
}
} }
// SET ///////////////////////////////////////////////////////// // SET /////////////////////////////////////////////////////////
@@ -147,4 +155,15 @@ export async function getUsersAPI(): Promise<User[]> {
console.error("Error fetching users:", error); console.error("Error fetching users:", error);
throw error; throw error;
} }
}
export async function getCoachsAPI(): Promise<Coach[]> {
try {
const response = await api.get<Coach[]>("/coach/all");
console.log(response);
return response.data;
} catch (error) {
console.error("Error fetching coachs:", error);
throw error;
}
} }

94
package-lock.json generated
View File

@@ -2,97 +2,5 @@
"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"
}
}
} }