From 4c22dfc1b1b5c90dd5a5a3a60b4ce6250ad5865b Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 18 Mar 2026 10:57:02 +0100 Subject: [PATCH 01/30] Move ExportCalendarbtn --- .../ExportCalendarBtn/ExportBtn.tsx | 20 ++++++++++++++++++ .../Home/components/Calendar/Calendar.jsx | 3 +-- .../Home/components/Calendar/ExportBtn.tsx | 21 ------------------- 3 files changed, 21 insertions(+), 23 deletions(-) create mode 100644 src/components/ExportCalendarBtn/ExportBtn.tsx delete mode 100644 src/pages/Home/components/Calendar/ExportBtn.tsx diff --git a/src/components/ExportCalendarBtn/ExportBtn.tsx b/src/components/ExportCalendarBtn/ExportBtn.tsx new file mode 100644 index 0000000..14bca2b --- /dev/null +++ b/src/components/ExportCalendarBtn/ExportBtn.tsx @@ -0,0 +1,20 @@ +import Button from "../ui/Button/Button"; +import { useContext } from "react"; +import { AuthContext, AuthContextType } from "../../contexts/Auth/AuthContext"; +import { APP_CONFIG } from "../../config/appConfig"; + +export default function ExportCalendarBtn() { + + 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 diff --git a/src/pages/Home/components/Calendar/Calendar.jsx b/src/pages/Home/components/Calendar/Calendar.jsx index ba80de5..66f7a7b 100644 --- a/src/pages/Home/components/Calendar/Calendar.jsx +++ b/src/pages/Home/components/Calendar/Calendar.jsx @@ -1,9 +1,8 @@ import {useState, useMemo, useEffect, useContext} from "react"; 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"; +import ExportBtn from "../../../../components/ExportCalendarBtn/ExportBtn.tsx"; function Calendar() { diff --git a/src/pages/Home/components/Calendar/ExportBtn.tsx b/src/pages/Home/components/Calendar/ExportBtn.tsx deleted file mode 100644 index c5192aa..0000000 --- a/src/pages/Home/components/Calendar/ExportBtn.tsx +++ /dev/null @@ -1,21 +0,0 @@ -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 { APP_CONFIG } from "../../../../config/appConfig"; - -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 00d1d948f7fd46f5a5de828a6307b599f4886220 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 18 Mar 2026 10:59:00 +0100 Subject: [PATCH 02/30] Add ExportBtn to settings --- src/components/ExportCalendarBtn/ExportBtn.tsx | 3 ++- .../Profile/components/SettingsModal/SettingsModal.tsx | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/ExportCalendarBtn/ExportBtn.tsx b/src/components/ExportCalendarBtn/ExportBtn.tsx index 14bca2b..d563a66 100644 --- a/src/components/ExportCalendarBtn/ExportBtn.tsx +++ b/src/components/ExportCalendarBtn/ExportBtn.tsx @@ -9,12 +9,13 @@ export default function ExportCalendarBtn() { const calendarUrl = `${import.meta.env.VITE_API_URL}/api/export/ics/${user?.id}`; return } \ No newline at end of file diff --git a/src/pages/Profile/components/SettingsModal/SettingsModal.tsx b/src/pages/Profile/components/SettingsModal/SettingsModal.tsx index 7d39830..f152857 100644 --- a/src/pages/Profile/components/SettingsModal/SettingsModal.tsx +++ b/src/pages/Profile/components/SettingsModal/SettingsModal.tsx @@ -7,6 +7,7 @@ import {AuthContext} from "../../../../contexts/Auth/AuthContext"; import TextInput from "../../../../components/ui/Input/Input"; import updateUser from "../../../../utils/users/updateUser.js"; import deleteUser from "../../../../utils/users/deleteUser.js"; +import ExportCalendarBtn from "../../../../components/ExportCalendarBtn/ExportBtn"; interface TaskType { id: number; @@ -130,6 +131,12 @@ export default function SettingsModal() { + +
+

Divers

+ +
+

Sécurité du compte

From 8abdb7935ead0e4bfa5a6b67f3e2b386c1692890 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 18 Mar 2026 11:03:18 +0100 Subject: [PATCH 03/30] Convert to Typescript --- src/pages/Home/HomePage.jsx | 15 --------------- src/pages/Home/HomePage.tsx | 12 ++++++++++++ src/router.js | 2 +- 3 files changed, 13 insertions(+), 16 deletions(-) delete mode 100644 src/pages/Home/HomePage.jsx create mode 100644 src/pages/Home/HomePage.tsx diff --git a/src/pages/Home/HomePage.jsx b/src/pages/Home/HomePage.jsx deleted file mode 100644 index 1e2e3d9..0000000 --- a/src/pages/Home/HomePage.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import styles from "./HomePage.module.css"; -import Calendar from "./components/Calendar/Calendar.jsx"; -import EventList from "./components/EventList/EventList"; - -function HomePage() { - - return ( -
- - -
- ); -} - -export default HomePage; diff --git a/src/pages/Home/HomePage.tsx b/src/pages/Home/HomePage.tsx new file mode 100644 index 0000000..a34d095 --- /dev/null +++ b/src/pages/Home/HomePage.tsx @@ -0,0 +1,12 @@ +import styles from "./HomePage.module.css"; +import Calendar from "./components/Calendar/Calendar"; +import EventList from "./components/EventList/EventList"; +import { ReactNode } from "react"; + +export default function HomePage(): ReactNode { + + return
+ + +
+} diff --git a/src/router.js b/src/router.js index 11c3bb8..418bf47 100644 --- a/src/router.js +++ b/src/router.js @@ -1,6 +1,6 @@ import { createBrowserRouter } from "react-router"; import Layout from "./layout.jsx"; -import HomePage from "./pages/Home/HomePage"; +import HomePage from "./pages/Home/HomePage.tsx"; import LoginPage from "./pages/Login/LoginPage"; import RegisterPage from "./pages/Register/RegisterPage.jsx"; import VolunteersPage from "./pages/Volunteers/VolunteersPage"; From 00337762212804d25ecb9e7507bcba4b797800f6 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Wed, 18 Mar 2026 11:04:11 +0100 Subject: [PATCH 04/30] add shortcut on RegisterMemeber --- .../Admin/components/RegisterMember/RegisterMember.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/pages/Admin/components/RegisterMember/RegisterMember.tsx b/src/pages/Admin/components/RegisterMember/RegisterMember.tsx index 9905e68..3c33740 100644 --- a/src/pages/Admin/components/RegisterMember/RegisterMember.tsx +++ b/src/pages/Admin/components/RegisterMember/RegisterMember.tsx @@ -48,12 +48,18 @@ const RegisterMember: React.FC = () => { setOpen(true); } + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + handleCreate(); + } + }; + return

Enregister un bénévole

-
+
setName(e.target.value)} /> setLastName(e.target.value)} /> setEmail(e.target.value)} /> From 15bb9126cd18feff8325684a4dc8d705586c7050 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Wed, 18 Mar 2026 11:29:02 +0100 Subject: [PATCH 05/30] group TS interfaces to avoid redundancy --- src/contexts/Auth/AuthContext.ts | 21 +-------- src/interfaces/auth.interfaces.ts | 6 +++ ...askType.interface.ts => task.interface.ts} | 6 +++ src/interfaces/user.interface.ts | 2 +- src/pages/Profile/ProfilePage.tsx | 43 +++---------------- 5 files changed, 20 insertions(+), 58 deletions(-) create mode 100644 src/interfaces/auth.interfaces.ts rename src/interfaces/{taskType.interface.ts => task.interface.ts} (73%) diff --git a/src/contexts/Auth/AuthContext.ts b/src/contexts/Auth/AuthContext.ts index b43a236..79c8bfd 100644 --- a/src/contexts/Auth/AuthContext.ts +++ b/src/contexts/Auth/AuthContext.ts @@ -1,24 +1,5 @@ import { createContext } from "react"; - - -export interface Task { - id: number; - title?: string; - completed?: boolean; - [key: string]: unknown; -} - -export interface User { - id: number - name: string; - lastname: string; - role: string; - email: string; - phone: string | null; - created_at: string; - profile_photo_path?: string | null; - tasks: Task[]; -} +import User from "./../../interfaces/user.interface" export interface AuthContextType { user: User | null; diff --git a/src/interfaces/auth.interfaces.ts b/src/interfaces/auth.interfaces.ts new file mode 100644 index 0000000..765a46a --- /dev/null +++ b/src/interfaces/auth.interfaces.ts @@ -0,0 +1,6 @@ + +import type User from "./user.interface"; +export interface AuthContextType { + user: User | null; + update: () => void; +} diff --git a/src/interfaces/taskType.interface.ts b/src/interfaces/task.interface.ts similarity index 73% rename from src/interfaces/taskType.interface.ts rename to src/interfaces/task.interface.ts index d116c3d..181d539 100644 --- a/src/interfaces/taskType.interface.ts +++ b/src/interfaces/task.interface.ts @@ -13,4 +13,10 @@ export default interface TaskType { user_id: number; task_id: number; }; +} +export default interface Task { + id: number; + title?: string; + completed?: boolean; + [key: string]: unknown; } \ No newline at end of file diff --git a/src/interfaces/user.interface.ts b/src/interfaces/user.interface.ts index de1f401..a2de519 100644 --- a/src/interfaces/user.interface.ts +++ b/src/interfaces/user.interface.ts @@ -1,4 +1,4 @@ -import TaskType from "./taskType.interface"; +import TaskType from "./task.interface"; export default interface User { id: number; diff --git a/src/pages/Profile/ProfilePage.tsx b/src/pages/Profile/ProfilePage.tsx index ef09a69..a0e7664 100644 --- a/src/pages/Profile/ProfilePage.tsx +++ b/src/pages/Profile/ProfilePage.tsx @@ -7,46 +7,15 @@ 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"; -import ManageMember from "./components/ManageMember/ManageMember.js"; +import getUserById from "../../utils/users/getUserById.js"; +import ManageMember from "./components/ManageMember/ManageMember"; import uploadProfilePhoto from "../../utils/users/uploadProfilePhoto"; -import deleteProfilePhoto from "../../utils/users/deleteProfilePhoto.js"; - -interface TaskType { - id: number; - name: string; - description: string; - location: string; - start: string; - end: string; - max_participants: number; - events_id: number; - created_at: string; - updated_at: string; - pivot: { - user_id: number; - task_id: number; - }; -} +import deleteProfilePhoto from "../../utils/users/deleteProfilePhoto"; +import type { AuthContextType } from "../../interfaces/AuthInterfaces"; +import type TaskType from "../../interfaces/task.interface"; +import type User from "../../interfaces/user.interface"; -interface User { - id: number; - name: string; - lastname: string; - role: string; - email: string; - phone: string | null; - created_at: string; - isAdmin: boolean; - tasks: TaskType[]; - profile_photo_path?: string | null; -} - -interface AuthContextType { - user: User | null; - update: () => void; -} function ProfilePage() { const navigate = useNavigate(); From 2c9d0918012d671f42c56b76bdcc0c2815dda32d Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 18 Mar 2026 20:45:25 +0100 Subject: [PATCH 06/30] Convert Background to Typescript --- .../{Background.jsx => Background.tsx} | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) rename src/components/Background/{Background.jsx => Background.tsx} (56%) diff --git a/src/components/Background/Background.jsx b/src/components/Background/Background.tsx similarity index 56% rename from src/components/Background/Background.jsx rename to src/components/Background/Background.tsx index 88cd57d..a578004 100644 --- a/src/components/Background/Background.jsx +++ b/src/components/Background/Background.tsx @@ -1,13 +1,18 @@ import styles from "./Background.module.css"; -import { useEffect, useRef, useState } from "react"; +import { useEffect, useRef, useState, ReactNode } from "react"; -const Background = ({ children, className }) => { +interface BackgroundProps { + children?: ReactNode; + className?: string; +} - const circlesRef = useRef([]); +const Background = ({ children, className }: BackgroundProps) => { + + const circlesRef = useRef<(HTMLDivElement | null)[]>([]); const [theme, setTheme] = useState("light"); - const getRandomTranslation = () => { - const randomX = Math.floor(Math.random() * 100) - 30; + const getRandomTranslation = (): { x: number; y: number } => { + const randomX = Math.floor(Math.random() * 100) - 30; const randomY = Math.floor(Math.random() * 100) - 30; return { x: randomX, y: randomY }; }; @@ -27,7 +32,7 @@ const Background = ({ children, className }) => { setTheme(localStorage.getItem("theme") || "light"); }; - updateTheme(); // Initial load + updateTheme(); window.addEventListener("theme-changed", updateTheme); @@ -40,29 +45,29 @@ const Background = ({ children, className }) => { return (
(circlesRef.current[0] = el)} + ref={(el) => { circlesRef.current[0] = el; }} className={`${styles["circle"]} ${styles["circle-1"]}`} - style={{ "--random-x": "0px", "--random-y": "0px" }} + style={{ "--random-x": "0px", "--random-y": "0px" } as React.CSSProperties} >
(circlesRef.current[1] = el)} + ref={(el) => { circlesRef.current[1] = el; }} className={`${styles["circle"]} ${styles["circle-2"]}`} - style={{ "--random-x": "0px", "--random-y": "0px" }} + style={{ "--random-x": "0px", "--random-y": "0px" } as React.CSSProperties} >
(circlesRef.current[2] = el)} + ref={(el) => { circlesRef.current[2] = el; }} className={`${styles["circle"]} ${styles["circle-3"]}`} - style={{ "--random-x": "0px", "--random-y": "0px" }} + style={{ "--random-x": "0px", "--random-y": "0px" } as React.CSSProperties} >
(circlesRef.current[3] = el)} + ref={(el) => { circlesRef.current[3] = el; }} className={`${styles["circle"]} ${styles["circle-4"]}`} - style={{ "--random-x": "0px", "--random-y": "0px" }} + style={{ "--random-x": "0px", "--random-y": "0px" } as React.CSSProperties} >
(circlesRef.current[4] = el)} + ref={(el) => { circlesRef.current[4] = el; }} className={`${styles["circle"]} ${styles["circle-5"]}`} - style={{ "--random-x": "0px", "--random-y": "0px" }} + style={{ "--random-x": "0px", "--random-y": "0px" } as React.CSSProperties} >
{children}
From 5b4078e75918c669923a99dfaceb0aa5f0f9e8da Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 18 Mar 2026 20:48:14 +0100 Subject: [PATCH 07/30] Convert Footer to Typescript --- .../Footer/{Footer.jsx => Footer.tsx} | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) rename src/components/Footer/{Footer.jsx => Footer.tsx} (84%) diff --git a/src/components/Footer/Footer.jsx b/src/components/Footer/Footer.tsx similarity index 84% rename from src/components/Footer/Footer.jsx rename to src/components/Footer/Footer.tsx index 881943e..06d5ca8 100644 --- a/src/components/Footer/Footer.jsx +++ b/src/components/Footer/Footer.tsx @@ -1,13 +1,13 @@ import styles from "./Footer.module.css" -import {Link} from "react-router"; -import {useState} from "react"; +import { Link } from "react-router"; +import { ReactNode, useState } from "react"; import Modal from "../ui/Modal/Modal"; import Button from "../ui/Button/Button"; import scrollToTop from "../../utils/scrollToTop.js"; -export default function Footer(){ +export default function Footer(): ReactNode{ const currentYear = new Date().getFullYear(); - const [isCopyrightModal, setIsCopyrightModal] = useState(false); + const [isCopyrightModal, setIsCopyrightModal] = useState(false); return <> @@ -48,11 +48,11 @@ export default function Footer(){ setIsCopyrightModal(false)}>
-

Quentin T'jampens

-

Antoine Ordonneau

-

Malo Leblond

+

Quentin T'JAMPENS

+

Antoine ORDONNEAU

+

Malo LEBLOND

- Giovanni Josserand ( + Giovanni JOSSERAND ( linktree )

@@ -60,4 +60,4 @@ export default function Footer(){
-} \ No newline at end of file +} From 5787f941fdeb13fa5c18a519237d8ce5a9b020a0 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 18 Mar 2026 20:53:45 +0100 Subject: [PATCH 08/30] Convert Header to Typescript --- .../Header/{Header.jsx => Header.tsx} | 49 +++++++++++-------- src/contexts/Events/EventContext.ts | 1 + 2 files changed, 29 insertions(+), 21 deletions(-) rename src/components/Header/{Header.jsx => Header.tsx} (83%) diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.tsx similarity index 83% rename from src/components/Header/Header.jsx rename to src/components/Header/Header.tsx index bd4b821..07e8785 100644 --- a/src/components/Header/Header.jsx +++ b/src/components/Header/Header.tsx @@ -1,5 +1,5 @@ import { Link, NavLink } from "react-router"; -import {useContext, useEffect, useRef, useState} from "react"; +import { useContext, useEffect, useRef, useState } from "react"; import styles from "./Header.module.css" import getUserNotifications from "../../utils/notifications/getUserNotifications.js"; import deleteNotificationUser from "../../utils/notifications/deleteNotificationUser.js"; @@ -9,32 +9,39 @@ import { userCreatedListener } from "../../utils/echo/listeners/userCreatedListe import { userNotificationsListener } from "../../utils/echo/listeners/userNotificationsListener.js"; import NotificationCard from "../NotificationCard/NotificationCard.jsx"; import { EventContext } from "../../contexts/Events/EventContext.js"; -import {AuthContext} from "../../contexts/Auth/AuthContext.js"; +import { AuthContext } from "../../contexts/Auth/AuthContext.js"; import { PendingMembersContext } from "../../contexts/PendingMembers/PendingMembersContext"; +interface Notification { + id: number; + content: string; + created_at: string | number; + pivot: { unread: number }; +} + function Header() { - const { update, user } = useContext(AuthContext); - const { updateEvent } = useContext(EventContext); - const [notificationMenu, setnotificationMenu] = useState(false); - const [unreadNotification, setunreadNotification] = useState(false); - const [mobileMenu, setMobileMenu] = useState(false); - const [notifications, setNotifications] = useState([]); - const notificationRef = useRef(null); - const { updatePendingMembers } = useContext(PendingMembersContext); + const { update, user } = useContext(AuthContext)!; + const { updateEvent } = useContext(EventContext)!; + const { updatePendingMembers } = useContext(PendingMembersContext) as unknown as { updatePendingMembers: () => void }; + const [notificationMenu, setnotificationMenu] = useState(false); + const [unreadNotification, setunreadNotification] = useState(false); + const [mobileMenu, setMobileMenu] = useState(false); + const [notifications, setNotifications] = useState([]); + const notificationRef = useRef(null); useEffect(() => { updateEvent(); - let echoInstance = null; - let channelsToLeave = []; + let echoInstance: ReturnType | null = null; + let channelsToLeave: string[] = []; async function initializeHeader() { try { const notifData = await getUserNotifications(); - const data = notifData || []; + const data: Notification[] = notifData || []; setNotifications(data); const hasUnread = data.some(n => n.pivot && n.pivot.unread === 1); setunreadNotification(hasUnread); @@ -42,11 +49,11 @@ function Header() { const echo = initEcho(); echoInstance = echo; - const activeChannels = [ + const activeChannels: (string | null)[] = [ userCreatedListener(echo, user, setNotifications, setunreadNotification, updatePendingMembers), userNotificationsListener(echo, user, setNotifications, setunreadNotification), ]; - channelsToLeave = activeChannels.filter(name => name !== null); + channelsToLeave = activeChannels.filter((name): name is string => name !== null); } catch (err) { console.error("Erreur initialisation Header:", err); @@ -55,11 +62,11 @@ function Header() { initializeHeader(); - const handleClickOutside = (event) => { + const handleClickOutside = (event: MouseEvent) => { if ( notificationRef.current && - !notificationRef.current.contains(event.target) && - !event.target.closest(`.${styles.bellBtn}`) + !notificationRef.current.contains(event.target as Node) && + !(event.target as Element).closest(`.${styles.bellBtn}`) ) { setnotificationMenu(false); } @@ -70,7 +77,7 @@ function Header() { return () => { document.removeEventListener("mousedown", handleClickOutside); if (echoInstance) { - channelsToLeave.forEach(chan => echoInstance.leave(chan)); + channelsToLeave.forEach(chan => echoInstance!.leave(chan)); } }; }, []); @@ -93,7 +100,7 @@ function Header() { } - async function deleteNotification(notificationId) { + async function deleteNotification(notificationId: number) { try { const result = await deleteNotificationUser(notificationId); if (result) { @@ -194,4 +201,4 @@ function Header() { ); } -export default Header; \ No newline at end of file +export default Header; diff --git a/src/contexts/Events/EventContext.ts b/src/contexts/Events/EventContext.ts index 166a883..7b87226 100644 --- a/src/contexts/Events/EventContext.ts +++ b/src/contexts/Events/EventContext.ts @@ -16,6 +16,7 @@ export type EventGroup = { export type EventContextType = { events: EventGroup[]; + updateEvent: () => void; }; export const EventContext = createContext(null); \ No newline at end of file From 724ae99b2970ee66a5850df0ea3c97d00abc699e Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 18 Mar 2026 20:58:30 +0100 Subject: [PATCH 09/30] Convert NotificationCard to Typescript --- src/components/Header/Header.tsx | 10 ++-------- .../{NotificationCard.jsx => NotificationCard.tsx} | 12 ++++++++---- src/interfaces/notification.interface.ts | 6 ++++++ 3 files changed, 16 insertions(+), 12 deletions(-) rename src/components/NotificationCard/{NotificationCard.jsx => NotificationCard.tsx} (69%) create mode 100644 src/interfaces/notification.interface.ts diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index 07e8785..ea8bf8c 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -7,17 +7,11 @@ import initEcho from "../../utils/echo/initEcho.js" import readNotifications from "../../utils/notifications/readNotifications.js"; import { userCreatedListener } from "../../utils/echo/listeners/userCreatedListener"; import { userNotificationsListener } from "../../utils/echo/listeners/userNotificationsListener.js"; -import NotificationCard from "../NotificationCard/NotificationCard.jsx"; +import NotificationCard from "../NotificationCard/NotificationCard"; import { EventContext } from "../../contexts/Events/EventContext.js"; import { AuthContext } from "../../contexts/Auth/AuthContext.js"; import { PendingMembersContext } from "../../contexts/PendingMembers/PendingMembersContext"; - -interface Notification { - id: number; - content: string; - created_at: string | number; - pivot: { unread: number }; -} +import Notification from "../../interfaces/notification.interface"; function Header() { diff --git a/src/components/NotificationCard/NotificationCard.jsx b/src/components/NotificationCard/NotificationCard.tsx similarity index 69% rename from src/components/NotificationCard/NotificationCard.jsx rename to src/components/NotificationCard/NotificationCard.tsx index 50774b4..b1baa66 100644 --- a/src/components/NotificationCard/NotificationCard.jsx +++ b/src/components/NotificationCard/NotificationCard.tsx @@ -1,16 +1,20 @@ import formatDate from "../../utils/date/formatDate.js"; import formatTime from "../../utils/date/formatTime.js"; - import styles from "./NotificationCard.module.css" +import Notification from "../../interfaces/notification.interface"; +interface NotificationCardProps { + notifications: Notification[]; + deleteNotification: (id: number) => void; +} -function NotificationCard({notifications, deleteNotification}) { +function NotificationCard({ notifications, deleteNotification }: NotificationCardProps) { return ( notifications.map((notification, index) => (
- Le {formatDate(notification.created_at)} à {formatTime(notification.created_at)} + Le {formatDate(String(notification.created_at))} à {formatTime(String(notification.created_at))}
-} \ No newline at end of file +} From 729e78c72564a45b2d58b86ae43a55a71b89c542 Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 18 Mar 2026 21:22:38 +0100 Subject: [PATCH 14/30] Convert RGPDPage to Typescript --- src/pages/RGPD/{RGPDPage.jsx => RGPDPage.tsx} | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) rename src/pages/RGPD/{RGPDPage.jsx => RGPDPage.tsx} (82%) diff --git a/src/pages/RGPD/RGPDPage.jsx b/src/pages/RGPD/RGPDPage.tsx similarity index 82% rename from src/pages/RGPD/RGPDPage.jsx rename to src/pages/RGPD/RGPDPage.tsx index 2769d54..e0a81bb 100644 --- a/src/pages/RGPD/RGPDPage.jsx +++ b/src/pages/RGPD/RGPDPage.tsx @@ -4,7 +4,7 @@ import {Link} from "react-router"; export default function RGPDPage() { return (
-

Fiche d'informatino RGPD

+

Fiche d'information RGPD

1. Présentation du site

@@ -12,8 +12,8 @@ export default function RGPDPage() { Le présent site web est un outil de gestion des bénévoles permettant notamment :

    -
  • L’inscription et la gestion des profils bénévoles
  • -
  • L’organisation d’événements ou de missions
  • +
  • L'inscription et la gestion des profils bénévoles
  • +
  • L'organisation d'événements ou de missions
  • La communication avec les bénévoles
  • Le suivi des participations
@@ -33,15 +33,15 @@ export default function RGPDPage() {

2. Responsable du traitement

Le responsable du traitement des données personnelles est Monsieur FRÈRE Robin -
Il est responsable de la collecte et de l’utilisation des données personnelles conformément au Règlement Général sur la Protection des Données (RGPD – UE 2016/679). +
Il est responsable de la collecte et de l'utilisation des données personnelles conformément au Règlement Général sur la Protection des Données (RGPD – UE 2016/679).

3. Données personnelles collectées

-

Les données susceptibles d’être collectées sont notamment :

+

Les données susceptibles d'être collectées sont notamment :

    -
  • Les données d’identification : nom, prénom, adresse email et numéro de téléphone.
  • +
  • Les données d'identification : nom, prénom, adresse email et numéro de téléphone.
  • Les données techniques : adresse IP, données de connexion (logs) et type de navigateur et appareil.
@@ -63,8 +63,8 @@ export default function RGPDPage() {

5. Base légale du traitement

Les traitements reposent sur :

    -
  • Le consentement de l’utilisateur
  • -
  • L’intérêt légitime de l’organisme (gestion des bénévoles)
  • +
  • Le consentement de l'utilisateur
  • +
  • L'intérêt légitime de l'organisme (gestion des bénévoles)
  • Une obligation légale, le cas échéant
@@ -73,7 +73,7 @@ export default function RGPDPage() {

6. Durée de conservation

Les données sont conservées :

    -
  • Pendant la durée de l’engagement bénévole
  • +
  • Pendant la durée de l'engagement bénévole
  • Puis archivées ou supprimées au plus tard 3 ans après la dernière activité ou contact

Les logs techniques sont conservés pour une durée maximale de 2 mois.

@@ -83,10 +83,10 @@ export default function RGPDPage() {

7. Destinataires des données

Les données sont accessibles uniquement :

    -
  • Aux personnes habilitées de l’organisme
  • +
  • Aux personnes habilitées de l'organisme
  • Aux prestataires techniques (hébergement, maintenance), strictement nécessaires
-

Aucune donnée n’est vendue ou cédée à des tiers.

+

Aucune donnée n'est vendue ou cédée à des tiers.

@@ -96,7 +96,7 @@ export default function RGPDPage() {
  • Siège social : 2 rue Kellermann - 59100 Roubaix - France
  • Site web : www.ovh.com
  • -

    L’hébergeur garantit un niveau de sécurité conforme au RGPD.

    +

    L'hébergeur garantit un niveau de sécurité conforme au RGPD.

    @@ -113,11 +113,11 @@ export default function RGPDPage() {

    10. Droits des utilisateurs

    Conformément au RGPD, vous disposez des droits suivants :

      -
    • Droit d’accès à vos données
    • +
    • Droit d'accès à vos données
    • Droit de rectification
    • -
    • Droit à l’effacement (droit à l’oubli)
    • +
    • Droit à l'effacement (droit à l'oubli)
    • Droit à la limitation du traitement
    • -
    • Droit d’opposition
    • +
    • Droit d'opposition
    • Droit à la portabilité des données
    @@ -126,7 +126,7 @@ export default function RGPDPage() {

    11. Réclamation

    Si vous estimez que vos droits ne sont pas respectés, vous pouvez introduire une réclamation auprès de la : -
    CNIL – Commission Nationale de l’Informatique et des Libertés +
    CNIL – Commission Nationale de l'Informatique et des Libertés
    Site : https://www.cnil.fr

    @@ -140,4 +140,4 @@ export default function RGPDPage() {
    ); -} \ No newline at end of file +} From 51a1ee144019b80b6343cb5ba4cdb9c87b324ebd Mon Sep 17 00:00:00 2001 From: T'JAMPENS QUENTIN p2406187 Date: Wed, 18 Mar 2026 21:25:56 +0100 Subject: [PATCH 15/30] Convert RGPDPage to Typescript --- src/contexts/Auth/AuthContext.ts | 1 + src/interfaces/user.interface.ts | 1 + .../{WaitValidationPage.jsx => WaitValidationPage.tsx} | 6 +++--- 3 files changed, 5 insertions(+), 3 deletions(-) rename src/pages/WaitValidation/{WaitValidationPage.jsx => WaitValidationPage.tsx} (92%) diff --git a/src/contexts/Auth/AuthContext.ts b/src/contexts/Auth/AuthContext.ts index 79c8bfd..718bd7f 100644 --- a/src/contexts/Auth/AuthContext.ts +++ b/src/contexts/Auth/AuthContext.ts @@ -6,6 +6,7 @@ export interface AuthContextType { loading: boolean; update: () => void; login: (email: string, password: string) => Promise<{ status: number }>; + logout: () => Promise; } diff --git a/src/interfaces/user.interface.ts b/src/interfaces/user.interface.ts index a2de519..dbfa4fa 100644 --- a/src/interfaces/user.interface.ts +++ b/src/interfaces/user.interface.ts @@ -9,6 +9,7 @@ export default interface User { phone: string | null; created_at: string; isAdmin: boolean; + validate: number; tasks: TaskType[]; profile_photo_path?: string | null; } \ No newline at end of file diff --git a/src/pages/WaitValidation/WaitValidationPage.jsx b/src/pages/WaitValidation/WaitValidationPage.tsx similarity index 92% rename from src/pages/WaitValidation/WaitValidationPage.jsx rename to src/pages/WaitValidation/WaitValidationPage.tsx index 2972391..1480cb7 100644 --- a/src/pages/WaitValidation/WaitValidationPage.jsx +++ b/src/pages/WaitValidation/WaitValidationPage.tsx @@ -1,5 +1,5 @@ import styles from "./WaitValidationPage.module.css" -import Background from "../../components/Background/Background.jsx"; +import Background from "../../components/Background/Background"; import Button from "../../components/ui/Button/Button"; import { useContext } from "react"; import { AuthContext } from "../../contexts/Auth/AuthContext.js"; @@ -7,7 +7,7 @@ import { Navigate, useNavigate, Link } from "react-router"; export default function WaitValidationPage() { - const { logout, user } = useContext(AuthContext); + const { logout, user } = useContext(AuthContext)!; const navigate = useNavigate(); const handleLogout = async () => { @@ -38,4 +38,4 @@ export default function WaitValidationPage() {
    -} \ No newline at end of file +} From 39be6f25c6cce97ca23f2a84a21ccd0d15dc5aa4 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Thu, 19 Mar 2026 09:01:01 +0100 Subject: [PATCH 16/30] logout after delete the user and redirect to login page --- src/pages/Profile/components/SettingsModal/SettingsModal.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/pages/Profile/components/SettingsModal/SettingsModal.tsx b/src/pages/Profile/components/SettingsModal/SettingsModal.tsx index f152857..6d8e9de 100644 --- a/src/pages/Profile/components/SettingsModal/SettingsModal.tsx +++ b/src/pages/Profile/components/SettingsModal/SettingsModal.tsx @@ -8,6 +8,7 @@ import TextInput from "../../../../components/ui/Input/Input"; import updateUser from "../../../../utils/users/updateUser.js"; import deleteUser from "../../../../utils/users/deleteUser.js"; import ExportCalendarBtn from "../../../../components/ExportCalendarBtn/ExportBtn"; +import { useNavigate } from "react-router-dom"; interface TaskType { id: number; @@ -36,6 +37,7 @@ interface AuthContextType { } export default function SettingsModal() { + const navigate = useNavigate(); const {user, logout, update} = useContext(AuthContext) as unknown as AuthContextType; const [open, setOpen] = useState(false); @@ -57,6 +59,8 @@ export default function SettingsModal() { const handleDelete = async (): Promise => { await deleteUser(); + logout(); + navigate('/'); update(); }; From 544c782e8404d2d0a8f884a2c8d546e44f9b8c5c Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Thu, 19 Mar 2026 10:04:58 +0100 Subject: [PATCH 17/30] fix broadcast name --- src/components/Header/Header.tsx | 4 ++-- .../{userCreatedListener.js => adminNotificationsListener.js} | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/utils/echo/listeners/{userCreatedListener.js => adminNotificationsListener.js} (78%) diff --git a/src/components/Header/Header.tsx b/src/components/Header/Header.tsx index ea8bf8c..a7188b9 100644 --- a/src/components/Header/Header.tsx +++ b/src/components/Header/Header.tsx @@ -5,7 +5,7 @@ import getUserNotifications from "../../utils/notifications/getUserNotifications import deleteNotificationUser from "../../utils/notifications/deleteNotificationUser.js"; import initEcho from "../../utils/echo/initEcho.js" import readNotifications from "../../utils/notifications/readNotifications.js"; -import { userCreatedListener } from "../../utils/echo/listeners/userCreatedListener"; +import { adminNotificationsListener } from "../../utils/echo/listeners/adminNotificationsListener"; import { userNotificationsListener } from "../../utils/echo/listeners/userNotificationsListener.js"; import NotificationCard from "../NotificationCard/NotificationCard"; import { EventContext } from "../../contexts/Events/EventContext.js"; @@ -44,7 +44,7 @@ function Header() { echoInstance = echo; const activeChannels: (string | null)[] = [ - userCreatedListener(echo, user, setNotifications, setunreadNotification, updatePendingMembers), + adminNotificationsListener(echo, user, setNotifications, setunreadNotification, updatePendingMembers), userNotificationsListener(echo, user, setNotifications, setunreadNotification), ]; channelsToLeave = activeChannels.filter((name): name is string => name !== null); diff --git a/src/utils/echo/listeners/userCreatedListener.js b/src/utils/echo/listeners/adminNotificationsListener.js similarity index 78% rename from src/utils/echo/listeners/userCreatedListener.js rename to src/utils/echo/listeners/adminNotificationsListener.js index a4a36c4..d9cc07c 100644 --- a/src/utils/echo/listeners/userCreatedListener.js +++ b/src/utils/echo/listeners/adminNotificationsListener.js @@ -1,6 +1,6 @@ -export const userCreatedListener = (echo, userData, setNotifications, setunreadNotification, updatePendingMembers) => { +export const adminNotificationsListener = (echo, userData, setNotifications, setunreadNotification, updatePendingMembers) => { if (userData.isAdmin) { - const channelName = "users.registration"; + const channelName = "users.admin"; echo.private(channelName) .listen(".users.registration", (event) => { const newNotification = { From a0c42b5e812bd1d17f78a96268686edef3901457 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Thu, 19 Mar 2026 16:40:53 +0100 Subject: [PATCH 18/30] remove duplicated notification handling code --- .../listeners/userNotificationsListener.js | 49 ++++++------------- 1 file changed, 16 insertions(+), 33 deletions(-) diff --git a/src/utils/echo/listeners/userNotificationsListener.js b/src/utils/echo/listeners/userNotificationsListener.js index 7d94483..7fa193d 100644 --- a/src/utils/echo/listeners/userNotificationsListener.js +++ b/src/utils/echo/listeners/userNotificationsListener.js @@ -1,46 +1,29 @@ -export const userNotificationsListener = (echo, userData, setNotifications, setunreadNotification) => { +export const userNotificationsListener = (echo, userData, setNotifications, setUnreadNotification) => { const channelName = `user.${userData.id}`; + const handleNotification = (content) => { + const newNotification = { + id: Date.now(), + content, + created_at: Date.now(), + pivot: { unread: 1 } + }; + setNotifications(prev => [newNotification, ...prev]); + setUnreadNotification(true); + }; + return echo.private(channelName) .listen('.event.participation.cancelled', (event) => { - const newNotification = { - id: Date.now(), - content: `L'événement ${event.event.name} a été supprimé ! Vous n'y participez donc plus.`, - created_at: Date.now(), - pivot: { unread: 1 } - }; - setNotifications(prev => [newNotification, ...prev]); - setunreadNotification(true); + handleNotification(`L'événement ${event.event.name} a été supprimé ! Vous n'y participez donc plus.`); }) .listen(`.task.participation.cancelled`, (event) => { - const newNotification = { - id: Date.now(), - content: `La tâche ${event.task.name} de l'événement ${event.event.name} a été supprimé ! Vous n'y participez donc plus.`, - created_at: Date.now(), - pivot: { unread: 1 } - }; - setNotifications(prev => [newNotification, ...prev]); - setunreadNotification(true); + handleNotification(`La tâche ${event.task.name} de l'événement ${event.event.name} a été supprimée !`); }) .listen('.volunteer.assigned.to.task', (event) => { - const newNotification = { - id: Date.now(), - content: `Vous avez été assigné à la tâche ${event.task.name} de l'événement ${event.event.name}`, - created_at: Date.now(), - pivot: { unread: 1 } - }; - setNotifications(prev => [newNotification, ...prev]); - setunreadNotification(true); + handleNotification(`Vous avez été assigné à la tâche ${event.task.name} de l'événement ${event.event.name}`); }) .listen('.volunteer.unassigned.to.task', (event) => { - const newNotification = { - id: Date.now(), - content: `Vous avez été désassigné de la tâche ${event.task.name} de l'événement ${event.event.name}`, - created_at: Date.now(), - pivot: { unread: 1 } - }; - setNotifications(prev => [newNotification, ...prev]); - setunreadNotification(true); + handleNotification(`Vous avez été désassigné de la tâche ${event.task.name} de l'événement ${event.event.name}`); }); }; \ No newline at end of file From dbed1148439dd1df793f046f23f247daad831a04 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Thu, 19 Mar 2026 16:42:09 +0100 Subject: [PATCH 19/30] remove duplicated notification handling code --- .../listeners/adminNotificationsListener.js | 23 +++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/utils/echo/listeners/adminNotificationsListener.js b/src/utils/echo/listeners/adminNotificationsListener.js index d9cc07c..7617b49 100644 --- a/src/utils/echo/listeners/adminNotificationsListener.js +++ b/src/utils/echo/listeners/adminNotificationsListener.js @@ -1,16 +1,21 @@ -export const adminNotificationsListener = (echo, userData, setNotifications, setunreadNotification, updatePendingMembers) => { +export const adminNotificationsListener = (echo, userData, setNotifications, setUnreadNotification, updatePendingMembers) => { if (userData.isAdmin) { const channelName = "users.admin"; + + const handleNotification = (content) => { + const newNotification = { + id: Date.now(), + content, + created_at: Date.now(), + pivot: { unread: 1 } + }; + setNotifications(prev => [newNotification, ...prev]); + setUnreadNotification(true); + }; + echo.private(channelName) .listen(".users.registration", (event) => { - const newNotification = { - id: Date.now(), - content: `Nouvelle demande d'inscription : ${event.user.name} ${event.user.lastname}`, - created_at: Date.now(), - pivot: { unread: 1 } - }; - setNotifications(prev => [newNotification, ...prev]); - setunreadNotification(true); + handleNotification(`Nouvelle demande d'inscription : ${event.user.name} ${event.user.lastname}`); updatePendingMembers(); }); return channelName; From 72d2cfae27a2a7aee1c3af58cc4954678329a18f Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Thu, 19 Mar 2026 16:58:21 +0100 Subject: [PATCH 20/30] resolve datetime conflict for notifications --- src/components/NotificationCard/NotificationCard.tsx | 2 +- src/utils/date/formatDate.ts | 4 +++- src/utils/date/formatTime.ts | 2 +- src/utils/echo/listeners/adminNotificationsListener.js | 2 +- src/utils/echo/listeners/userNotificationsListener.js | 7 ++++++- 5 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/components/NotificationCard/NotificationCard.tsx b/src/components/NotificationCard/NotificationCard.tsx index b1baa66..5412b0d 100644 --- a/src/components/NotificationCard/NotificationCard.tsx +++ b/src/components/NotificationCard/NotificationCard.tsx @@ -14,7 +14,7 @@ function NotificationCard({ notifications, deleteNotification }: NotificationCar
    - Le {formatDate(String(notification.created_at))} à {formatTime(String(notification.created_at))} + Le {formatDate(notification.created_at)} à {formatTime(notification.created_at)}
    +
    +

    Notifications

    + +
    +

    Notifications par email

    + +
    + +
    +

    Notifications sur le site

    + +
    +
    +

    Divers

    From c2b365b05fe1e6b3e20e93857036a807da60b803 Mon Sep 17 00:00:00 2001 From: Giovanni-Josserand Date: Thu, 26 Mar 2026 10:21:32 +0100 Subject: [PATCH 30/30] remove unecessary console.log() --- src/pages/Profile/ProfilePage.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/pages/Profile/ProfilePage.tsx b/src/pages/Profile/ProfilePage.tsx index a0e7664..5844adb 100644 --- a/src/pages/Profile/ProfilePage.tsx +++ b/src/pages/Profile/ProfilePage.tsx @@ -29,7 +29,6 @@ function ProfilePage() { useEffect(() => { (async () => { - console.log(JSON.stringify(import.meta.env.VITE_API_URL)); if (!isOwnProfile && id) { const res = await getUserById(Number(id)); if (res.status === 404) {