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}
diff --git a/src/components/Footer/Footer.jsx b/src/components/Footer/Footer.tsx similarity index 80% rename from src/components/Footer/Footer.jsx rename to src/components/Footer/Footer.tsx index 881943e..a25704a 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 <> @@ -30,7 +30,7 @@ export default function Footer(){ Fiche RGPD - + Mentions légales @@ -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 +} diff --git a/src/components/Header/Header.jsx b/src/components/Header/Header.tsx similarity index 84% rename from src/components/Header/Header.jsx rename to src/components/Header/Header.tsx index bd4b821..ea8bf8c 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"; @@ -7,34 +7,35 @@ 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 { AuthContext } from "../../contexts/Auth/AuthContext.js"; import { PendingMembersContext } from "../../contexts/PendingMembers/PendingMembersContext"; +import Notification from "../../interfaces/notification.interface"; 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 +43,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 +56,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 +71,7 @@ function Header() { return () => { document.removeEventListener("mousedown", handleClickOutside); if (echoInstance) { - channelsToLeave.forEach(chan => echoInstance.leave(chan)); + channelsToLeave.forEach(chan => echoInstance!.leave(chan)); } }; }, []); @@ -93,7 +94,7 @@ function Header() { } - async function deleteNotification(notificationId) { + async function deleteNotification(notificationId: number) { try { const result = await deleteNotificationUser(notificationId); if (result) { @@ -194,4 +195,4 @@ function Header() { ); } -export default Header; \ No newline at end of file +export default 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 +} 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 +} 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 +} diff --git a/src/router.js b/src/router.js index 418bf47..e17bf44 100644 --- a/src/router.js +++ b/src/router.js @@ -10,7 +10,7 @@ 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.tsx"; -import legalNotices from "./pages/LegalNotices/LegalNoticesPage.jsx"; +import legalNotices from "./pages/LegalNotices/LegalNoticesPage.tsx"; import RGPDPage from "./pages/RGPD/RGPDPage.jsx"; const router = createBrowserRouter([