Merge branch 'dev' into fixcss/event
merge dev into fixcss
This commit is contained in:
@@ -48,12 +48,18 @@ const RegisterMember: React.FC = () => {
|
||||
setOpen(true);
|
||||
}
|
||||
|
||||
const handleKeyDown = (e: React.KeyboardEvent) => {
|
||||
if (e.key === 'Enter') {
|
||||
handleCreate();
|
||||
}
|
||||
};
|
||||
|
||||
return <div className={`${styles.leftBlock} glassCard`}>
|
||||
<div className={styles.registerMemberHeader}>
|
||||
<h2>Enregister un bénévole</h2>
|
||||
</div>
|
||||
|
||||
<div className={styles.registerForm}>
|
||||
<div className={styles.registerForm} onKeyDown={handleKeyDown}>
|
||||
<TextInput placeholder={"Prenom"} type={"text"} value={name} onChange={e => setName(e.target.value)} />
|
||||
<TextInput placeholder={"Nom"} type={"text"} value={lastname} onChange={e => setLastName(e.target.value)} />
|
||||
<TextInput placeholder={"Adresse Email"} type={"email"} value={email} onChange={e => setEmail(e.target.value)} />
|
||||
|
||||
@@ -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 (
|
||||
<div className={styles.allContent}>
|
||||
<Calendar />
|
||||
<EventList />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default HomePage;
|
||||
@@ -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 <div className={styles.allContent}>
|
||||
<Calendar/>
|
||||
<EventList/>
|
||||
</div>
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
@@ -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 <Button className={styles.exportbtn}
|
||||
onClick={() => {
|
||||
window.open(
|
||||
`${APP_CONFIG.newCalendarURL}${calendarUrl}`
|
||||
);
|
||||
}}
|
||||
>
|
||||
Exporter
|
||||
</Button>
|
||||
}
|
||||
+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>
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
@@ -60,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) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import {useContext, useState, ChangeEvent} from "react";
|
||||
import {useContext, useState, ChangeEvent, useEffect} from "react";
|
||||
import Modal from "../../../../components/ui/Modal/Modal";
|
||||
import Button from "../../../../components/ui/Button/Button";
|
||||
import styles from "./SettingsModal.module.css";
|
||||
@@ -7,6 +7,11 @@ 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";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import toggleEmailNotifications from "../../../../utils/users/toggleEmailNotifications";
|
||||
import toggleWebNotifications from "../../../../utils/users/toggleWebNotifications";
|
||||
|
||||
|
||||
interface TaskType {
|
||||
id: number;
|
||||
@@ -25,7 +30,9 @@ interface User {
|
||||
phone: string | null;
|
||||
created_at: string;
|
||||
isAdmin: boolean;
|
||||
tasks: TaskType[];
|
||||
tasks: TaskType[],
|
||||
email_notifications: number,
|
||||
web_notifications: number;
|
||||
}
|
||||
|
||||
interface AuthContextType {
|
||||
@@ -35,6 +42,7 @@ interface AuthContextType {
|
||||
}
|
||||
|
||||
export default function SettingsModal() {
|
||||
const navigate = useNavigate();
|
||||
const {user, logout, update} = useContext(AuthContext) as unknown as AuthContextType;
|
||||
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
@@ -44,6 +52,9 @@ export default function SettingsModal() {
|
||||
const [lastname, setLastName] = useState<string>(user?.lastname ?? "");
|
||||
const [phone, setPhone] = useState<string>(user?.phone ?? "");
|
||||
|
||||
const [emailNotifications, setEmailNotifications] = useState<number>(user?.email_notifications ?? 0);
|
||||
const [webNotifications, setWebNotifications] = useState<number>(user?.web_notifications ?? 0);
|
||||
|
||||
const handleLogout = (): void => {
|
||||
logout();
|
||||
};
|
||||
@@ -56,6 +67,8 @@ export default function SettingsModal() {
|
||||
|
||||
const handleDelete = async (): Promise<void> => {
|
||||
await deleteUser();
|
||||
logout();
|
||||
navigate('/');
|
||||
update();
|
||||
};
|
||||
|
||||
@@ -71,6 +84,26 @@ export default function SettingsModal() {
|
||||
setPhone(e.target.value);
|
||||
};
|
||||
|
||||
const handleEmailToggle = async () => {
|
||||
try {
|
||||
await toggleEmailNotifications(user.id);
|
||||
setEmailNotifications(prev => prev === 0 ? 1 : 0);
|
||||
update();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
const handleWebToggle = async () => {
|
||||
try {
|
||||
await toggleWebNotifications(user.id);
|
||||
setWebNotifications(prev => prev === 0 ? 1 : 0);
|
||||
update();
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<>
|
||||
@@ -130,6 +163,34 @@ export default function SettingsModal() {
|
||||
<ThemeSwitcher/>
|
||||
</div>
|
||||
|
||||
<div className={`glassBorder ${styles.section}`}>
|
||||
<h3>Notifications</h3>
|
||||
|
||||
<div className={styles.test}>
|
||||
<h4>Notifications par email</h4>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={emailNotifications === 1}
|
||||
onChange={handleEmailToggle}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={styles.test}>
|
||||
<h4>Notifications sur le site</h4>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={webNotifications === 1}
|
||||
onChange={handleWebToggle}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div className={`glassBorder ${styles.section}`}>
|
||||
<h3>Divers</h3>
|
||||
<ExportCalendarBtn />
|
||||
</div>
|
||||
|
||||
<div className={`glassBorder ${styles.section}`}>
|
||||
<h3>Sécurité du compte</h3>
|
||||
|
||||
|
||||
@@ -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>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user