From dc779da68138593ffd73856b72ea708aa450f479 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 14:15:51 +0100 Subject: [PATCH 01/29] remove irrelevant comment + disturbing variables --- src/pages/Profile/ProfilePage.tsx | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/src/pages/Profile/ProfilePage.tsx b/src/pages/Profile/ProfilePage.tsx index 4035569..9e2b576 100644 --- a/src/pages/Profile/ProfilePage.tsx +++ b/src/pages/Profile/ProfilePage.tsx @@ -1,5 +1,4 @@ import getXSRFToken from "../../utils/getXSRF.js"; -// import fetchWrapper from "../../utils/fetchWrapper"; import {useContext, useEffect, useState} from "react"; import styles from "./ProfilePage.module.css"; import {AuthContext} from "../../contexts/auth/AuthContext"; @@ -11,11 +10,9 @@ import {useNavigate} from "react-router"; import {useRef} from "react"; import getUserById from "../../utils/users/getUserById.js"; import ManageMember from "./components/manageMember/ManageMember.jsx"; - import uploadProfilePhoto from "../../utils/users/uploadProfilePhoto"; import deleteProfilePhoto from "../../utils/users/deleteProfilePhoto.js"; - interface TaskType { id: number; name: string; @@ -58,8 +55,6 @@ function ProfilePage() { const { user, update } = useContext(AuthContext) as AuthContextType; const [profileUser, setProfileUser] = useState(null); const [profilePicture, setProfilePicture] = useState(null); - const [error, setError] = useState(null); - const [success, setSuccess] = useState(null); const fileInputRef = useRef(null); const isOwnProfile = !id || user?.id.toString() === id; @@ -74,16 +69,14 @@ function ProfilePage() { return; } if (res.status !== 200) { - console.error("Erreur lors du chargement du profil", res); + console.log("Erreur lors du chargement du profil", res); return; } setProfileUser(res.data); } else { - //update(); setProfileUser(user); if (user?.profile_photo_path) { setProfilePicture(`${import.meta.env.VITE_API_URL}/storage/${user.profile_photo_path}`); - //setProfilePicture(`${import.meta.env.VITE_API_URL}/${user.profile_photo_path}`); } } })(); @@ -103,17 +96,13 @@ function ProfilePage() { const res = await uploadProfilePhoto(file); if (res.ok) { setProfilePicture(`${import.meta.env.VITE_API_URL}/storage/${res.data.profile_photo_path}`); - //setProfilePicture(`${import.meta.env.VITE_API_URL}/${res.data.profile_photo_path}`); - setSuccess("Photo mise à jour !"); - setError(null); + console.log("Photo mise à jour") await update(); } else { - setError(res.data?.message || res.error || "Erreur lors de l'upload."); - setSuccess(null); + console.log(res.data?.message || res.error || "Erreur lors de l'upload."); } } catch (err) { - setError("Erreur réseau."); - setSuccess(null); + console.log("Erreur réseau."); } }; const handleDeletePicture = async () => { @@ -154,8 +143,6 @@ function ProfilePage() { accept="image/*" style={{ display: "none" }} /> - {error &&

{error}

} - {success &&

{success}

}
From 664ebf1e529178c3776df17092720ff40ad84a49 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 14:23:09 +0100 Subject: [PATCH 02/29] edit interface TS --- src/components/ui/input/input.tsx | 24 +++++++------ src/contexts/events/EventContext.ts | 5 --- .../pendingMembers/PendingMembers.jsx | 2 -- .../Home/components/EventList/eventList.tsx | 35 ------------------- src/pages/Profile/ProfilePage.module.css | 5 --- src/utils/date/formatDateLetter.ts | 32 ----------------- src/utils/getUser.js | 2 +- 7 files changed, 14 insertions(+), 91 deletions(-) diff --git a/src/components/ui/input/input.tsx b/src/components/ui/input/input.tsx index 0cc1e7f..07099cb 100644 --- a/src/components/ui/input/input.tsx +++ b/src/components/ui/input/input.tsx @@ -11,14 +11,14 @@ interface TextInputProps extends InputHTMLAttributes { } const TextInput = ({ - placeholder, - onChange, - value, - borderStyle = "square", - password, - className = "", - ...props - }: TextInputProps) => { + placeholder = "", + onChange, + value = "", + borderStyle = "square", + password = false, + className = "", + ...props +}: TextInputProps) => { const [showPassword, setShowPassword] = useState(false); let inputBorderStyle = styles.square; @@ -28,15 +28,16 @@ const TextInput = ({ setShowPassword((prev) => !prev); }; - if (password) + if (password) { return (
-
); + } return ( { - // Vérifie explicitement que `events` est un tableau avant de trier - if (!Array.isArray(events)) return []; - return [...events].sort( - (a, b) => new Date(a.start) - new Date(b.start) - ); - }, [events]); - - return ( -
-

Liste des événements à venir

- {sortedEvents.length > 0 ? ( -
- {sortedEvents.map((eventGroup, index) => ( - - ))} -
- ) : ( -

Aucun événement planifié pour l'instant.

- )} -
- ); -} - -export default EventList;*/ import { useMemo, useContext } from "react"; import styles from "./eventList.module.css"; import EventItem from "./eventItem"; diff --git a/src/pages/Profile/ProfilePage.module.css b/src/pages/Profile/ProfilePage.module.css index 2bcecee..a47a7a7 100644 --- a/src/pages/Profile/ProfilePage.module.css +++ b/src/pages/Profile/ProfilePage.module.css @@ -1,4 +1,3 @@ -/* Conteneur principal */ .container { width: 100%; padding: 12px; @@ -113,7 +112,6 @@ margin: 0; } -/* Conteneur des informations principales */ .topDescription { display: flex; flex-direction: column; @@ -122,14 +120,12 @@ margin-bottom: 20px; } -/* Bloc d'informations */ .infoBlock { width: 100%; padding: 12px; box-sizing: border-box; } -/* Conteneur pour les paramètres */ .settingImage { width: 100%; display: flex; @@ -137,7 +133,6 @@ margin-top: 16px; } -/* Adaptation pour tablette et PC */ @media (min-width: 768px) { .contentWrapper { flex-direction: row; diff --git a/src/utils/date/formatDateLetter.ts b/src/utils/date/formatDateLetter.ts index f4c3f91..1da9160 100644 --- a/src/utils/date/formatDateLetter.ts +++ b/src/utils/date/formatDateLetter.ts @@ -1,35 +1,3 @@ - - -/*export function formatDateLetter(d) { - if (!d) return "Date inconnue"; - - const dateObj = new Date(d); - if (isNaN(dateObj.getTime())) return "Date invalide"; - - const monthNames = [ - "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", - "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" - ]; - - const day = dateObj.getDate().toString().padStart(2, "0"); - const month = monthNames[dateObj.getMonth()]; - const year = dateObj.getFullYear(); - const hours = dateObj.getHours().toString().padStart(2, "0"); - const minutes = dateObj.getMinutes().toString().padStart(2, "0"); - - return `${day} ${month} ${year} à ${hours}:${minutes}`; -} - - -export function formatDateLetterJS(d) { - const monthNames = [ - "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", - "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" - ]; - const [year, month, day] = d.split('-'); - return `${day} ${monthNames[parseInt(month) - 1]} ${year}`; -}*/ - export function formatDateLetter(d: string | Date | null | undefined): string { if (!d) return "Date inconnue"; diff --git a/src/utils/getUser.js b/src/utils/getUser.js index 6d71295..7a485b8 100644 --- a/src/utils/getUser.js +++ b/src/utils/getUser.js @@ -2,4 +2,4 @@ import fetchWrapper from "./fetchWrapper.js"; export default async function getUser() { return fetchWrapper("/api/users/me", null, "GET"); -} +} \ No newline at end of file From c3f71965c3dc86fe6ecd5bae5d1e0f5179b9e9f9 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Fri, 13 Mar 2026 14:40:24 +0100 Subject: [PATCH 03/29] Convert TS --- src/pages/EventDetail/EventDetailPage.jsx | 55 -------- src/pages/EventDetail/EventDetailPage.tsx | 65 +++++++++ .../CreateTaskBtn/CreateTaskBtn.jsx | 116 ---------------- .../CreateTaskBtn/CreateTaskBtn.tsx | 129 ++++++++++++++++++ .../DeleteEventBtn/DeleteEventBtn.jsx | 42 ------ .../DeleteEventBtn/DeleteEventBtn.tsx | 56 ++++++++ .../DeleteTaskBtn/DeleteTaskBtn.jsx | 28 ---- .../DeleteTaskBtn/DeleteTaskBtn.tsx | 48 +++++++ .../components/EventTask/EventTask.jsx | 98 ------------- .../components/EventTask/EventTask.tsx | 119 ++++++++++++++++ src/router.js | 2 +- 11 files changed, 418 insertions(+), 340 deletions(-) delete mode 100644 src/pages/EventDetail/EventDetailPage.jsx create mode 100644 src/pages/EventDetail/EventDetailPage.tsx delete mode 100644 src/pages/EventDetail/components/CreateTaskBtn/CreateTaskBtn.jsx create mode 100644 src/pages/EventDetail/components/CreateTaskBtn/CreateTaskBtn.tsx delete mode 100644 src/pages/EventDetail/components/DeleteEventBtn/DeleteEventBtn.jsx create mode 100644 src/pages/EventDetail/components/DeleteEventBtn/DeleteEventBtn.tsx delete mode 100644 src/pages/EventDetail/components/DeleteTaskBtn/DeleteTaskBtn.jsx create mode 100644 src/pages/EventDetail/components/DeleteTaskBtn/DeleteTaskBtn.tsx delete mode 100644 src/pages/EventDetail/components/EventTask/EventTask.jsx create mode 100644 src/pages/EventDetail/components/EventTask/EventTask.tsx diff --git a/src/pages/EventDetail/EventDetailPage.jsx b/src/pages/EventDetail/EventDetailPage.jsx deleted file mode 100644 index ee31c39..0000000 --- a/src/pages/EventDetail/EventDetailPage.jsx +++ /dev/null @@ -1,55 +0,0 @@ -import {useEffect, useContext} from "react"; -import styles from "./EventDetailPage.module.css"; -import {useParams} from "react-router"; -import {formatDateLetter} from "../../utils/date/formatDateLetter.js"; -import EventTask from "./components/EventTask/EventTask.jsx"; -import {AuthContext} from "../../contexts/Auth/AuthContext.js"; -import {EventDetailContext} from "../../contexts/EventDetail/EventDetailContext.js"; -import CreateTaskBtn from "./components/CreateTaskBtn/CreateTaskBtn.jsx"; -import DeleteEventBtn from "./components/DeleteEventBtn/DeleteEventBtn.jsx"; - - -function EventDetailPage() { - - const params = useParams(); - const id = params.id; - const {user} = useContext(AuthContext) - const {tasks, updateEventInfo, eventInfo} = useContext(EventDetailContext) - - useEffect(() => { - updateEventInfo(id); - }, []) - - - return ( -
-
-
- Illustration événement -
-

{eventInfo?.name}

-
-
-

{eventInfo && formatDateLetter(eventInfo.start)}

-

{eventInfo?.description}

-
- {user?.isAdmin &&
- - -
} -
-
-
- -

Tâches

-
- {tasks?.map((task, index) => ( - - ))} -
-
-
- ); -} - -export default EventDetailPage; \ No newline at end of file diff --git a/src/pages/EventDetail/EventDetailPage.tsx b/src/pages/EventDetail/EventDetailPage.tsx new file mode 100644 index 0000000..9c76e8e --- /dev/null +++ b/src/pages/EventDetail/EventDetailPage.tsx @@ -0,0 +1,65 @@ +import { useEffect, useContext } from "react"; +import styles from "./EventDetailPage.module.css"; +import { useParams } from "react-router"; +import { formatDateLetter } from "../../utils/date/formatDateLetter"; +import EventTask from "./components/EventTask/EventTask"; +import { AuthContext } from "../../contexts/Auth/AuthContext"; +import { EventDetailContext } from "../../contexts/EventDetail/EventDetailContext"; +import CreateTaskBtn from "./components/CreateTaskBtn/CreateTaskBtn"; +import DeleteEventBtn from "./components/DeleteEventBtn/DeleteEventBtn"; + +function EventDetailPage() { + const params = useParams(); + const id = params.id as string; + + const { user } = useContext(AuthContext) as any; + const { tasks, updateEventInfo, eventInfo } = useContext(EventDetailContext) as any; + + useEffect(() => { + if (id) { + updateEventInfo(id); + } + }, []); + + return ( +
+
+
+ Illustration événement + +
+

{eventInfo?.name}

+ +
+
+

{eventInfo && formatDateLetter(eventInfo.start)}

+

{eventInfo?.description}

+
+ + {user?.isAdmin && ( +
+ + +
+ )} +
+
+
+ +

Tâches

+ +
+ {tasks?.map((task: any, index: number) => ( + + ))} +
+
+
+ ); +} + +export default EventDetailPage; \ No newline at end of file diff --git a/src/pages/EventDetail/components/CreateTaskBtn/CreateTaskBtn.jsx b/src/pages/EventDetail/components/CreateTaskBtn/CreateTaskBtn.jsx deleted file mode 100644 index 4a0f47b..0000000 --- a/src/pages/EventDetail/components/CreateTaskBtn/CreateTaskBtn.jsx +++ /dev/null @@ -1,116 +0,0 @@ -import styles from "../../EventDetailPage.module.css"; -import Button from "../../../../components/ui/Button/Button"; -import {useContext, useState} from "react"; -import TextInput from "../../../../components/ui/Input/Input"; -import Modal from "../../../../components/ui/Modal/Modal"; -import createTaskApi from "../../../../utils/tasks/createTask.js"; -import {EventDetailContext} from "../../../../contexts/EventDetail/EventDetailContext.js"; - -export default function CreateTaskBtn({ id }) { - - const [openTaskModal, setOpenTaskModal] = useState(false); - - const [taskName, setTaskName] = useState(""); - const [taskDescription, setTaskDescription] = useState(""); - const [taskLocation, setTaskLocation] = useState(""); - const [maxParticipants, setMaxParticipants] = useState(""); - const [startTime, setStartTime] = useState(""); - const [endTime, setEndTime] = useState(""); - - const { updateEventInfo } = useContext(EventDetailContext) - - const createTask = async () => { - const data = await createTaskApi({ - eventId: id, - name: taskName, - description: taskDescription, - start: startTime, - end: endTime, - location: taskLocation, - maxParticipants, - }); - - if (data?.status === 200) { - setOpenTaskModal(false); - setTaskName(""); - setTaskDescription(""); - setTaskLocation(""); - setMaxParticipants(""); - setStartTime(""); - setEndTime(""); - - updateEventInfo(id) - } else { - console.log("⚠️ Échec de la création de la task"); - } - }; - - return <> - - - - setOpenTaskModal(false)} title={"Créer tâche"}> -
- -
-

Nom de la tâche

- setTaskName(e.target.value)} - placeholder="Nom de la tâche" - /> -
- -
-

Description

- setTaskDescription(e.target.value)} - placeholder="Description de la tâche" - /> -
- -
-

Lieu

- setTaskLocation(e.target.value)} - placeholder="Lieu" - /> -
- -
-

Nombre maximum de participants

- setMaxParticipants(e.target.value)} - placeholder="Participants max" - /> -
- -
-

Heure de début

- setStartTime(e.target.value)} - /> -
- -
-

Heure de fin

- setEndTime(e.target.value)} - /> -
- - - -
-
- - -} \ No newline at end of file diff --git a/src/pages/EventDetail/components/CreateTaskBtn/CreateTaskBtn.tsx b/src/pages/EventDetail/components/CreateTaskBtn/CreateTaskBtn.tsx new file mode 100644 index 0000000..9b228c3 --- /dev/null +++ b/src/pages/EventDetail/components/CreateTaskBtn/CreateTaskBtn.tsx @@ -0,0 +1,129 @@ +import styles from "../../EventDetailPage.module.css"; +import Button from "../../../../components/ui/Button/Button"; +import { useContext, useState } from "react"; +import TextInput from "../../../../components/ui/Input/Input"; +import Modal from "../../../../components/ui/Modal/Modal"; +import createTaskApi from "../../../../utils/tasks/createTask"; +import { EventDetailContext } from "../../../../contexts/EventDetail/EventDetailContext"; + +type CreateTaskBtnProps = { + id: string | number; +}; + +export default function CreateTaskBtn({ id }: CreateTaskBtnProps) { + const [openTaskModal, setOpenTaskModal] = useState(false); + + const [taskName, setTaskName] = useState(""); + const [taskDescription, setTaskDescription] = useState(""); + const [taskLocation, setTaskLocation] = useState(""); + const [maxParticipants, setMaxParticipants] = useState(""); + const [startTime, setStartTime] = useState(""); + const [endTime, setEndTime] = useState(""); + + const { updateEventInfo } = useContext(EventDetailContext) as any; + + const createTask = async () => { + const data = await createTaskApi({ + eventId: id, + name: taskName, + description: taskDescription, + start: startTime, + end: endTime, + location: taskLocation, + maxParticipants, + }); + + if (data?.status === 200) { + setOpenTaskModal(false); + setTaskName(""); + setTaskDescription(""); + setTaskLocation(""); + setMaxParticipants(""); + setStartTime(""); + setEndTime(""); + + updateEventInfo(id); + } else { + console.log("⚠️ Échec de la création de la task"); + } + }; + + return ( + <> + + + setOpenTaskModal(false)} + title={"Créer tâche"} + > +
+
+

Nom de la tâche

+ setTaskName(e.target.value)} + placeholder="Nom de la tâche" + /> +
+ +
+

Description

+ setTaskDescription(e.target.value)} + placeholder="Description de la tâche" + /> +
+ +
+

Lieu

+ setTaskLocation(e.target.value)} + placeholder="Lieu" + /> +
+ +
+

Nombre maximum de participants

+ setMaxParticipants(e.target.value)} + placeholder="Participants max" + /> +
+ +
+

Heure de début

+ setStartTime(e.target.value)} + /> +
+ +
+

Heure de fin

+ setEndTime(e.target.value)} + /> +
+ + +
+
+ + ); +} \ No newline at end of file diff --git a/src/pages/EventDetail/components/DeleteEventBtn/DeleteEventBtn.jsx b/src/pages/EventDetail/components/DeleteEventBtn/DeleteEventBtn.jsx deleted file mode 100644 index 5309450..0000000 --- a/src/pages/EventDetail/components/DeleteEventBtn/DeleteEventBtn.jsx +++ /dev/null @@ -1,42 +0,0 @@ -import styles from "../../EventDetailPage.module.css"; -import Button from "../../../../components/ui/Button/Button"; -import Modal from "../../../../components/ui/Modal/Modal"; -import { useContext, useState } from "react"; -import { EventDetailContext } from "../../../../contexts/EventDetail/EventDetailContext.js"; -import { EventContext } from "../../../../contexts/Events/EventContext.js"; -import { useNavigate } from "react-router"; - -export default function DeleteEventBtn({ id }) { - - const { eventInfo } = useContext(EventDetailContext) - const { removeEvent } = useContext(EventContext) - const [open, setOpen] = useState(false); - const navigate = useNavigate(); - - const handleDelete = () => { - setOpen(true); - } - - const delEvent = async () => { - const result = await removeEvent(id); - - if (result.status === 200 || result.status === 204) { - setOpen(false); - navigate("/events"); - } - } - - return <> - - - - setOpen(false)} title={"Suppression"}> -
-

Etes-vous sur de vouloir supprimer l'événement {eventInfo?.name} ?

- - -
-
- - -} \ No newline at end of file diff --git a/src/pages/EventDetail/components/DeleteEventBtn/DeleteEventBtn.tsx b/src/pages/EventDetail/components/DeleteEventBtn/DeleteEventBtn.tsx new file mode 100644 index 0000000..9a79467 --- /dev/null +++ b/src/pages/EventDetail/components/DeleteEventBtn/DeleteEventBtn.tsx @@ -0,0 +1,56 @@ +import styles from "../../EventDetailPage.module.css"; +import Button from "../../../../components/ui/Button/Button"; +import Modal from "../../../../components/ui/Modal/Modal"; +import { useContext, useState } from "react"; +import { EventDetailContext } from "../../../../contexts/EventDetail/EventDetailContext"; +import { EventContext } from "../../../../contexts/Events/EventContext"; +import { useNavigate } from "react-router"; + +type DeleteEventBtnProps = { + id: string | number; +}; + +export default function DeleteEventBtn({ id }: DeleteEventBtnProps) { + const { eventInfo } = useContext(EventDetailContext) as any; + const { removeEvent } = useContext(EventContext) as any; + + const [open, setOpen] = useState(false); + const navigate = useNavigate(); + + const handleDelete = () => { + setOpen(true); + }; + + const delEvent = async () => { + const result = await removeEvent(id); + + if (result.status === 200 || result.status === 204) { + setOpen(false); + navigate("/events"); + } + }; + + return ( + <> + + + setOpen(false)} title={"Suppression"}> +
+

+ Etes-vous sur de vouloir supprimer l'événement {eventInfo?.name} ? +

+ + +
+
+ + ); +} \ No newline at end of file diff --git a/src/pages/EventDetail/components/DeleteTaskBtn/DeleteTaskBtn.jsx b/src/pages/EventDetail/components/DeleteTaskBtn/DeleteTaskBtn.jsx deleted file mode 100644 index af6e3d0..0000000 --- a/src/pages/EventDetail/components/DeleteTaskBtn/DeleteTaskBtn.jsx +++ /dev/null @@ -1,28 +0,0 @@ -import { useContext } from "react"; -import { AuthContext } from "../../../../contexts/Auth/AuthContext.js"; -import { EventDetailContext } from "../../../../contexts/EventDetail/EventDetailContext.js"; -import Button from "../../../../components/ui/Button/Button"; -import { useState } from "react"; -import Modal from "../../../../components/ui/Modal/Modal"; -import styles from "../../EventDetailPage.module.css"; - -export default function DeleteTaskBtn({ taskId, eventId, taskName }) { - - const { user } = useContext(AuthContext) - const { deleteTask } = useContext(EventDetailContext) - - const [openModal, setOpenModal] = useState(false); - - if(!user?.isAdmin) return null; - - return <> - - - -
-

Etes-vous sur de vouloir supprimer la tâche {taskName} ?

- -
-
- -} \ No newline at end of file diff --git a/src/pages/EventDetail/components/DeleteTaskBtn/DeleteTaskBtn.tsx b/src/pages/EventDetail/components/DeleteTaskBtn/DeleteTaskBtn.tsx new file mode 100644 index 0000000..6c16221 --- /dev/null +++ b/src/pages/EventDetail/components/DeleteTaskBtn/DeleteTaskBtn.tsx @@ -0,0 +1,48 @@ +import { useContext, useState } from "react"; +import { AuthContext } from "../../../../contexts/Auth/AuthContext"; +import { EventDetailContext } from "../../../../contexts/EventDetail/EventDetailContext"; +import Button from "../../../../components/ui/Button/Button"; +import Modal from "../../../../components/ui/Modal/Modal"; +import styles from "../../EventDetailPage.module.css"; + +type DeleteTaskBtnProps = { + taskId: string | number; + eventId: string | number; + taskName: string; +}; + +export default function DeleteTaskBtn({ taskId, eventId, taskName }: DeleteTaskBtnProps) { + + const { user } = useContext(AuthContext) as any; + const { deleteTask } = useContext(EventDetailContext) as any; + + const [openModal, setOpenModal] = useState(false); + + if (!user?.isAdmin) return null; + + return ( + <> + + + setOpenModal(false)} title={"Suppression"}> +
+

+ Etes-vous sur de vouloir supprimer la tâche {taskName} ? +

+ + +
+
+ + ); +} \ No newline at end of file diff --git a/src/pages/EventDetail/components/EventTask/EventTask.jsx b/src/pages/EventDetail/components/EventTask/EventTask.jsx deleted file mode 100644 index 41e6429..0000000 --- a/src/pages/EventDetail/components/EventTask/EventTask.jsx +++ /dev/null @@ -1,98 +0,0 @@ -import styles from "./EventTask.module.css"; -import { formatDateLetter } from "../../../../utils/date/formatDateLetter.js"; -import Button from "../../../../components/ui/Button/Button"; -import assign from "../../../../utils/tasks/assign.js"; -import unAssign from "../../../../utils/tasks/unAssign.js"; -import { useContext, useEffect, useState } from "react"; -import isAssigned from "../../../../utils/tasks/isAssigned.js"; -import Modal from "../../../../components/ui/Modal/Modal"; -import { AuthContext } from "../../../../contexts/Auth/AuthContext.js"; -import DeleteTaskBtn from "../DeleteTaskBtn/DeleteTaskBtn.jsx"; - -export default function EventTask({ task, index, eventId }) { - - const { update } = useContext(AuthContext) - - const [assigned, setAssigned] = useState(false); - const [open, setOpen] = useState(false); - const [title, setTitle] = useState(""); - const [message, setMessage] = useState(""); - - async function checkAssign() { - const data = await isAssigned(task.id); - setAssigned(data?.data.assigned); - } - - useEffect(() => { - checkAssign(); - }, []) - - - const handleRegisterBtn = async () => { - const res = await assign(task.id); - - switch (res.status) { - case 200: - update() - setTitle("Inscription réussie") - setMessage(`Vous êtes maintenant inscrit à la tâche ${task.name}`); - setOpen(true); - setAssigned(true); - break; - - case 409: - setTitle("Erreur lors de l'inscription") - setMessage("Vous êtes déjà inscrit à cette tâche") - setOpen(true); - break; - - case 403: - setTitle("Erreur lors de l'inscription") - setMessage("Le nombre maximum d'inscription pour cette tâche à été atteint") - setOpen(true); - break; - } - }; - - const handleUnassign = async () => { - const res = await unAssign(task.id); - - switch (res.status) { - case 200: - update() - setTitle("Désinscription réussie") - setMessage(`Vous n'êtes plus inscrit à la tâche ${task.name}`); - setOpen(true); - setAssigned(false); - break; - - case 409: - setTitle("Erreur lors de la désinscription") - setMessage(`Vous n'êtes pas inscrit à cette tâche`); - setOpen(true); - break; - } - }; - - return
-
-
- {task.name} -

{formatDateLetter(task.start)} - {formatDateLetter(task.end)}

-

{task.description}

-
-
- {assigned ? - - : - - } - -
-
- - -

{message}

-
-
-} \ No newline at end of file diff --git a/src/pages/EventDetail/components/EventTask/EventTask.tsx b/src/pages/EventDetail/components/EventTask/EventTask.tsx new file mode 100644 index 0000000..bebc62d --- /dev/null +++ b/src/pages/EventDetail/components/EventTask/EventTask.tsx @@ -0,0 +1,119 @@ +import styles from "./EventTask.module.css"; +import { formatDateLetter } from "../../../../utils/date/formatDateLetter"; +import Button from "../../../../components/ui/Button/Button"; +import assign from "../../../../utils/tasks/assign"; +import unAssign from "../../../../utils/tasks/unAssign"; +import { useContext, useEffect, useState } from "react"; +import isAssigned from "../../../../utils/tasks/isAssigned"; +import Modal from "../../../../components/ui/Modal/Modal"; +import { AuthContext } from "../../../../contexts/Auth/AuthContext"; +import DeleteTaskBtn from "../DeleteTaskBtn/DeleteTaskBtn"; + +type EventTaskProps = { + task: any; + index: number; + eventId: string | number; +}; + +export default function EventTask({ task, index, eventId }: EventTaskProps) { + + const { update } = useContext(AuthContext) as any; + + const [assigned, setAssigned] = useState(false); + const [open, setOpen] = useState(false); + const [title, setTitle] = useState(""); + const [message, setMessage] = useState(""); + + async function checkAssign() { + const data = await isAssigned(task.id); + setAssigned(data?.data.assigned); + } + + useEffect(() => { + checkAssign(); + }, []); + + const handleRegisterBtn = async () => { + const res = await assign(task.id); + + switch (res.status) { + case 200: + update(); + setTitle("Inscription réussie"); + setMessage(`Vous êtes maintenant inscrit à la tâche ${task.name}`); + setOpen(true); + setAssigned(true); + break; + + case 409: + setTitle("Erreur lors de l'inscription"); + setMessage("Vous êtes déjà inscrit à cette tâche"); + setOpen(true); + break; + + case 403: + setTitle("Erreur lors de l'inscription"); + setMessage("Le nombre maximum d'inscription pour cette tâche à été atteint"); + setOpen(true); + break; + } + }; + + const handleUnassign = async () => { + const res = await unAssign(task.id); + + switch (res.status) { + case 200: + update(); + setTitle("Désinscription réussie"); + setMessage(`Vous n'êtes plus inscrit à la tâche ${task.name}`); + setOpen(true); + setAssigned(false); + break; + + case 409: + setTitle("Erreur lors de la désinscription"); + setMessage(`Vous n'êtes pas inscrit à cette tâche`); + setOpen(true); + break; + } + }; + + return ( +
+
+
+ + {task.name} + +

+ {formatDateLetter(task.start)} - {formatDateLetter(task.end)} +

+

{task.description}

+
+ +
+ {assigned ? ( + + ) : ( + + )} + + +
+
+ + setOpen(false)} title={title}> +

{message}

+
+
+ ); +} \ No newline at end of file diff --git a/src/router.js b/src/router.js index 75d0bd6..11c3bb8 100644 --- a/src/router.js +++ b/src/router.js @@ -9,7 +9,7 @@ import EventsPage from "./pages/Events/EventsPage.jsx"; import AdminPage from "./pages/Admin/AdminPage.jsx"; import WaitValidationPage from "./pages/WaitValidation/WaitValidationPage.jsx"; import PageNotFoundPage from "./pages/PageNotFound/PageNotFoundPage.jsx"; -import eventDetail from "./pages/EventDetail/EventDetailPage.jsx"; +import eventDetail from "./pages/EventDetail/EventDetailPage.tsx"; import legalNotices from "./pages/LegalNotices/LegalNoticesPage.jsx"; import RGPDPage from "./pages/RGPD/RGPDPage.jsx"; From 0f11ec641a26dcfb7138868602ec93c3ef3712e7 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 15:13:16 +0100 Subject: [PATCH 04/29] convert to TS --- src/contexts/Auth/AuthContext.ts | 1 + src/pages/Login/LoginPage.tsx | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 src/pages/Login/LoginPage.tsx diff --git a/src/contexts/Auth/AuthContext.ts b/src/contexts/Auth/AuthContext.ts index ed005d1..3e3142c 100644 --- a/src/contexts/Auth/AuthContext.ts +++ b/src/contexts/Auth/AuthContext.ts @@ -21,6 +21,7 @@ export interface User { export interface AuthContextType { user: User | null; + loading: boolean; update: () => void; login: (email: string, password: string) => Promise<{ status: number }>; } diff --git a/src/pages/Login/LoginPage.tsx b/src/pages/Login/LoginPage.tsx new file mode 100644 index 0000000..9868eaa --- /dev/null +++ b/src/pages/Login/LoginPage.tsx @@ -0,0 +1,28 @@ +import styles from "./LoginPage.module.css"; +import LoginForm from "./components/LoginForm/LoginForm"; +import Background from "../../components/Background/Background.jsx"; +import { useEffect, useContext } from "react"; +import { AuthContext, AuthContextType } from "../../../src/contexts/Auth/AuthContext"; +import { useNavigate } from "react-router"; + +function LoginPage() { + const { user, loading } = useContext(AuthContext) as AuthContextType; + const navigate = useNavigate(); + + useEffect(() => { + if (!loading && user) { + navigate("/"); + } + }, [loading, user, navigate]); + + return ( + +
+

Connexion

+ +
+
+ ); +} + +export default LoginPage; \ No newline at end of file From 8d21eb7a7797788b18030691116c4e7bb32ded45 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 15:16:50 +0100 Subject: [PATCH 05/29] convert login.js to TS --- src/utils/auth/login.js | 13 ------------- src/utils/auth/login.ts | 14 ++++++++++++++ src/utils/fetchWrapper.ts | 40 --------------------------------------- 3 files changed, 14 insertions(+), 53 deletions(-) delete mode 100644 src/utils/auth/login.js create mode 100644 src/utils/auth/login.ts diff --git a/src/utils/auth/login.js b/src/utils/auth/login.js deleted file mode 100644 index 1d99d02..0000000 --- a/src/utils/auth/login.js +++ /dev/null @@ -1,13 +0,0 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; - -export default async function login(email, password) { - const csrfToken = await getXSRFToken(); - - return fetchWrapper( - "/api/users/login", - { email, password }, - "POST", - { "X-XSRF-TOKEN": csrfToken } - ); -} diff --git a/src/utils/auth/login.ts b/src/utils/auth/login.ts new file mode 100644 index 0000000..3c7c6e2 --- /dev/null +++ b/src/utils/auth/login.ts @@ -0,0 +1,14 @@ +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; + + + +export default async function login(email: string, password: string) { + const csrfToken: string = await getXSRFToken(); + return fetchWrapper( + "/api/users/login", + { email, password }, + "POST", + { "X-XSRF-TOKEN": csrfToken } + ); +} \ No newline at end of file diff --git a/src/utils/fetchWrapper.ts b/src/utils/fetchWrapper.ts index a130373..287e683 100644 --- a/src/utils/fetchWrapper.ts +++ b/src/utils/fetchWrapper.ts @@ -1,43 +1,3 @@ -/*export default async function fetchWrapper(path,data = null,method = "GET",headers = {}) { - try { - const res = await fetch( - `${import.meta.env.VITE_API_URL}${path}`, - { - method, - credentials: "include", - headers: { - "Accept": "application/json", - "Content-Type": "application/json", - ...headers, - }, - body: data ? JSON.stringify(data) : null, - } - ); - - let responseData = null; - - try { - responseData = await res.json(); - } catch (_) { - responseData = null; - } - - return { - status: res.status, - data: responseData, - }; - - } catch (err) { - console.error("❌ Erreur réseau :", err); - - return { - status: 0, - data: { - message: "Network error", - }, - }; - } -}*/ interface FetchResponse { status: number; From 4bb0ed60ad96480bf9be822d5fd08c5b7189d09f Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 15:27:42 +0100 Subject: [PATCH 06/29] refactor: remove .js extensions from imports --- src/pages/Admin/AdminPage.jsx | 6 +-- src/utils/auth/{logout.js => logout.ts} | 0 src/utils/fetchWrapper.ts | 43 +------------------- src/utils/{getRoles.js => getRoles.ts} | 0 src/utils/{getUser.js => getUser.ts} | 0 src/utils/{register.js => register.ts} | 6 +-- src/utils/{scrollToTop.js => scrollToTop.ts} | 0 src/utils/users/adminCreateUser.ts | 4 +- src/utils/users/deactivateUser.js | 4 +- src/utils/users/deleteOtherUser.js | 4 +- src/utils/users/deleteProfilePhoto.ts | 2 +- src/utils/users/getAllUsers.js | 2 +- src/utils/users/getUserById.js | 2 +- src/utils/users/getUserToValidate.js | 2 +- src/utils/users/modifyRole.js | 4 +- src/utils/users/uploadProfilePhoto.ts | 2 +- src/utils/users/validateUser.js | 4 +- 17 files changed, 22 insertions(+), 63 deletions(-) rename src/utils/auth/{logout.js => logout.ts} (100%) rename src/utils/{getRoles.js => getRoles.ts} (100%) rename src/utils/{getUser.js => getUser.ts} (100%) rename src/utils/{register.js => register.ts} (52%) rename src/utils/{scrollToTop.js => scrollToTop.ts} (100%) diff --git a/src/pages/Admin/AdminPage.jsx b/src/pages/Admin/AdminPage.jsx index 7d36503..5765849 100644 --- a/src/pages/Admin/AdminPage.jsx +++ b/src/pages/Admin/AdminPage.jsx @@ -1,8 +1,8 @@ import { useContext } from "react"; import styles from "./AdminPage.module.css"; -import IncompleteEvents from "./components/IncompleteEvent/IncompleteEvent.jsx"; -import PendingMembers from "./components/PendingMembers/PendingMembers.jsx"; -import { AuthContext } from "../../contexts/Auth/AuthContext.js"; +import IncompleteEvents from "./components/IncompleteEvent/IncompleteEvent"; +import PendingMembers from "./components/PendingMembers/PendingMembers"; +import { AuthContext } from "../../contexts/Auth/AuthContext"; import { useNavigate } from "react-router"; import RegisterMember from "./components/RegisterMember/RegisterMember"; diff --git a/src/utils/auth/logout.js b/src/utils/auth/logout.ts similarity index 100% rename from src/utils/auth/logout.js rename to src/utils/auth/logout.ts diff --git a/src/utils/fetchWrapper.ts b/src/utils/fetchWrapper.ts index a130373..4f04e5e 100644 --- a/src/utils/fetchWrapper.ts +++ b/src/utils/fetchWrapper.ts @@ -1,44 +1,3 @@ -/*export default async function fetchWrapper(path,data = null,method = "GET",headers = {}) { - try { - const res = await fetch( - `${import.meta.env.VITE_API_URL}${path}`, - { - method, - credentials: "include", - headers: { - "Accept": "application/json", - "Content-Type": "application/json", - ...headers, - }, - body: data ? JSON.stringify(data) : null, - } - ); - - let responseData = null; - - try { - responseData = await res.json(); - } catch (_) { - responseData = null; - } - - return { - status: res.status, - data: responseData, - }; - - } catch (err) { - console.error("❌ Erreur réseau :", err); - - return { - status: 0, - data: { - message: "Network error", - }, - }; - } -}*/ - interface FetchResponse { status: number; data: T | null; @@ -79,7 +38,7 @@ export default async function fetchWrapper( }; } catch (err) { - console.error("❌ Erreur réseau :", err); + console.error("Erreur réseau :", err); return { status: 0, diff --git a/src/utils/getRoles.js b/src/utils/getRoles.ts similarity index 100% rename from src/utils/getRoles.js rename to src/utils/getRoles.ts diff --git a/src/utils/getUser.js b/src/utils/getUser.ts similarity index 100% rename from src/utils/getUser.js rename to src/utils/getUser.ts diff --git a/src/utils/register.js b/src/utils/register.ts similarity index 52% rename from src/utils/register.js rename to src/utils/register.ts index 489f07c..69a983c 100644 --- a/src/utils/register.js +++ b/src/utils/register.ts @@ -1,7 +1,7 @@ -import fetchWrapper from "./fetchWrapper.js"; -import getXSRFToken from "./getXSRF.js"; +import fetchWrapper from "./fetchWrapper"; +import getXSRFToken from "./getXSRF"; -export default async function register(email, password, name, lastname, phone) { +export default async function register(email:string, password:string, name:string, lastname:string, phone:string) { const csrfToken = await getXSRFToken(); return fetchWrapper( diff --git a/src/utils/scrollToTop.js b/src/utils/scrollToTop.ts similarity index 100% rename from src/utils/scrollToTop.js rename to src/utils/scrollToTop.ts diff --git a/src/utils/users/adminCreateUser.ts b/src/utils/users/adminCreateUser.ts index 01860d3..5577840 100644 --- a/src/utils/users/adminCreateUser.ts +++ b/src/utils/users/adminCreateUser.ts @@ -1,5 +1,5 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; import Response from "../../interfaces/response.interface"; export default async function adminCreateUser(email: string, name: string, lastname: string, phone: string): Promise { diff --git a/src/utils/users/deactivateUser.js b/src/utils/users/deactivateUser.js index fdf4c44..aa38680 100644 --- a/src/utils/users/deactivateUser.js +++ b/src/utils/users/deactivateUser.js @@ -1,5 +1,5 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; export default async function deactivateUser(userId) { const csrfToken = await getXSRFToken(); diff --git a/src/utils/users/deleteOtherUser.js b/src/utils/users/deleteOtherUser.js index ece6425..649945f 100644 --- a/src/utils/users/deleteOtherUser.js +++ b/src/utils/users/deleteOtherUser.js @@ -1,5 +1,5 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; export default async function deleteOtherUser(userId) { const csrfToken = await getXSRFToken(); diff --git a/src/utils/users/deleteProfilePhoto.ts b/src/utils/users/deleteProfilePhoto.ts index a5e830f..ca55ef4 100644 --- a/src/utils/users/deleteProfilePhoto.ts +++ b/src/utils/users/deleteProfilePhoto.ts @@ -1,4 +1,4 @@ -import getXSRFToken from "../getXSRF.js"; +import getXSRFToken from "../getXSRF"; export default async function deleteProfilePhoto(): Promise<{ status: number; ok: boolean; data?: any; error?: string }> { try { diff --git a/src/utils/users/getAllUsers.js b/src/utils/users/getAllUsers.js index 584c39f..1b75dc9 100644 --- a/src/utils/users/getAllUsers.js +++ b/src/utils/users/getAllUsers.js @@ -1,4 +1,4 @@ -import fetchWrapper from "../fetchWrapper.js"; +import fetchWrapper from "../fetchWrapper"; export default async function getAllUser() { return fetchWrapper("/api/users"); diff --git a/src/utils/users/getUserById.js b/src/utils/users/getUserById.js index e9a2c75..9acd7bd 100644 --- a/src/utils/users/getUserById.js +++ b/src/utils/users/getUserById.js @@ -1,4 +1,4 @@ -import fetchWrapper from "../fetchWrapper.js"; +import fetchWrapper from "../fetchWrapper"; export default async function getUserById(id) { return fetchWrapper(`/api/users/${id}`); diff --git a/src/utils/users/getUserToValidate.js b/src/utils/users/getUserToValidate.js index 5176f1f..b0fde0e 100644 --- a/src/utils/users/getUserToValidate.js +++ b/src/utils/users/getUserToValidate.js @@ -1,4 +1,4 @@ -import fetchWrapper from "../fetchWrapper.js"; +import fetchWrapper from "../fetchWrapper"; export default async function getUserToValidate() { return fetchWrapper("/api/users/invalid"); diff --git a/src/utils/users/modifyRole.js b/src/utils/users/modifyRole.js index 6526cea..aab4899 100644 --- a/src/utils/users/modifyRole.js +++ b/src/utils/users/modifyRole.js @@ -1,5 +1,5 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; export default async function modifyRole(role, userId) { const csrfToken = await getXSRFToken(); diff --git a/src/utils/users/uploadProfilePhoto.ts b/src/utils/users/uploadProfilePhoto.ts index ca252a2..f3341ee 100644 --- a/src/utils/users/uploadProfilePhoto.ts +++ b/src/utils/users/uploadProfilePhoto.ts @@ -1,4 +1,4 @@ -import getXSRFToken from "../getXSRF.js"; +import getXSRFToken from "../getXSRF"; export default async function uploadProfilePhoto(file: File): Promise<{ status: number; ok: boolean; data?: any; error?: string }> { const formData = new FormData(); diff --git a/src/utils/users/validateUser.js b/src/utils/users/validateUser.js index f73b3ef..b8567bb 100644 --- a/src/utils/users/validateUser.js +++ b/src/utils/users/validateUser.js @@ -1,5 +1,5 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; export default async function validateUser(userId) { const csrfToken = await getXSRFToken(); From e488d8c11e8175431e011caf5f436921d86b1b87 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 15:30:52 +0100 Subject: [PATCH 07/29] remove commented JS code --- src/utils/events/createEvent.js | 4 ++-- src/utils/events/deleteEvent.js | 4 ++-- src/utils/events/getAllEvents.js | 2 +- src/utils/events/getEventById.js | 2 +- src/utils/getRoles.ts | 2 +- src/utils/getUser.ts | 2 +- src/utils/getXSRF.ts | 20 ------------------- .../notifications/deleteNotificationUser.js | 2 +- src/utils/notifications/readNotifications.js | 2 +- 9 files changed, 10 insertions(+), 30 deletions(-) diff --git a/src/utils/events/createEvent.js b/src/utils/events/createEvent.js index 764d419..27da6b1 100644 --- a/src/utils/events/createEvent.js +++ b/src/utils/events/createEvent.js @@ -1,5 +1,5 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; export default async function createEvent(name, description, start, end) { const csrfToken = await getXSRFToken(); diff --git a/src/utils/events/deleteEvent.js b/src/utils/events/deleteEvent.js index 10c8a49..2781e91 100644 --- a/src/utils/events/deleteEvent.js +++ b/src/utils/events/deleteEvent.js @@ -1,5 +1,5 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; export default async function deleteEvent(eventId) { const csrfToken = await getXSRFToken(); diff --git a/src/utils/events/getAllEvents.js b/src/utils/events/getAllEvents.js index b35f979..79bfc67 100644 --- a/src/utils/events/getAllEvents.js +++ b/src/utils/events/getAllEvents.js @@ -1,4 +1,4 @@ -import fetchWrapper from "../fetchWrapper.js"; +import fetchWrapper from "../fetchWrapper"; export default async function getAllEvents() { return fetchWrapper("/api/events/", null, "GET"); diff --git a/src/utils/events/getEventById.js b/src/utils/events/getEventById.js index 97d6272..0b41625 100644 --- a/src/utils/events/getEventById.js +++ b/src/utils/events/getEventById.js @@ -1,4 +1,4 @@ -import fetchWrapper from "../fetchWrapper.js"; +import fetchWrapper from "../fetchWrapper"; export default async function GetEventById(id) { return fetchWrapper(`/api/events/${id}`, null, "GET"); diff --git a/src/utils/getRoles.ts b/src/utils/getRoles.ts index 99cadb6..fd8d0d4 100644 --- a/src/utils/getRoles.ts +++ b/src/utils/getRoles.ts @@ -1,4 +1,4 @@ -import fetchWrapper from "./fetchWrapper.js"; +import fetchWrapper from "./fetchWrapper"; export default async function getRoles() { return fetchWrapper("/api/roles", null, "GET"); diff --git a/src/utils/getUser.ts b/src/utils/getUser.ts index 7a485b8..811c2b5 100644 --- a/src/utils/getUser.ts +++ b/src/utils/getUser.ts @@ -1,4 +1,4 @@ -import fetchWrapper from "./fetchWrapper.js"; +import fetchWrapper from "./fetchWrapper"; export default async function getUser() { return fetchWrapper("/api/users/me", null, "GET"); diff --git a/src/utils/getXSRF.ts b/src/utils/getXSRF.ts index f96606d..c7b8048 100644 --- a/src/utils/getXSRF.ts +++ b/src/utils/getXSRF.ts @@ -1,23 +1,3 @@ -/*export default async function getXSRFToken() { - const response = await fetch(`${import.meta.env.VITE_API_URL}/sanctum/csrf-cookie`, { - method: 'GET', - credentials: 'include' - }); - - if (!response.ok && response.status !== 204) { - throw new Error(`Error : ${response.status}`); - } - - const name = 'XSRF-TOKEN'; - const value = `; ${document.cookie}`; - const parts = value.split(`; ${name}=`); - if (parts.length === 2) { - return decodeURIComponent(parts.pop().split(';').shift()); - } - - throw new Error('Error: Invalid XSRF-TOKEN'); -}*/ - export default async function getXSRFToken(): Promise { const response = await fetch(`${import.meta.env.VITE_API_URL}/sanctum/csrf-cookie`, { method: 'GET', diff --git a/src/utils/notifications/deleteNotificationUser.js b/src/utils/notifications/deleteNotificationUser.js index b7d7a93..d01c8a3 100644 --- a/src/utils/notifications/deleteNotificationUser.js +++ b/src/utils/notifications/deleteNotificationUser.js @@ -1,4 +1,4 @@ -import getXSRFToken from "../getXSRF.js"; +import getXSRFToken from "../getXSRF"; export default async function deleteNotificationUser(notificationId) { const csrfToken = await getXSRFToken(); diff --git a/src/utils/notifications/readNotifications.js b/src/utils/notifications/readNotifications.js index 0f406ce..5b7f998 100644 --- a/src/utils/notifications/readNotifications.js +++ b/src/utils/notifications/readNotifications.js @@ -1,4 +1,4 @@ -import getXSRFToken from "../getXSRF.js"; +import getXSRFToken from "../getXSRF"; export default async function readNotifications() { From e73d607ac3f1ba8f78f1dc3e04bc2d56791f40a7 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 16:42:25 +0100 Subject: [PATCH 08/29] fix adminCreateUser.ts --- src/utils/users/adminCreateUser.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/users/adminCreateUser.ts b/src/utils/users/adminCreateUser.ts index 01860d3..29b5786 100644 --- a/src/utils/users/adminCreateUser.ts +++ b/src/utils/users/adminCreateUser.ts @@ -2,7 +2,7 @@ import fetchWrapper from "../fetchWrapper.js"; import getXSRFToken from "../getXSRF.js"; import Response from "../../interfaces/response.interface"; -export default async function adminCreateUser(email: string, name: string, lastname: string, phone: string): Promise { +export default async function adminCreateUser(email: string, name: string, lastname: string, phone: string) { const csrfToken = await getXSRFToken(); return fetchWrapper( From 94ceff82885d9cab6e1819e6a0599f2dd745746e Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Fri, 13 Mar 2026 16:54:00 +0100 Subject: [PATCH 09/29] Create AssignUserBtn component --- .../AssignUserBtn/AssignUserBtn.module.css | 23 ++++++ .../AssignUserBtn/AssignUserBtn.tsx | 71 +++++++++++++++++++ .../components/EventTask/EventTask.tsx | 3 + 3 files changed, 97 insertions(+) create mode 100644 src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.module.css create mode 100644 src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx diff --git a/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.module.css b/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.module.css new file mode 100644 index 0000000..c5798dc --- /dev/null +++ b/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.module.css @@ -0,0 +1,23 @@ +.usersList { + display: flex; + flex-direction: column; + gap: 10px; + margin-top: 10px; +} + +.userCard { + display: flex; + align-items: center; + justify-content: space-between; + padding: 10px 14px; + border-radius: 10px; + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.08); +} + +.userName { + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} \ No newline at end of file diff --git a/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx b/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx new file mode 100644 index 0000000..ee69cc6 --- /dev/null +++ b/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx @@ -0,0 +1,71 @@ +import { ReactNode, useEffect, useState } from "react"; +import Button from "../../../../components/ui/Button/Button"; +import Modal from "../../../../components/ui/Modal/Modal"; +import User from "../../../Volunteers/interfaces/user.interface"; +import getAllUser from "../../../../utils/users/getAllUsers"; +import Loading from "../../../../components/ui/Loading/Loading"; +import getUserById from "../../../../utils/users/getUserById"; +import styles from "./AssignUserBtn.module.css"; + +interface AssignUserBtnProps { + taskId: string | number; +} + +export default function AssignUserBtn({ taskId }: AssignUserBtnProps): ReactNode { + + const [open, setOpen] = useState(false); + const [users, setUsers] = useState>([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + (async () => { + setLoading(true); + + const result = await getAllUser(); + + if (result.status !== 200 || !Array.isArray(result.data)) { + console.error("Erreur lors du chargement des utilisateurs", result); + return; + } + + const usersData = await Promise.all( + result.data.map(async (id: number): Promise => { + const res = await getUserById(id); + + if (res.status === 200) { + return res.data as User; + } + + return null; + }) + ); + + setUsers(usersData.filter((user): user is User => user !== null)); + setLoading(false); + })(); + }, []); + + const handleAssign = async (user: User) => { + + }; + + return <> + + + setOpen(false)} title={"Assigner un utilisateur à cette tâche"}> +
+ {loading ? : users.map((user: User, index) => ( +
+

+ {user.name} {user.lastname} +

+ + +
+ ))} +
+
+ +} \ No newline at end of file diff --git a/src/pages/EventDetail/components/EventTask/EventTask.tsx b/src/pages/EventDetail/components/EventTask/EventTask.tsx index bebc62d..4a1188b 100644 --- a/src/pages/EventDetail/components/EventTask/EventTask.tsx +++ b/src/pages/EventDetail/components/EventTask/EventTask.tsx @@ -8,6 +8,7 @@ import isAssigned from "../../../../utils/tasks/isAssigned"; import Modal from "../../../../components/ui/Modal/Modal"; import { AuthContext } from "../../../../contexts/Auth/AuthContext"; import DeleteTaskBtn from "../DeleteTaskBtn/DeleteTaskBtn"; +import AssignUserBtn from "../AssignUserBtn/AssignUserBtn"; type EventTaskProps = { task: any; @@ -108,6 +109,8 @@ export default function EventTask({ task, index, eventId }: EventTaskProps) { taskId={task.id} taskName={task.name} /> + +
From 4325fe3dcb76e50b5f3f40fb323183db23108331 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 16:54:08 +0100 Subject: [PATCH 10/29] convert API call function to TS --- .../events/{createEvent.js => createEvent.ts} | 6 +-- .../events/{deleteEvent.js => deleteEvent.ts} | 6 +-- .../{getAllEvents.js => getAllEvents.ts} | 2 +- src/utils/events/getEventById.js | 5 --- src/utils/events/getEventById.ts | 5 +++ src/utils/{getRoles.js => getRoles.ts} | 0 src/utils/{getUser.js => getUser.ts} | 0 ...ationUser.js => deleteNotificationUser.ts} | 2 +- ...tifications.js => getUserNotifications.ts} | 0 ...dNotifications.js => readNotifications.ts} | 2 +- src/utils/{register.js => register.ts} | 2 +- src/utils/{scrollToTop.js => scrollToTop.ts} | 0 .../{deactivateUser.js => deactivateUser.ts} | 2 +- ...{deleteOtherUser.js => deleteOtherUser.ts} | 2 +- .../users/{getAllUsers.js => getAllUsers.ts} | 2 +- src/utils/users/getUserById.js | 5 --- src/utils/users/getUserById.ts | 5 +++ ...UserToValidate.js => getUserToValidate.ts} | 2 +- .../users/{modifyRole.js => modifyRole.ts} | 6 +-- src/utils/users/updateUser.ts | 37 ++++--------------- .../{validateUser.js => validateUser.ts} | 6 +-- 21 files changed, 38 insertions(+), 59 deletions(-) rename src/utils/events/{createEvent.js => createEvent.ts} (52%) rename src/utils/events/{deleteEvent.js => deleteEvent.ts} (57%) rename src/utils/events/{getAllEvents.js => getAllEvents.ts} (68%) delete mode 100644 src/utils/events/getEventById.js create mode 100644 src/utils/events/getEventById.ts rename src/utils/{getRoles.js => getRoles.ts} (100%) rename src/utils/{getUser.js => getUser.ts} (100%) rename src/utils/notifications/{deleteNotificationUser.js => deleteNotificationUser.ts} (98%) rename src/utils/notifications/{getUserNotifications.js => getUserNotifications.ts} (100%) rename src/utils/notifications/{readNotifications.js => readNotifications.ts} (94%) rename src/utils/{register.js => register.ts} (72%) rename src/utils/{scrollToTop.js => scrollToTop.ts} (100%) rename src/utils/users/{deactivateUser.js => deactivateUser.ts} (82%) rename src/utils/users/{deleteOtherUser.js => deleteOtherUser.ts} (81%) rename src/utils/users/{getAllUsers.js => getAllUsers.ts} (64%) delete mode 100644 src/utils/users/getUserById.js create mode 100644 src/utils/users/getUserById.ts rename src/utils/users/{getUserToValidate.js => getUserToValidate.ts} (68%) rename src/utils/users/{modifyRole.js => modifyRole.ts} (55%) rename src/utils/users/{validateUser.js => validateUser.ts} (56%) diff --git a/src/utils/events/createEvent.js b/src/utils/events/createEvent.ts similarity index 52% rename from src/utils/events/createEvent.js rename to src/utils/events/createEvent.ts index 764d419..eac4b13 100644 --- a/src/utils/events/createEvent.js +++ b/src/utils/events/createEvent.ts @@ -1,7 +1,7 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; -export default async function createEvent(name, description, start, end) { +export default async function createEvent(name:string, description:string, start:string, end:string) { const csrfToken = await getXSRFToken(); return fetchWrapper( diff --git a/src/utils/events/deleteEvent.js b/src/utils/events/deleteEvent.ts similarity index 57% rename from src/utils/events/deleteEvent.js rename to src/utils/events/deleteEvent.ts index 10c8a49..7a748a1 100644 --- a/src/utils/events/deleteEvent.js +++ b/src/utils/events/deleteEvent.ts @@ -1,7 +1,7 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; -export default async function deleteEvent(eventId) { +export default async function deleteEvent(eventId:number) { const csrfToken = await getXSRFToken(); return fetchWrapper( diff --git a/src/utils/events/getAllEvents.js b/src/utils/events/getAllEvents.ts similarity index 68% rename from src/utils/events/getAllEvents.js rename to src/utils/events/getAllEvents.ts index b35f979..79bfc67 100644 --- a/src/utils/events/getAllEvents.js +++ b/src/utils/events/getAllEvents.ts @@ -1,4 +1,4 @@ -import fetchWrapper from "../fetchWrapper.js"; +import fetchWrapper from "../fetchWrapper"; export default async function getAllEvents() { return fetchWrapper("/api/events/", null, "GET"); diff --git a/src/utils/events/getEventById.js b/src/utils/events/getEventById.js deleted file mode 100644 index 97d6272..0000000 --- a/src/utils/events/getEventById.js +++ /dev/null @@ -1,5 +0,0 @@ -import fetchWrapper from "../fetchWrapper.js"; - -export default async function GetEventById(id) { - return fetchWrapper(`/api/events/${id}`, null, "GET"); -} diff --git a/src/utils/events/getEventById.ts b/src/utils/events/getEventById.ts new file mode 100644 index 0000000..70cb6db --- /dev/null +++ b/src/utils/events/getEventById.ts @@ -0,0 +1,5 @@ +import fetchWrapper from "../fetchWrapper"; + +export default async function GetEventById(id:number) { + return fetchWrapper(`/api/events/${id}`, null, "GET"); +} diff --git a/src/utils/getRoles.js b/src/utils/getRoles.ts similarity index 100% rename from src/utils/getRoles.js rename to src/utils/getRoles.ts diff --git a/src/utils/getUser.js b/src/utils/getUser.ts similarity index 100% rename from src/utils/getUser.js rename to src/utils/getUser.ts diff --git a/src/utils/notifications/deleteNotificationUser.js b/src/utils/notifications/deleteNotificationUser.ts similarity index 98% rename from src/utils/notifications/deleteNotificationUser.js rename to src/utils/notifications/deleteNotificationUser.ts index b7d7a93..7f37034 100644 --- a/src/utils/notifications/deleteNotificationUser.js +++ b/src/utils/notifications/deleteNotificationUser.ts @@ -1,6 +1,6 @@ import getXSRFToken from "../getXSRF.js"; -export default async function deleteNotificationUser(notificationId) { +export default async function deleteNotificationUser(notificationId:number) { const csrfToken = await getXSRFToken(); try { diff --git a/src/utils/notifications/getUserNotifications.js b/src/utils/notifications/getUserNotifications.ts similarity index 100% rename from src/utils/notifications/getUserNotifications.js rename to src/utils/notifications/getUserNotifications.ts diff --git a/src/utils/notifications/readNotifications.js b/src/utils/notifications/readNotifications.ts similarity index 94% rename from src/utils/notifications/readNotifications.js rename to src/utils/notifications/readNotifications.ts index 0f406ce..5b7f998 100644 --- a/src/utils/notifications/readNotifications.js +++ b/src/utils/notifications/readNotifications.ts @@ -1,4 +1,4 @@ -import getXSRFToken from "../getXSRF.js"; +import getXSRFToken from "../getXSRF"; export default async function readNotifications() { diff --git a/src/utils/register.js b/src/utils/register.ts similarity index 72% rename from src/utils/register.js rename to src/utils/register.ts index 489f07c..e2b6599 100644 --- a/src/utils/register.js +++ b/src/utils/register.ts @@ -1,7 +1,7 @@ import fetchWrapper from "./fetchWrapper.js"; import getXSRFToken from "./getXSRF.js"; -export default async function register(email, password, name, lastname, phone) { +export default async function register(email:string, password:string, name:string, lastname:string, phone:string) { const csrfToken = await getXSRFToken(); return fetchWrapper( diff --git a/src/utils/scrollToTop.js b/src/utils/scrollToTop.ts similarity index 100% rename from src/utils/scrollToTop.js rename to src/utils/scrollToTop.ts diff --git a/src/utils/users/deactivateUser.js b/src/utils/users/deactivateUser.ts similarity index 82% rename from src/utils/users/deactivateUser.js rename to src/utils/users/deactivateUser.ts index fdf4c44..58a358c 100644 --- a/src/utils/users/deactivateUser.js +++ b/src/utils/users/deactivateUser.ts @@ -1,7 +1,7 @@ import fetchWrapper from "../fetchWrapper.js"; import getXSRFToken from "../getXSRF.js"; -export default async function deactivateUser(userId) { +export default async function deactivateUser(userId:number) { const csrfToken = await getXSRFToken(); return fetchWrapper( diff --git a/src/utils/users/deleteOtherUser.js b/src/utils/users/deleteOtherUser.ts similarity index 81% rename from src/utils/users/deleteOtherUser.js rename to src/utils/users/deleteOtherUser.ts index ece6425..9a32763 100644 --- a/src/utils/users/deleteOtherUser.js +++ b/src/utils/users/deleteOtherUser.ts @@ -1,7 +1,7 @@ import fetchWrapper from "../fetchWrapper.js"; import getXSRFToken from "../getXSRF.js"; -export default async function deleteOtherUser(userId) { +export default async function deleteOtherUser(userId:number) { const csrfToken = await getXSRFToken(); return fetchWrapper( diff --git a/src/utils/users/getAllUsers.js b/src/utils/users/getAllUsers.ts similarity index 64% rename from src/utils/users/getAllUsers.js rename to src/utils/users/getAllUsers.ts index 584c39f..1b75dc9 100644 --- a/src/utils/users/getAllUsers.js +++ b/src/utils/users/getAllUsers.ts @@ -1,4 +1,4 @@ -import fetchWrapper from "../fetchWrapper.js"; +import fetchWrapper from "../fetchWrapper"; export default async function getAllUser() { return fetchWrapper("/api/users"); diff --git a/src/utils/users/getUserById.js b/src/utils/users/getUserById.js deleted file mode 100644 index e9a2c75..0000000 --- a/src/utils/users/getUserById.js +++ /dev/null @@ -1,5 +0,0 @@ -import fetchWrapper from "../fetchWrapper.js"; - -export default async function getUserById(id) { - return fetchWrapper(`/api/users/${id}`); -} diff --git a/src/utils/users/getUserById.ts b/src/utils/users/getUserById.ts new file mode 100644 index 0000000..d08943a --- /dev/null +++ b/src/utils/users/getUserById.ts @@ -0,0 +1,5 @@ +import fetchWrapper from "../fetchWrapper"; + +export default async function getUserById(id:number) { + return fetchWrapper(`/api/users/${id}`); +} diff --git a/src/utils/users/getUserToValidate.js b/src/utils/users/getUserToValidate.ts similarity index 68% rename from src/utils/users/getUserToValidate.js rename to src/utils/users/getUserToValidate.ts index 5176f1f..b0fde0e 100644 --- a/src/utils/users/getUserToValidate.js +++ b/src/utils/users/getUserToValidate.ts @@ -1,4 +1,4 @@ -import fetchWrapper from "../fetchWrapper.js"; +import fetchWrapper from "../fetchWrapper"; export default async function getUserToValidate() { return fetchWrapper("/api/users/invalid"); diff --git a/src/utils/users/modifyRole.js b/src/utils/users/modifyRole.ts similarity index 55% rename from src/utils/users/modifyRole.js rename to src/utils/users/modifyRole.ts index 6526cea..592f739 100644 --- a/src/utils/users/modifyRole.js +++ b/src/utils/users/modifyRole.ts @@ -1,7 +1,7 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; -export default async function modifyRole(role, userId) { +export default async function modifyRole(role:number, userId:number) { const csrfToken = await getXSRFToken(); return fetchWrapper( diff --git a/src/utils/users/updateUser.ts b/src/utils/users/updateUser.ts index 6714250..48f5b51 100644 --- a/src/utils/users/updateUser.ts +++ b/src/utils/users/updateUser.ts @@ -1,33 +1,12 @@ -/*import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; - -export default async function updateUser(name, lastname, phone) { - const csrfToken = await getXSRFToken(); - - return fetchWrapper( - "/api/users/update", - { name, lastname, phone }, - "POST", - { "X-XSRF-TOKEN": csrfToken } - ); -}*/ - import fetchWrapper from "../fetchWrapper"; import getXSRFToken from "../getXSRF"; -interface UserUpdateData { - name: string; - lastname: string; - phone: string | null; +export default async function updateUser(name: string, lastname: string, phone: string | null) { + const csrfToken = await getXSRFToken(); + return fetchWrapper( + "/api/users/update", + { name, lastname, phone }, + "POST", + { "X-XSRF-TOKEN": csrfToken } + ); } - -interface RequestHeaders { - "X-XSRF-TOKEN": string; -} -export default async function updateUser(name: string,lastname: string,phone: string | null): Promise { - const csrfToken: string = await getXSRFToken(); - const userData: UserUpdateData = {name,lastname,phone,}; - const headers: RequestHeaders = {"X-XSRF-TOKEN": csrfToken,}; - return fetchWrapper("/api/users/update",userData,"POST",headers); -} - diff --git a/src/utils/users/validateUser.js b/src/utils/users/validateUser.ts similarity index 56% rename from src/utils/users/validateUser.js rename to src/utils/users/validateUser.ts index f73b3ef..de10071 100644 --- a/src/utils/users/validateUser.js +++ b/src/utils/users/validateUser.ts @@ -1,7 +1,7 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; -export default async function validateUser(userId) { +export default async function validateUser(userId:number) { const csrfToken = await getXSRFToken(); return fetchWrapper( From 4dbd1274fde55c22e382aa3aa3acde59acdfa8e4 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Fri, 13 Mar 2026 17:08:36 +0100 Subject: [PATCH 11/29] fix useNavigate import --- src/pages/Login/components/LoginForm/LoginForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Login/components/LoginForm/LoginForm.tsx b/src/pages/Login/components/LoginForm/LoginForm.tsx index 49d576b..a899b16 100644 --- a/src/pages/Login/components/LoginForm/LoginForm.tsx +++ b/src/pages/Login/components/LoginForm/LoginForm.tsx @@ -3,7 +3,7 @@ import styles from "./LoginForm.module.css"; import Button from "../../../../components/ui/Button/Button"; import Input from "../../../../components/ui/Input/Input"; import Modal from "../../../../components/ui/Modal/Modal"; -import { useNavigate } from "react-router-dom"; +import { useNavigate } from "react-router"; import { AuthContext, AuthContextType } from "../../../../contexts/Auth/AuthContext"; interface LoginFormProps { From 6349439435c03856861ee9670b7e223f1519407d Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Fri, 13 Mar 2026 17:09:41 +0100 Subject: [PATCH 12/29] Show btn only if user is admin --- .../EventDetail/components/AssignUserBtn/AssignUserBtn.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx b/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx index ee69cc6..44bdaeb 100644 --- a/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx +++ b/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx @@ -1,4 +1,4 @@ -import { ReactNode, useEffect, useState } from "react"; +import {ReactNode, useContext, useEffect, useState} from "react"; import Button from "../../../../components/ui/Button/Button"; import Modal from "../../../../components/ui/Modal/Modal"; import User from "../../../Volunteers/interfaces/user.interface"; @@ -6,6 +6,7 @@ import getAllUser from "../../../../utils/users/getAllUsers"; import Loading from "../../../../components/ui/Loading/Loading"; import getUserById from "../../../../utils/users/getUserById"; import styles from "./AssignUserBtn.module.css"; +import {AuthContext} from "../../../../contexts/Auth/AuthContext"; interface AssignUserBtnProps { taskId: string | number; @@ -17,6 +18,10 @@ export default function AssignUserBtn({ taskId }: AssignUserBtnProps): ReactNode const [users, setUsers] = useState>([]); const [loading, setLoading] = useState(true); + const { user } = useContext(AuthContext) as any; + + if (!user?.isAdmin) return null; + useEffect(() => { (async () => { setLoading(true); From 79aeef6489d02450df17af727a1625bc80084042 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Fri, 13 Mar 2026 17:20:03 +0100 Subject: [PATCH 13/29] Update loading on auth --- src/layout.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/layout.jsx b/src/layout.jsx index d4a492b..4f94287 100644 --- a/src/layout.jsx +++ b/src/layout.jsx @@ -5,13 +5,16 @@ import Background from "./components/Background/Background.jsx"; import { Navigate } from "react-router"; import { useContext} from "react"; import { AuthContext } from "./contexts/Auth/AuthContext.js"; +import Loading from "./components/ui/Loading/Loading.tsx"; function Layout(){ const { user, loading } = useContext(AuthContext); - if (loading) return

Loading

; + if (loading) return + + ; if (!user) return ; if(user && user.validate === 0) return ; From 2dfc46ede8f70adc34658bcb8470a032d5af9d1a Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 17:29:15 +0100 Subject: [PATCH 14/29] lick on profile picture to update it --- src/pages/Profile/ProfilePage.module.css | 24 ++++++++++++- src/pages/Profile/ProfilePage.tsx | 35 +++++++++---------- .../SettingsModal/SettingsModal.tsx | 2 +- 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/pages/Profile/ProfilePage.module.css b/src/pages/Profile/ProfilePage.module.css index a47a7a7..288c0d1 100644 --- a/src/pages/Profile/ProfilePage.module.css +++ b/src/pages/Profile/ProfilePage.module.css @@ -133,6 +133,29 @@ margin-top: 16px; } +.profilePictureContainer { + position: relative; +} + +.pictureOverlay { + position: absolute; + bottom: 0; + left: 0; + right: 0; + background: rgba(0, 0, 0, 0.5); + color: white; + text-align: center; + padding: 2px; + border-radius: 0 0 90% 90%; + opacity: 0; + transition: opacity 0.2s; +} +.clickable { + cursor: pointer; +} +.profilePictureContainer:hover .pictureOverlay { + opacity: 1; +} @media (min-width: 768px) { .contentWrapper { flex-direction: row; @@ -172,7 +195,6 @@ } } -/* Adaptation pour grand écran */ @media (min-width: 1024px) { .container { max-width: 1200px; diff --git a/src/pages/Profile/ProfilePage.tsx b/src/pages/Profile/ProfilePage.tsx index 897ff61..12a2e34 100644 --- a/src/pages/Profile/ProfilePage.tsx +++ b/src/pages/Profile/ProfilePage.tsx @@ -1,7 +1,6 @@ -import getXSRFToken from "../../utils/getXSRF.js"; import {useContext, useEffect, useState} from "react"; import styles from "./ProfilePage.module.css"; -import {AuthContext} from "../../../src/contexts/Auth/AuthContext.js"; +import {AuthContext} from "../../contexts/Auth/AuthContext"; import formatDate from "../../utils/date/formatDate"; import Task from "../../components/Task/Task"; import SettingsModal from "./components/SettingsModal/SettingsModal"; @@ -63,7 +62,7 @@ function ProfilePage() { (async () => { console.log(JSON.stringify(import.meta.env.VITE_API_URL)); if (!isOwnProfile && id) { - const res = await getUserById(id); + const res = await getUserById(Number(id)); if (res.status === 404) { navigate("/404"); return; @@ -107,7 +106,7 @@ function ProfilePage() { }; const handleDeletePicture = async () => { - deleteProfilePhoto(); + await deleteProfilePhoto(); setProfilePicture(null); }; @@ -115,27 +114,27 @@ function ProfilePage() {
-
+ {/*
Photo de profil +
*/} +
+ Photo de profil + {isOwnProfile && ( +
+ Modifier +
+ )}
- {isOwnProfile && ( -
- - {user?.profile_photo_path && ( - - )} -
- )} - + (false); const [isDelete, setIsDelete] = useState(false); From 9ce7f1058c2264a8eb92837c18caefa2c31b9e90 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Fri, 13 Mar 2026 17:37:48 +0100 Subject: [PATCH 15/29] fix css for VolunteersProfilePicture --- src/pages/Profile/ProfilePage.tsx | 7 ------- .../components/VolunteersCard/VolunteersCard.module.css | 1 + 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/pages/Profile/ProfilePage.tsx b/src/pages/Profile/ProfilePage.tsx index 12a2e34..9cbc958 100644 --- a/src/pages/Profile/ProfilePage.tsx +++ b/src/pages/Profile/ProfilePage.tsx @@ -114,13 +114,6 @@ function ProfilePage() {
- {/*
- Photo de profil -
*/}
Date: Sun, 15 Mar 2026 16:12:33 +0100 Subject: [PATCH 16/29] Assign other user by admin account --- .../AssignUserBtn/AssignUserBtn.tsx | 25 ++++++++++++++++--- src/utils/tasks/assignOtherUser.ts | 13 ++++++++++ src/utils/tasks/unAssignOtherUser.ts | 13 ++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 src/utils/tasks/assignOtherUser.ts create mode 100644 src/utils/tasks/unAssignOtherUser.ts diff --git a/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx b/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx index 44bdaeb..9a9ad3d 100644 --- a/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx +++ b/src/pages/EventDetail/components/AssignUserBtn/AssignUserBtn.tsx @@ -7,6 +7,8 @@ import Loading from "../../../../components/ui/Loading/Loading"; import getUserById from "../../../../utils/users/getUserById"; import styles from "./AssignUserBtn.module.css"; import {AuthContext} from "../../../../contexts/Auth/AuthContext"; +import assignOtherUser from "../../../../utils/tasks/assignOtherUser"; +import unAssignOtherUser from "../../../../utils/tasks/unAssignOtherUser"; interface AssignUserBtnProps { taskId: string | number; @@ -50,8 +52,17 @@ export default function AssignUserBtn({ taskId }: AssignUserBtnProps): ReactNode })(); }, []); - const handleAssign = async (user: User) => { + const isUserAssigned = (u: User): boolean => + u.tasks.some(t => t.id === taskId); + const handleAssign = async (selectedUser: User) => { + await assignOtherUser(taskId as number, selectedUser.id); + setOpen(false); + }; + + const handleUnassign = async (selectedUser: User) => { + await unAssignOtherUser(taskId as number, selectedUser.id); + setOpen(false); }; return <> @@ -65,9 +76,15 @@ export default function AssignUserBtn({ taskId }: AssignUserBtnProps): ReactNode {user.name} {user.lastname}

- + {isUserAssigned(user) ? ( + + ) : ( + + )}
))}
diff --git a/src/utils/tasks/assignOtherUser.ts b/src/utils/tasks/assignOtherUser.ts new file mode 100644 index 0000000..189c06b --- /dev/null +++ b/src/utils/tasks/assignOtherUser.ts @@ -0,0 +1,13 @@ +import fetchWrapper from "../fetchWrapper.js"; +import getXSRFToken from "../getXSRF.js"; + +export default async function assignOtherUser(taskId: number, userId: number): Promise { + const csrfToken = await getXSRFToken(); + + return fetchWrapper( + `/api/events/task/assign/${userId}`, + {task_id: taskId}, + "POST", + {"X-XSRF-TOKEN": csrfToken} + ); +} diff --git a/src/utils/tasks/unAssignOtherUser.ts b/src/utils/tasks/unAssignOtherUser.ts new file mode 100644 index 0000000..0781dca --- /dev/null +++ b/src/utils/tasks/unAssignOtherUser.ts @@ -0,0 +1,13 @@ +import fetchWrapper from "../fetchWrapper.js"; +import getXSRFToken from "../getXSRF.js"; + +export default async function unAssignOtherUser(taskId: number, userId: number): Promise { + const csrfToken = await getXSRFToken(); + + return fetchWrapper( + `/api/events/task/unassign/${userId}`, + {task_id: taskId}, + "POST", + {"X-XSRF-TOKEN": csrfToken} + ); +} \ No newline at end of file From 1824b294f4e432cc6ab06ff9dde1802ee5276b6a Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Sun, 15 Mar 2026 16:28:24 +0100 Subject: [PATCH 17/29] Convert TS --- src/components/SearchBar/SearchBar.tsx | 4 +- src/components/Task/Task.tsx | 2 +- .../EventDetail/EventDetailProvider.jsx | 4 +- src/pages/Profile/ProfilePage.tsx | 2 +- src/utils/events/eventCounter.js | 28 ------------- src/utils/events/getEventById.js | 5 --- .../{searchEvents.js => searchEvents.ts} | 4 +- src/utils/tasks/{assign.js => assign.ts} | 6 +-- src/utils/tasks/createTask.js | 29 -------------- src/utils/tasks/createTask.ts | 39 +++++++++++++++++++ src/utils/tasks/deleteTask.js | 13 ------- src/utils/tasks/deleteTask.ts | 13 +++++++ src/utils/tasks/isAssigned.js | 9 ----- src/utils/tasks/isAssigned.ts | 9 +++++ src/utils/tasks/{unAssign.js => unAssign.ts} | 6 +-- src/utils/users/getUserById.js | 5 --- .../users/{searchUsers.js => searchUsers.ts} | 4 +- 17 files changed, 77 insertions(+), 105 deletions(-) delete mode 100644 src/utils/events/eventCounter.js delete mode 100644 src/utils/events/getEventById.js rename src/utils/events/{searchEvents.js => searchEvents.ts} (80%) rename src/utils/tasks/{assign.js => assign.ts} (56%) delete mode 100644 src/utils/tasks/createTask.js create mode 100644 src/utils/tasks/createTask.ts delete mode 100644 src/utils/tasks/deleteTask.js create mode 100644 src/utils/tasks/deleteTask.ts delete mode 100644 src/utils/tasks/isAssigned.js create mode 100644 src/utils/tasks/isAssigned.ts rename src/utils/tasks/{unAssign.js => unAssign.ts} (56%) delete mode 100644 src/utils/users/getUserById.js rename src/utils/users/{searchUsers.js => searchUsers.ts} (80%) diff --git a/src/components/SearchBar/SearchBar.tsx b/src/components/SearchBar/SearchBar.tsx index d1ef4c6..3e928ee 100644 --- a/src/components/SearchBar/SearchBar.tsx +++ b/src/components/SearchBar/SearchBar.tsx @@ -1,8 +1,8 @@ import styles from "./SearchBar.module.css"; import { Link } from "react-router"; import { useEffect, useState } from "react"; -import searchEvents from "../../utils/events/searchEvents.js"; -import searchUsers from "../../utils/users/searchUsers.js"; +import searchEvents from "../../utils/events/searchEvents"; +import searchUsers from "../../utils/users/searchUsers"; import { useLocation } from "react-router"; function SearchBar(): any { diff --git a/src/components/Task/Task.tsx b/src/components/Task/Task.tsx index daf805d..0c8c161 100644 --- a/src/components/Task/Task.tsx +++ b/src/components/Task/Task.tsx @@ -1,5 +1,5 @@ import { useEffect, useState } from "react"; -import getEventById from "../../utils/events/getEventById.js"; +import getEventById from "../../utils/events/getEventById"; import styles from "./Task.module.css"; import formatDate from "../../utils/date/formatDate"; diff --git a/src/contexts/EventDetail/EventDetailProvider.jsx b/src/contexts/EventDetail/EventDetailProvider.jsx index a760ab4..1d3b991 100644 --- a/src/contexts/EventDetail/EventDetailProvider.jsx +++ b/src/contexts/EventDetail/EventDetailProvider.jsx @@ -1,7 +1,7 @@ import {useState} from 'react'; import { EventDetailContext } from "./EventDetailContext.js" -import getEventById from "../../utils/events/getEventById.js"; -import deleteTaskFunction from "../../utils/tasks/deleteTask.js"; +import getEventById from "../../utils/events/getEventById"; +import deleteTaskFunction from "../../utils/tasks/deleteTask"; export function EventDetailProvider({ children }) { diff --git a/src/pages/Profile/ProfilePage.tsx b/src/pages/Profile/ProfilePage.tsx index 9cbc958..8eaa107 100644 --- a/src/pages/Profile/ProfilePage.tsx +++ b/src/pages/Profile/ProfilePage.tsx @@ -7,7 +7,7 @@ import SettingsModal from "./components/SettingsModal/SettingsModal"; import {useParams} from "react-router"; import {useNavigate} from "react-router"; import {useRef} from "react"; -import getUserById from "../../utils/users/getUserById.js"; +import getUserById from "../../utils/users/getUserById"; import ManageMember from "./components/ManageMember/ManageMember.jsx"; import uploadProfilePhoto from "../../utils/users/uploadProfilePhoto"; import deleteProfilePhoto from "../../utils/users/deleteProfilePhoto.js"; diff --git a/src/utils/events/eventCounter.js b/src/utils/events/eventCounter.js deleted file mode 100644 index 20ee578..0000000 --- a/src/utils/events/eventCounter.js +++ /dev/null @@ -1,28 +0,0 @@ -import { useEffect, useState } from "react"; -import getAllEvents from "../../utils/events/getAllEvents"; - -function EventsCounter() { - const [eventsCount, setEventsCount] = useState(0); - const [loading, setLoading] = useState(true); - useEffect(() => { - const fetchEvents = async () => { - try { - const events = await getAllEvents(); - if (Array.isArray(events)) { - setEventsCount(events.length); - } else { - setEventsCount(0); - } - } catch (err) { - console.error(err); - setEventsCount(0); - } finally { - setLoading(false); - } - }; - fetchEvents(); - }, []); - if (loading) return

Chargement...

; - return

Nombre d’événements : {eventsCount}

; -} -export default EventsCounter; diff --git a/src/utils/events/getEventById.js b/src/utils/events/getEventById.js deleted file mode 100644 index 0b41625..0000000 --- a/src/utils/events/getEventById.js +++ /dev/null @@ -1,5 +0,0 @@ -import fetchWrapper from "../fetchWrapper"; - -export default async function GetEventById(id) { - return fetchWrapper(`/api/events/${id}`, null, "GET"); -} diff --git a/src/utils/events/searchEvents.js b/src/utils/events/searchEvents.ts similarity index 80% rename from src/utils/events/searchEvents.js rename to src/utils/events/searchEvents.ts index aa8a327..351ae77 100644 --- a/src/utils/events/searchEvents.js +++ b/src/utils/events/searchEvents.ts @@ -1,4 +1,4 @@ -export default async function searchEvents(query) { +export default async function searchEvents(query: string): Promise { try { const encodedQuery = encodeURIComponent(query); const response = await fetch( @@ -13,7 +13,7 @@ export default async function searchEvents(query) { } ); const data = await response.json(); - return data.hits.map(hit => hit.document); + return data.hits.map((hit: any) => hit.document); } catch (err) { console.error("Erreur :", err); diff --git a/src/utils/tasks/assign.js b/src/utils/tasks/assign.ts similarity index 56% rename from src/utils/tasks/assign.js rename to src/utils/tasks/assign.ts index cb85dd3..a9d7e8b 100644 --- a/src/utils/tasks/assign.js +++ b/src/utils/tasks/assign.ts @@ -1,7 +1,7 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; -export default async function assign(taskId) { +export default async function assign(taskId: number): Promise { const csrfToken = await getXSRFToken(); return fetchWrapper( diff --git a/src/utils/tasks/createTask.js b/src/utils/tasks/createTask.js deleted file mode 100644 index a023d70..0000000 --- a/src/utils/tasks/createTask.js +++ /dev/null @@ -1,29 +0,0 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; - -export default async function createTask({ - eventId, - name, - description, - start, - end, - location, - maxParticipants, - }) { - const csrfToken = await getXSRFToken(); - - return fetchWrapper( - "/api/events/task", - { - event_id: eventId, - name, - description, - start, - end, - location, - max_participants: maxParticipants, - }, - "POST", - {"X-XSRF-TOKEN": csrfToken} - ); -} diff --git a/src/utils/tasks/createTask.ts b/src/utils/tasks/createTask.ts new file mode 100644 index 0000000..495b67e --- /dev/null +++ b/src/utils/tasks/createTask.ts @@ -0,0 +1,39 @@ +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; + +interface CreateTaskParams { + eventId: number; + name: string; + description: string; + start: string; + end: string; + location: string; + maxParticipants: number; +} + +export default async function createTask({ + eventId, + name, + description, + start, + end, + location, + maxParticipants, +}: CreateTaskParams): Promise { + const csrfToken = await getXSRFToken(); + + return fetchWrapper( + "/api/events/task", + { + event_id: eventId, + name, + description, + start, + end, + location, + max_participants: maxParticipants, + }, + "POST", + {"X-XSRF-TOKEN": csrfToken} + ); +} diff --git a/src/utils/tasks/deleteTask.js b/src/utils/tasks/deleteTask.js deleted file mode 100644 index 2641307..0000000 --- a/src/utils/tasks/deleteTask.js +++ /dev/null @@ -1,13 +0,0 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; - -export default async function deleteTask(taskId) { - const csrfToken = await getXSRFToken(); - - return fetchWrapper( - `/api/events/tasks/${taskId}`, - { task_id: taskId }, - "DELETE", - { "X-XSRF-TOKEN": csrfToken } - ); -} diff --git a/src/utils/tasks/deleteTask.ts b/src/utils/tasks/deleteTask.ts new file mode 100644 index 0000000..bc0e163 --- /dev/null +++ b/src/utils/tasks/deleteTask.ts @@ -0,0 +1,13 @@ +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; + +export default async function deleteTask(taskId: number): Promise { + const csrfToken = await getXSRFToken(); + + return fetchWrapper( + `/api/events/tasks/${taskId}`, + {task_id: taskId}, + "DELETE", + {"X-XSRF-TOKEN": csrfToken} + ); +} diff --git a/src/utils/tasks/isAssigned.js b/src/utils/tasks/isAssigned.js deleted file mode 100644 index 99ce6ff..0000000 --- a/src/utils/tasks/isAssigned.js +++ /dev/null @@ -1,9 +0,0 @@ -import fetchWrapper from "../fetchWrapper.js"; - -export default async function isAssigned(taskId) { - return fetchWrapper( - `/api/events/tasks/${taskId}/assigned`, - null, - "GET" - ); -} diff --git a/src/utils/tasks/isAssigned.ts b/src/utils/tasks/isAssigned.ts new file mode 100644 index 0000000..aafd14e --- /dev/null +++ b/src/utils/tasks/isAssigned.ts @@ -0,0 +1,9 @@ +import fetchWrapper from "../fetchWrapper"; + +export default async function isAssigned(taskId: number): Promise { + return fetchWrapper( + `/api/events/tasks/${taskId}/assigned`, + null, + "GET" + ); +} diff --git a/src/utils/tasks/unAssign.js b/src/utils/tasks/unAssign.ts similarity index 56% rename from src/utils/tasks/unAssign.js rename to src/utils/tasks/unAssign.ts index 7110328..4871a2e 100644 --- a/src/utils/tasks/unAssign.js +++ b/src/utils/tasks/unAssign.ts @@ -1,7 +1,7 @@ -import fetchWrapper from "../fetchWrapper.js"; -import getXSRFToken from "../getXSRF.js"; +import fetchWrapper from "../fetchWrapper"; +import getXSRFToken from "../getXSRF"; -export default async function unAssign(taskId) { +export default async function unAssign(taskId: number): Promise { const csrfToken = await getXSRFToken(); return fetchWrapper( diff --git a/src/utils/users/getUserById.js b/src/utils/users/getUserById.js deleted file mode 100644 index 9acd7bd..0000000 --- a/src/utils/users/getUserById.js +++ /dev/null @@ -1,5 +0,0 @@ -import fetchWrapper from "../fetchWrapper"; - -export default async function getUserById(id) { - return fetchWrapper(`/api/users/${id}`); -} diff --git a/src/utils/users/searchUsers.js b/src/utils/users/searchUsers.ts similarity index 80% rename from src/utils/users/searchUsers.js rename to src/utils/users/searchUsers.ts index ae0bd3a..6c06005 100644 --- a/src/utils/users/searchUsers.js +++ b/src/utils/users/searchUsers.ts @@ -1,4 +1,4 @@ -export default async function searchUsers(query) { +export default async function searchUsers(query: string): Promise { try { const encodedQuery = encodeURIComponent(query); const response = await fetch( @@ -13,7 +13,7 @@ export default async function searchUsers(query) { } ); const data = await response.json(); - return data.hits.map(hit => hit.document); + return data.hits.map((hit: any) => hit.document); } catch (err) { console.error("Erreur :", err); From c4943ea71dbb629a3bf7dd5c5c89040e8f0fa989 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 16 Mar 2026 09:57:04 +0100 Subject: [PATCH 18/29] Create Loading story --- src/stories/Loading.stories.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 src/stories/Loading.stories.tsx diff --git a/src/stories/Loading.stories.tsx b/src/stories/Loading.stories.tsx new file mode 100644 index 0000000..c2bc6aa --- /dev/null +++ b/src/stories/Loading.stories.tsx @@ -0,0 +1,14 @@ +import Loading from "../components/ui/Loading/Loading" + + +export default { + title: "UI/Loading", + component: Loading, + parameters: { + layout: "centered", + }, + tags: ['autodocs'], + argTypes: {}, +} + +export const Default = {} \ No newline at end of file From 4b12861423e8bdadfd3b2cad347efe83de633de9 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 16 Mar 2026 09:57:53 +0100 Subject: [PATCH 19/29] Delete .jsx loading story --- src/stories/Loading.stories.jsx | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 src/stories/Loading.stories.jsx diff --git a/src/stories/Loading.stories.jsx b/src/stories/Loading.stories.jsx deleted file mode 100644 index d856a7e..0000000 --- a/src/stories/Loading.stories.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import Loading from "../components/ui/Loading/Loading"; - - -export default { - title: 'UI/Loading', - component: Loading, - parameters: { - layout: 'centered', - }, - tags: ['autodocs'], -}; - -export const Primary = {}; \ No newline at end of file From 71ae5f0f904015824b7b5a1bffdcc10146a72861 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 16 Mar 2026 10:13:43 +0100 Subject: [PATCH 20/29] Create Header story --- src/stories/Header.stories.tsx | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/stories/Header.stories.tsx diff --git a/src/stories/Header.stories.tsx b/src/stories/Header.stories.tsx new file mode 100644 index 0000000..0d4610e --- /dev/null +++ b/src/stories/Header.stories.tsx @@ -0,0 +1,30 @@ +import { JSX } from "react"; +import { MemoryRouter } from "react-router"; +import Header from "../components/Header/Header"; +import { EventProvider } from "../contexts/Events/EventProvider"; +import { PendingMembersProvider } from "../contexts/PendingMembers/PendingMembersProvider"; +import { AuthProvider } from "../contexts/Auth/AuthProvider"; + +export default { + title: "Layout/Header", + component: Header, + parameters: { + layout: "fullscreen", + }, + tags: ["autodocs"], + decorators: [ + (Story: () => JSX.Element) => ( + + + + + + + + + + ), + ], +}; + +export const Default = {}; From e24ec61957720a748eb523554622f055067b284f Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 16 Mar 2026 12:23:22 +0100 Subject: [PATCH 21/29] Create Footer story --- src/stories/Footer.stories.tsx | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/stories/Footer.stories.tsx diff --git a/src/stories/Footer.stories.tsx b/src/stories/Footer.stories.tsx new file mode 100644 index 0000000..a8f2a60 --- /dev/null +++ b/src/stories/Footer.stories.tsx @@ -0,0 +1,21 @@ +import { JSX } from "react"; +import { MemoryRouter } from "react-router"; +import Footer from "../components/Footer/Footer"; + +export default { + title: "Layout/Footer", + component: Footer, + parameters: { + layout: "fullscreen", + }, + tags: ["autodocs"], + decorators: [ + (Story: () => JSX.Element) => ( + + + + ), + ], +}; + +export const Default = {}; From 0e4ce9ec3058c02f70c8ba72da1dec85ed1cbed4 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 16 Mar 2026 15:13:47 +0100 Subject: [PATCH 22/29] Remove task view in EventCard --- .../tools/CreateEventBtn/CreateEventBtn.jsx | 2 +- src/pages/Events/components/Event/Event.jsx | 55 +------------------ .../Events/components/Event/Event.module.css | 9 +++ 3 files changed, 13 insertions(+), 53 deletions(-) diff --git a/src/components/ToolBar/tools/CreateEventBtn/CreateEventBtn.jsx b/src/components/ToolBar/tools/CreateEventBtn/CreateEventBtn.jsx index 5aae9d6..1db6a10 100644 --- a/src/components/ToolBar/tools/CreateEventBtn/CreateEventBtn.jsx +++ b/src/components/ToolBar/tools/CreateEventBtn/CreateEventBtn.jsx @@ -26,7 +26,7 @@ export default function CreateEventBtn() { setIsOpen(false); } - if(!user.isAdmin) return null; + if(!user?.isAdmin) return null; return <> diff --git a/src/pages/Events/components/Event/Event.jsx b/src/pages/Events/components/Event/Event.jsx index 3067e79..fe15c4e 100644 --- a/src/pages/Events/components/Event/Event.jsx +++ b/src/pages/Events/components/Event/Event.jsx @@ -1,5 +1,4 @@ import styles from "./Event.module.css"; -import { useState, useEffect } from "react"; import { useNavigate } from "react-router"; import Button from "/src/components/ui/Button/Button" @@ -7,27 +6,10 @@ function Event({event}){ const navigate = useNavigate(); - const [eventMenu, seteventMenu] = useState(false); - const [windowSize, setWindowSize] = useState({ - width: null, - height: null, - }); - - useEffect(() => { - function handleResize() { - setWindowSize({ - width: window.innerWidth, - height: window.innerHeight, - }); - } - window.addEventListener("resize", handleResize); - handleResize(); - return () => window.removeEventListener("resize", handleResize); - }, []); - + const handleNavigate = () => navigate(`/events/` + event.id); return ( -
seteventMenu(!eventMenu)}> +
@@ -40,40 +22,9 @@ function Event({event}){

{event.name}

{event.description}

- {event.tasks != null ? ( -
-
    - {event.tasks - .slice(0,5) - .map((task, index) => ( -
  • - {task.name}
  • - ))} - {event.tasks.length > 5 ? ( -
  • ...
  • - ) : null} -
-
- ) : null}
- {windowSize.width > 768 ? ( -
- -
- ) : null} -
-
- {(windowSize.width <= 768 || eventMenu) ? ( - - - - ) : null} +
) diff --git a/src/pages/Events/components/Event/Event.module.css b/src/pages/Events/components/Event/Event.module.css index 021f7bd..409ce24 100644 --- a/src/pages/Events/components/Event/Event.module.css +++ b/src/pages/Events/components/Event/Event.module.css @@ -6,6 +6,10 @@ padding: 1rem 0.5rem; } +.eventContainer:hover { + cursor: pointer; +} + .eventContainerTop { display: flex; justify-content: space-between; @@ -99,6 +103,11 @@ display: none; } +.openBtn { + align-self: center; + white-space: nowrap; +} + @media screen and (max-width: 768px) { .eventImage { width: 100%; From d6f69fa4a5784942e5e2e70de1590b1b2a75e2be Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 16 Mar 2026 15:24:56 +0100 Subject: [PATCH 23/29] Remove task view in EventItem --- .../Home/components/EventList/EventItem.tsx | 52 +++---------------- 1 file changed, 6 insertions(+), 46 deletions(-) diff --git a/src/pages/Home/components/EventList/EventItem.tsx b/src/pages/Home/components/EventList/EventItem.tsx index 185f09d..2b48c79 100644 --- a/src/pages/Home/components/EventList/EventItem.tsx +++ b/src/pages/Home/components/EventList/EventItem.tsx @@ -1,6 +1,6 @@ import styles from "./EventList.module.css"; import { formatDateLetter } from "../../../../utils/date/formatDateLetter"; -import { useState } from "react"; +import { useNavigate } from "react-router"; type Task = { name: string; @@ -10,6 +10,7 @@ type Task = { }; type EventGroup = { + id: number; date: string; name: string; start: string | Date; @@ -21,60 +22,19 @@ type EventItemProps = { }; export default function EventItem({ eventGroup }: EventItemProps) { - const [isVisible, setIsVisible] = useState(false); + + const navigate = useNavigate(); return (
setIsVisible(!isVisible)} + onClick={() => navigate(`/events/${eventGroup.id}`)} >

{eventGroup.name}

{formatDateLetter(eventGroup.start)}

- - {isVisible && ( -
    - {eventGroup.tasks.map((task, i) => ( -
  • -

    - - {task.name} - {task.description} -

    -

    - {formatDateLetter(task.start)} - {formatDateLetter(task.end)} -

    -
  • - ))} -
- )}
); -} - -/*import styles from "./eventList.module.css"; -import { formatDateLetter } from "../../../../utils/date/formatDateLetter.ts"; -import { useState } from "react"; - -export default function EventItem({ eventGroup }) { - - const [isVisible, setIsVisible] = useState(false); - - return
setIsVisible(!isVisible)}> -
-

{eventGroup.name}

-

{formatDateLetter(eventGroup.start)}

-
- {isVisible && -
    - {eventGroup.tasks.map((task, i) => ( -
  • -

    - {task.name} - {task.description}

    -

    {formatDateLetter(task.start)} - {formatDateLetter(task.end)}

    -
  • - ))} -
- } -
-} -*/ \ No newline at end of file +} \ No newline at end of file From 76bf6384f5d1b52925ed333817367cca12cc6955 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Mon, 16 Mar 2026 15:34:48 +0100 Subject: [PATCH 24/29] Create ExportBtn component + Change calendar adding url --- .../Home/components/Calendar/Calendar.jsx | 14 ++----------- .../components/Calendar/Calendar.module.css | 1 + .../Home/components/Calendar/ExportBtn.tsx | 20 +++++++++++++++++++ 3 files changed, 23 insertions(+), 12 deletions(-) create mode 100644 src/pages/Home/components/Calendar/ExportBtn.tsx diff --git a/src/pages/Home/components/Calendar/Calendar.jsx b/src/pages/Home/components/Calendar/Calendar.jsx index 53ba22a..574b172 100644 --- a/src/pages/Home/components/Calendar/Calendar.jsx +++ b/src/pages/Home/components/Calendar/Calendar.jsx @@ -3,13 +3,12 @@ import styles from "./Calendar.module.css"; import {formatDateLetterJS} from "../../../../utils/date/formatDateLetter.js"; import Button from "../../../../components/ui/Button/Button"; import {AuthContext} from "../../../../contexts/Auth/AuthContext.ts"; +import ExportBtn from "./ExportBtn.tsx"; function Calendar() { const { user } = useContext(AuthContext); - const calendarUrl = `${import.meta.env.VITE_API_URL}/api/export/ics/${user.id}`; - const monthNames = [ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" @@ -152,16 +151,7 @@ Calendar() {
)}
-

votre lien d'agenda: {calendarUrl}

- +
diff --git a/src/pages/Home/components/Calendar/Calendar.module.css b/src/pages/Home/components/Calendar/Calendar.module.css index b70ac34..c577ba6 100644 --- a/src/pages/Home/components/Calendar/Calendar.module.css +++ b/src/pages/Home/components/Calendar/Calendar.module.css @@ -156,6 +156,7 @@ margin-top: 16px; display: flex; align-items: center; + justify-content: center; } .exportbtn { diff --git a/src/pages/Home/components/Calendar/ExportBtn.tsx b/src/pages/Home/components/Calendar/ExportBtn.tsx new file mode 100644 index 0000000..61dd619 --- /dev/null +++ b/src/pages/Home/components/Calendar/ExportBtn.tsx @@ -0,0 +1,20 @@ +import Button from "../../../../components/ui/Button/Button"; +import styles from "../../HomePage.module.css" +import { useContext } from "react"; +import {AuthContext, AuthContextType} from "../../../../contexts/Auth/AuthContext"; + +export default function ExportBtn() { + + const { user } = useContext(AuthContext) as AuthContextType; + const calendarUrl = `${import.meta.env.VITE_API_URL}/api/export/ics/${user?.id}`; + + return +} \ No newline at end of file From 64e5e33c4a5e0e2582c467a81a883030c19b83c2 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Tue, 17 Mar 2026 08:35:46 +0100 Subject: [PATCH 25/29] Fix id in User type --- src/contexts/Auth/AuthContext.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/contexts/Auth/AuthContext.ts b/src/contexts/Auth/AuthContext.ts index 3e3142c..b43a236 100644 --- a/src/contexts/Auth/AuthContext.ts +++ b/src/contexts/Auth/AuthContext.ts @@ -9,6 +9,7 @@ export interface Task { } export interface User { + id: number name: string; lastname: string; role: string; From 580a0c31564733610923b6d86c80a80955f2c396 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Tue, 17 Mar 2026 08:39:21 +0100 Subject: [PATCH 26/29] Move google calendar url to APP_CONFIG --- src/config/appConfig.js | 3 ++- src/pages/Home/components/Calendar/ExportBtn.tsx | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/config/appConfig.js b/src/config/appConfig.js index 12764ab..899a34a 100644 --- a/src/config/appConfig.js +++ b/src/config/appConfig.js @@ -1,4 +1,5 @@ export const APP_CONFIG = { contactEmail: "contact@example.com", - contactPhone: "+33 01 02 03 04 05" + contactPhone: "+33 01 02 03 04 05", + newCalendarURL: "https://calendar.google.com/calendar/u/0/r/settings/addbyurl?cid=" } \ No newline at end of file diff --git a/src/pages/Home/components/Calendar/ExportBtn.tsx b/src/pages/Home/components/Calendar/ExportBtn.tsx index 61dd619..c5192aa 100644 --- a/src/pages/Home/components/Calendar/ExportBtn.tsx +++ b/src/pages/Home/components/Calendar/ExportBtn.tsx @@ -1,7 +1,8 @@ import Button from "../../../../components/ui/Button/Button"; import styles from "../../HomePage.module.css" import { useContext } from "react"; -import {AuthContext, AuthContextType} from "../../../../contexts/Auth/AuthContext"; +import { AuthContext, AuthContextType } from "../../../../contexts/Auth/AuthContext"; +import { APP_CONFIG } from "../../../../config/appConfig"; export default function ExportBtn() { @@ -11,7 +12,7 @@ export default function ExportBtn() { return