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 01/10] 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 02/10] 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 03/10] 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 04/10] 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 09/10] 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 10/10] 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 +}