Merge branch 'refac/typescript' into dev
This commit is contained in:
+21
-16
@@ -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 (
|
||||
<div className={`${styles.backgroundContainer} ${className || ''} ${theme === "light" ? styles.backgroundLight : styles.backgroundDark}`}>
|
||||
<div
|
||||
ref={(el) => (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}
|
||||
></div>
|
||||
<div
|
||||
ref={(el) => (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}
|
||||
></div>
|
||||
<div
|
||||
ref={(el) => (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}
|
||||
></div>
|
||||
<div
|
||||
ref={(el) => (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}
|
||||
></div>
|
||||
<div
|
||||
ref={(el) => (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}
|
||||
></div>
|
||||
{children}
|
||||
</div>
|
||||
@@ -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<boolean>(false);
|
||||
|
||||
|
||||
return <>
|
||||
@@ -30,7 +30,7 @@ export default function Footer(){
|
||||
Fiche RGPD
|
||||
</Link>
|
||||
<span className={styles.separator}></span>
|
||||
<Link to="/legalNoticesPage" className={styles.link} onClick={scrollToTop}>
|
||||
<Link to="/legalNotices" className={styles.link} onClick={scrollToTop}>
|
||||
Mentions légales
|
||||
</Link>
|
||||
<span className={styles.separator}></span>
|
||||
@@ -48,11 +48,11 @@ export default function Footer(){
|
||||
<Modal title={"Réalisé par"} open={isCopyrightModal} onClose={() => setIsCopyrightModal(false)}>
|
||||
<section className={styles.section}>
|
||||
<div className={styles.inputContainer}>
|
||||
<p>Quentin T'jampens</p>
|
||||
<p>Antoine Ordonneau</p>
|
||||
<p>Malo Leblond</p>
|
||||
<p>Quentin T'JAMPENS</p>
|
||||
<p>Antoine ORDONNEAU</p>
|
||||
<p>Malo LEBLOND</p>
|
||||
<p>
|
||||
Giovanni Josserand (
|
||||
Giovanni JOSSERAND (
|
||||
<Link to={"https://linktree.josserand.ovh/"}>linktree</Link>
|
||||
)
|
||||
</p>
|
||||
@@ -60,4 +60,4 @@ export default function Footer(){
|
||||
</section>
|
||||
</Modal>
|
||||
</>
|
||||
}
|
||||
}
|
||||
@@ -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<boolean>(false);
|
||||
const [unreadNotification, setunreadNotification] = useState<boolean>(false);
|
||||
const [mobileMenu, setMobileMenu] = useState<boolean>(false);
|
||||
const [notifications, setNotifications] = useState<Notification[]>([]);
|
||||
const notificationRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
updateEvent();
|
||||
|
||||
let echoInstance = null;
|
||||
let channelsToLeave = [];
|
||||
let echoInstance: ReturnType<typeof initEcho> | 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;
|
||||
export default Header;
|
||||
+8
-4
@@ -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) => (
|
||||
<div className={styles.notificationCard} key={index}>
|
||||
<div className={styles.cardHeader}>
|
||||
<span className={styles.timeTag}>
|
||||
Le {formatDate(notification.created_at)} à {formatTime(notification.created_at)}
|
||||
Le {formatDate(String(notification.created_at))} à {formatTime(String(notification.created_at))}
|
||||
</span>
|
||||
<button
|
||||
className={styles.closeIconButton}
|
||||
@@ -31,4 +35,4 @@ function NotificationCard({notifications, deleteNotification}) {
|
||||
);
|
||||
}
|
||||
|
||||
export default NotificationCard;
|
||||
export default NotificationCard;
|
||||
@@ -1,9 +1,20 @@
|
||||
import styles from "./ToolBar.module.css"
|
||||
import CreateEventBtn from "./tools/CreateEventBtn/CreateEventBtn.jsx";
|
||||
import CreateEventBtn from "./tools/CreateEventBtn/CreateEventBtn";
|
||||
import SearchBtn from "./tools/SearchBtn";
|
||||
import FilterBtn from "./tools/FilterBtn";
|
||||
|
||||
function ToolBar({setFilters, filters, showCreate = true}) {
|
||||
interface Filters {
|
||||
alphabetical: "asc" | "desc";
|
||||
yearOrder: "asc" | "desc";
|
||||
}
|
||||
|
||||
interface ToolBarProps {
|
||||
setFilters: React.Dispatch<React.SetStateAction<Filters>>;
|
||||
filters: Filters;
|
||||
showCreate?: boolean;
|
||||
}
|
||||
|
||||
function ToolBar({ setFilters, filters, showCreate = true }: ToolBarProps) {
|
||||
|
||||
return (
|
||||
<div>
|
||||
@@ -16,4 +27,4 @@ function ToolBar({setFilters, filters, showCreate = true}) {
|
||||
);
|
||||
}
|
||||
|
||||
export default ToolBar;
|
||||
export default ToolBar;
|
||||
+9
-9
@@ -4,19 +4,19 @@ import Modal from "../../../ui/Modal/Modal";
|
||||
import Button from "../../../ui/Button/Button";
|
||||
import TextInput from "../../../ui/Input/Input";
|
||||
import { EventContext } from "../../../../contexts/Events/EventContext.js";
|
||||
import {AuthContext} from "../../../../contexts/Auth/AuthContext.ts";
|
||||
import { AuthContext } from "../../../../contexts/Auth/AuthContext";
|
||||
|
||||
|
||||
export default function CreateEventBtn() {
|
||||
|
||||
const { addEvent } = useContext(EventContext);
|
||||
const { user } = useContext(AuthContext);
|
||||
const { addEvent } = useContext(EventContext)!;
|
||||
const { user } = useContext(AuthContext)!;
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const [name, setName] = useState("");
|
||||
const [description, setDescription] = useState("");
|
||||
const [start, setStart] = useState("");
|
||||
const [end, setEnd] = useState("");
|
||||
const [isOpen, setIsOpen] = useState<boolean>(false);
|
||||
const [name, setName] = useState<string>("");
|
||||
const [description, setDescription] = useState<string>("");
|
||||
const [start, setStart] = useState<string>("");
|
||||
const [end, setEnd] = useState<string>("");
|
||||
|
||||
const handleCreateEvent = async () => {
|
||||
|
||||
@@ -62,4 +62,4 @@ export default function CreateEventBtn() {
|
||||
</section>
|
||||
</Modal>
|
||||
</>
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ export interface AuthContextType {
|
||||
loading: boolean;
|
||||
update: () => void;
|
||||
login: (email: string, password: string) => Promise<{ status: number }>;
|
||||
logout: () => Promise<void>;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ export type EventGroup = {
|
||||
|
||||
export type EventContextType = {
|
||||
events: EventGroup[];
|
||||
updateEvent: () => void;
|
||||
addEvent: (name: string, description: string, start: string, end: string) => Promise<void>;
|
||||
};
|
||||
|
||||
export const EventContext = createContext<EventContextType | null>(null);
|
||||
@@ -0,0 +1,6 @@
|
||||
export default interface Notification {
|
||||
id: number;
|
||||
content: string;
|
||||
created_at: string | number;
|
||||
pivot: { unread: number };
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
+1
-1
@@ -37,4 +37,4 @@ export default function legalNoticesPage() {
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -1,4 +1,4 @@
|
||||
import Background from "../../components/Background/Background.jsx";
|
||||
import Background from "../../components/Background/Background";
|
||||
import styles from "./PageNotFoundPage.module.css"
|
||||
import { useNavigate } from "react-router";
|
||||
import { APP_CONFIG } from "../../config/appConfig.js";
|
||||
@@ -12,14 +12,14 @@ export default function PageNotFoundPage() {
|
||||
<h1 className={styles.title}> Page non trouvée </h1>
|
||||
<div className={`${styles.container} glassCard`}>
|
||||
<p>
|
||||
Désolé, la page que vous recherchez n’existe pas ou n’est plus disponible. <br/>
|
||||
Désolé, la page que vous recherchez n'existe pas ou n'est plus disponible. <br/>
|
||||
Vous pouvez : <br/>
|
||||
- Vérifier l’URL pour une éventuelle erreur de saisie. <br/>
|
||||
- Revenir à l’accueil <span onClick={() => navigate("/")} className={styles.redirectSpan}>ici.</span> <br/>
|
||||
- Vérifier l'URL pour une éventuelle erreur de saisie. <br/>
|
||||
- Revenir à l'accueil <span onClick={() => navigate("/")} className={styles.redirectSpan}>ici.</span> <br/>
|
||||
|
||||
</p>
|
||||
<p> Contact : {APP_CONFIG.contactEmail} </p>
|
||||
</div>
|
||||
</div>
|
||||
</Background>
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ import {Link} from "react-router";
|
||||
export default function RGPDPage() {
|
||||
return (
|
||||
<div className={`${styles.RGPD} glassCard`}>
|
||||
<h1> Fiche d'informatino RGPD </h1>
|
||||
<h1> Fiche d'information RGPD </h1>
|
||||
|
||||
<section className={styles.section}>
|
||||
<h2 className={styles.h2}> 1. Présentation du site </h2>
|
||||
@@ -12,8 +12,8 @@ export default function RGPDPage() {
|
||||
Le présent site web est un outil de gestion des bénévoles permettant notamment :
|
||||
</p>
|
||||
<ul>
|
||||
<li>L’inscription et la gestion des profils bénévoles</li>
|
||||
<li>L’organisation d’événements ou de missions</li>
|
||||
<li>L'inscription et la gestion des profils bénévoles</li>
|
||||
<li>L'organisation d'événements ou de missions</li>
|
||||
<li>La communication avec les bénévoles</li>
|
||||
<li>Le suivi des participations</li>
|
||||
</ul>
|
||||
@@ -33,15 +33,15 @@ export default function RGPDPage() {
|
||||
<h2 className={styles.h2}>2. Responsable du traitement</h2>
|
||||
<p>
|
||||
Le responsable du traitement des données personnelles est Monsieur FRÈRE Robin
|
||||
<br />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).
|
||||
<br />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).
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section className={styles.section}>
|
||||
<h2 className={styles.h2}>3. Données personnelles collectées</h2>
|
||||
<p>Les données susceptibles d’être collectées sont notamment :</p>
|
||||
<p>Les données susceptibles d'être collectées sont notamment :</p>
|
||||
<ul>
|
||||
<li>Les données d’identification : nom, prénom, adresse email et numéro de téléphone.</li>
|
||||
<li>Les données d'identification : nom, prénom, adresse email et numéro de téléphone.</li>
|
||||
<li>Les données techniques : adresse IP, données de connexion (logs) et type de navigateur et appareil.</li>
|
||||
</ul>
|
||||
|
||||
@@ -63,8 +63,8 @@ export default function RGPDPage() {
|
||||
<h2 className={styles.h2}>5. Base légale du traitement</h2>
|
||||
<p>Les traitements reposent sur :</p>
|
||||
<ul>
|
||||
<li>Le consentement de l’utilisateur</li>
|
||||
<li>L’intérêt légitime de l’organisme (gestion des bénévoles)</li>
|
||||
<li>Le consentement de l'utilisateur</li>
|
||||
<li>L'intérêt légitime de l'organisme (gestion des bénévoles)</li>
|
||||
<li>Une obligation légale, le cas échéant</li>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -73,7 +73,7 @@ export default function RGPDPage() {
|
||||
<h2 className={styles.h2}>6. Durée de conservation</h2>
|
||||
<p>Les données sont conservées :</p>
|
||||
<ul>
|
||||
<li>Pendant la durée de l’engagement bénévole</li>
|
||||
<li>Pendant la durée de l'engagement bénévole</li>
|
||||
<li>Puis archivées ou supprimées au plus tard 3 ans après la dernière activité ou contact</li>
|
||||
</ul>
|
||||
<p>Les logs techniques sont conservés pour une durée maximale de 2 mois.</p>
|
||||
@@ -83,10 +83,10 @@ export default function RGPDPage() {
|
||||
<h2 className={styles.h2}>7. Destinataires des données</h2>
|
||||
<p>Les données sont accessibles uniquement :</p>
|
||||
<ul>
|
||||
<li>Aux personnes habilitées de l’organisme</li>
|
||||
<li>Aux personnes habilitées de l'organisme</li>
|
||||
<li>Aux prestataires techniques (hébergement, maintenance), strictement nécessaires</li>
|
||||
</ul>
|
||||
<p>Aucune donnée n’est vendue ou cédée à des tiers.</p>
|
||||
<p>Aucune donnée n'est vendue ou cédée à des tiers.</p>
|
||||
</section>
|
||||
|
||||
<section className={styles.section}>
|
||||
@@ -96,7 +96,7 @@ export default function RGPDPage() {
|
||||
<li>Siège social : 2 rue Kellermann - 59100 Roubaix - France</li>
|
||||
<li>Site web : <Link to={"www.ovh.com"}>www.ovh.com</Link></li>
|
||||
</ul>
|
||||
<p>L’hébergeur garantit un niveau de sécurité conforme au RGPD.</p>
|
||||
<p>L'hébergeur garantit un niveau de sécurité conforme au RGPD.</p>
|
||||
</section>
|
||||
|
||||
<section className={styles.section}>
|
||||
@@ -113,11 +113,11 @@ export default function RGPDPage() {
|
||||
<h2 className={styles.h2}>10. Droits des utilisateurs</h2>
|
||||
<p>Conformément au RGPD, vous disposez des droits suivants :</p>
|
||||
<ul>
|
||||
<li>Droit d’accès à vos données</li>
|
||||
<li>Droit d'accès à vos données</li>
|
||||
<li>Droit de rectification</li>
|
||||
<li>Droit à l’effacement (droit à l’oubli)</li>
|
||||
<li>Droit à l'effacement (droit à l'oubli)</li>
|
||||
<li>Droit à la limitation du traitement</li>
|
||||
<li>Droit d’opposition</li>
|
||||
<li>Droit d'opposition</li>
|
||||
<li>Droit à la portabilité des données</li>
|
||||
</ul>
|
||||
</section>
|
||||
@@ -126,7 +126,7 @@ export default function RGPDPage() {
|
||||
<h2 className={styles.h2}>11. Réclamation</h2>
|
||||
<p>
|
||||
Si vous estimez que vos droits ne sont pas respectés, vous pouvez introduire une réclamation auprès de la :
|
||||
<br /><strong>CNIL</strong> – Commission Nationale de l’Informatique et des Libertés
|
||||
<br /><strong>CNIL</strong> – Commission Nationale de l'Informatique et des Libertés
|
||||
<br />Site : <a href="https://www.cnil.fr" target="_blank" rel="noreferrer">https://www.cnil.fr</a>
|
||||
</p>
|
||||
</section>
|
||||
@@ -140,4 +140,4 @@ export default function RGPDPage() {
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -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() {
|
||||
</div>
|
||||
</div>
|
||||
</Background>
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -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([
|
||||
|
||||
Reference in New Issue
Block a user