@@ -185,3 +328,26 @@ export default function SettingsModal() {
>
);
}
+=======
+
setIsDelete(false)}
+ >
+
+
+ Êtes vous vraiment sûr de vouloir supprimer votre compte ?
+
+
+
+
+ >
+ );
+}
+>>>>>>> dev
diff --git a/src/pages/VolunteerProfile/components/manageMember/ManageMember.jsx b/src/pages/Profile/components/manageMember/ManageMember.jsx
similarity index 100%
rename from src/pages/VolunteerProfile/components/manageMember/ManageMember.jsx
rename to src/pages/Profile/components/manageMember/ManageMember.jsx
diff --git a/src/pages/VolunteerProfile/components/manageMember/deactivateMember/deactivateMemberBtn.jsx b/src/pages/Profile/components/manageMember/deactivateMember/deactivateMemberBtn.jsx
similarity index 100%
rename from src/pages/VolunteerProfile/components/manageMember/deactivateMember/deactivateMemberBtn.jsx
rename to src/pages/Profile/components/manageMember/deactivateMember/deactivateMemberBtn.jsx
diff --git a/src/pages/VolunteerProfile/components/manageMember/manageMember.module.css b/src/pages/Profile/components/manageMember/manageMember.module.css
similarity index 100%
rename from src/pages/VolunteerProfile/components/manageMember/manageMember.module.css
rename to src/pages/Profile/components/manageMember/manageMember.module.css
diff --git a/src/pages/VolunteerProfile/components/manageMember/modifyrole/ModifyRole.jsx b/src/pages/Profile/components/manageMember/modifyrole/ModifyRole.jsx
similarity index 100%
rename from src/pages/VolunteerProfile/components/manageMember/modifyrole/ModifyRole.jsx
rename to src/pages/Profile/components/manageMember/modifyrole/ModifyRole.jsx
diff --git a/src/pages/VolunteerProfile/VolunteerProfilePage.jsx b/src/pages/VolunteerProfile/VolunteerProfilePage.jsx
deleted file mode 100644
index 763b7f7..0000000
--- a/src/pages/VolunteerProfile/VolunteerProfilePage.jsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import styles from "./VolunteerProfilePage.module.css";
-import { useParams, useNavigate } from "react-router";
-import { useEffect, useState, useContext } from "react";
-import getUserById from "../../utils/users/getUserById.js";
-import formatDate from "../../utils/date/formatDate.js";
-import Task from "../../components/Task/Task.jsx";
-import ManageMember from "./components/manageMember/ManageMember.jsx";
-import { AuthContext } from "../../contexts/auth/AuthContext.js";
-
-export default function VolunteerProfilePage() {
- const { id } = useParams();
- const navigate = useNavigate();
- const { user: currentUser } = useContext(AuthContext);
-
- const [user, setUser] = useState(null);
-
- useEffect(() => {
- (async () => {
- const res = await getUserById(id);
-
- if (res.status === 404) {
- navigate("/404");
- return;
- }
-
- if (res.status !== 200) {
- console.error("Erreur lors du chargement du profil", res);
- return;
- }
-
- setUser(res.data);
- })();
- }, [id, navigate]);
-
- if (!user) return null;
-
- return (
-
-
-
-
-

-
-
-
-
-
{user.name} {user.lastname}
- {currentUser?.isAdmin && (
-
- )}
-
-
-
-
-
Role : {user.role}
-
Membre depuis : {formatDate(user.created_at)}
-
-
-
Mail : {user.email}
-
- Téléphone :{" "}
- {user.phone ?? "Pas de numéro enregistré"}
-
-
-
-
-
Tâches :
- {user.tasks?.length > 0 ? (
- user.tasks.map((task, index) => (
-
- ))
- ) : (
-
Aucune tâche pour le moment.
- )}
-
-
-
-
- );
-}
diff --git a/src/pages/VolunteerProfile/VolunteerProfilePage.module.css b/src/pages/VolunteerProfile/VolunteerProfilePage.module.css
deleted file mode 100644
index 834af59..0000000
--- a/src/pages/VolunteerProfile/VolunteerProfilePage.module.css
+++ /dev/null
@@ -1,163 +0,0 @@
-.container {
- width: 100%;
- padding: 10px;
- box-sizing: border-box;
-}
-
-.profileboard {
- width: 100%;
- padding: 15px;
- border-radius: 20px;
- box-sizing: border-box;
-}
-
-.contentWrapper {
- display: flex;
- flex-direction: column;
- align-items: center;
- width: 100%;
-}
-
-.profilePictureContainer {
- width: 120px;
- height: 120px;
- margin-bottom: 15px;
-}
-
-.profilePicture {
- width: 100%;
- height: 100%;
- border-radius: 50%;
- object-fit: cover;
-}
-
-.description {
- width: 100%;
- text-align: left;
- margin-left:4%;
-}
-
-.topDescription {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 10px;
- margin-bottom: 15px;
-}
-
-.infoBlock {
- width: 100%;
- background: rgba(255, 255, 255, 0.1);
- padding: 10px;
- border-radius: 5px;
-}
-
-.eventTasks {
- max-height: 0;
- overflow: hidden;
- transition: max-height 0.3s ease-out, opacity 0.2s ease;
- opacity: 0;
- padding-left: 20px;
-}
-
-.eventTasks.expanded {
- max-height: 500px;
- opacity: 1;
- margin-top: 10px;
-}
-.description h2{
- font-size:30px;
-
-}
-.profilePicture{
- width:90%;
-}
-
-.settingsBtns {
- display: flex;
- gap: 5px;
- justify-content: right;
-}
-
-@media screen and (min-width: 768px) {
- .contentWrapper {
- flex-direction: row;
- justify-content: flex-start;
- align-items: flex-start;
- }
-
- .profilePictureContainer {
- width: 150px;
- height: 150px;
- margin-right: 20px;
- margin-bottom: 0;
- }
-
- .description {
- width: calc(100% - 170px);
- margin-left:4%;
- }
-
- .topDescription {
- flex-direction: row;
- justify-content: space-between;
- }
-
- .infoBlock {
- width: 48%;
- }
-
- .event {
- padding: 15px;
- }
- .description h2{
- font-size:30px;
- }
- .profilePicture{
- width:90%;
- }
-}
-.description button{
- width:50px;
- height:50px;
-
-}
-
-.headerProfile {
- display: flex;
- flex-direction: row;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
-}
-
-@media screen and (min-width: 1024px) {
- .container {
- max-width: 100%;
- margin: 0 auto;
- padding: 20px;
- }
-
- .profileboard {
- padding: 25px;
- }
-
- .profilePictureContainer {
- width: 30%;
- height:auto;
- }
- .profilePicture{
- width:90%;
- }
- .description {
- width: calc(100% - 200px);
- margin-left:4%;
- }
-
- .event {
- padding: 18px;
- }
- .description h2{
- font-size:30px;
- }
-}
diff --git a/src/pages/Volunteers/VolunteerCard.jsx b/src/pages/Volunteers/VolunteerCard.jsx
deleted file mode 100644
index f69f6df..0000000
--- a/src/pages/Volunteers/VolunteerCard.jsx
+++ /dev/null
@@ -1,78 +0,0 @@
-import React, {useState} from "react";
-import styles from "./VolunteersPage.module.css";
-import formatDate from "../../utils/date/formatDate.js";
-import { useNavigate } from "react-router";
-import Button from "../../components/ui/button/button.tsx";
-
-export default function VolunteerCard({ user }) {
-
- const [isExpanded, setIsExpanded] = useState(false);
-
- const toggleExpand = () => {
- setIsExpanded(!isExpanded);
- };
-
- const navigate = useNavigate();
-
- return (
-
setIsExpanded(!isExpanded))}>
-
-
-
- {user?.name}{" "}
- {user?.lastname}
-
-
-
-
-
-
- {!isExpanded ? (
-
-
Rôle : {user?.role}
-
Membre depuis : {user?.created_at && formatDate(user.created_at)}
-
- ) : (
-
-
-

-
-
-
-
-
Rôle : {user?.role}
-
Membre depuis : {user?.created_at && formatDate(user.created_at)}
-
-
-
-
Email : {user?.email}
- {user?.phone &&
Téléphone : {user.phone}
}
-
-
-
- )}
-
-
- {isExpanded && (
-
-
-
- )}
-
-
- );
-
-
-
-}
\ No newline at end of file
diff --git a/src/pages/Volunteers/VolunteersPage.jsx b/src/pages/Volunteers/VolunteersPage.jsx
deleted file mode 100644
index 169275a..0000000
--- a/src/pages/Volunteers/VolunteersPage.jsx
+++ /dev/null
@@ -1,53 +0,0 @@
-import { useState, useEffect } from "react";
-import styles from "./VolunteersPage.module.css";
-import VolunteerCard from "./VolunteerCard.jsx";
-import getAllUser from "../../utils/users/getAllUsers.js";
-import ToolBar from "../../components/ToolBar/ToolBar.jsx";
-import filter from "../../utils/filter.js";
-import getUserById from "../../utils/users/getUserById.js";
-
-function VolunteerPage() {
- const [filters, setFilters] = useState({
- alphabetical: "asc",
- yearOrder: "desc",
- });
- const [users, setUsers] = useState([]);
-
- useEffect(() => {
- (async () => {
- const result = await getAllUser();
-
- if (result.status !== 200 || !Array.isArray(result.data)) {
- console.error("Erreur lors du chargement des utilisateurs", result);
- return;
- }
-
- const usersData = await Promise.all(
- result.data.map(async (id) => {
- const res = await getUserById(id);
-
- if (res.status === 200) {
- return res.data;
- }
- console.warn(`Utilisateur ${id} non récupéré`, res.status);
- return null;
- })
- );
-
- setUsers(usersData.filter(Boolean));
- })();
- }, []);
-
- return (
-
-
-
- {filter(users, filters, "user").map((user, index) => (
-
- ))}
-
-
- );
-}
-
-export default VolunteerPage;
diff --git a/src/pages/Volunteers/VolunteersPage.module.css b/src/pages/Volunteers/VolunteersPage.module.css
index 6ef455b..b953cb5 100644
--- a/src/pages/Volunteers/VolunteersPage.module.css
+++ b/src/pages/Volunteers/VolunteersPage.module.css
@@ -3,33 +3,18 @@
position: relative;
padding: 10px;
}
-.userName {
- display: flex;
- gap: 5px;
- font-weight: bold;
- font-size: 1rem;
- overflow: hidden;
-}
-
-.firstName {
- white-space: nowrap;
- flex-shrink: 0;
-}
-
-.lastName {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- flex-shrink: 1;
- max-width: 100px;
-}
.usersList {
- display: flex;
- flex-direction: column;
- align-items: center;
- gap: 10px;
+ display: grid;
+ gap: 16px;
+ width: 100%;
+ grid-template-columns: 1fr;
}
+
+.usersList > * {
+ min-width: 0;
+}
+
.profileboard {
width: 100%;
max-width: 380px;
@@ -140,12 +125,23 @@
}
}
+.loading {
+ width: 100%;
+ text-align: center;
+ font-size: 1.1rem;
+ opacity: 1;
+ color: white;
+}
+
@media screen and (min-width: 1024px) {
.container {
padding: 20px;
}
.usersList {
gap: 20px;
+ grid-template-columns: repeat(3, 1fr);
+ padding-right: 5em;
+ padding-left: 5em;
}
.profileboard {
max-width: 700px;
diff --git a/src/pages/Volunteers/VolunteersPage.tsx b/src/pages/Volunteers/VolunteersPage.tsx
new file mode 100644
index 0000000..ae43fbc
--- /dev/null
+++ b/src/pages/Volunteers/VolunteersPage.tsx
@@ -0,0 +1,81 @@
+import { useEffect, useState } from "react";
+import styles from "./VolunteersPage.module.css";
+import VolunteerCard from "./components/VolunteersCard/VolunteerCard";
+import getAllUser from "../../utils/users/getAllUsers";
+import ToolBar from "../../components/ToolBar/ToolBar";
+import filter from "../../utils/filter";
+import getUserById from "../../utils/users/getUserById";
+import User from "./interfaces/user.interface";
+import Loading from "../../components/ui/loading/loading";
+
+interface Filters {
+ alphabetical: "asc" | "desc";
+ yearOrder: "asc" | "desc";
+}
+
+const VolunteerPage: React.FC = () => {
+ const [filters, setFilters] = useState
({
+ alphabetical: "asc",
+ yearOrder: "desc",
+ });
+
+ const [users, setUsers] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ const fetchUsers = async (): Promise => {
+ setLoading(true);
+
+ try {
+ const result = await getAllUser();
+
+ if (result.status !== 200 || !Array.isArray(result.data)) {
+ console.error("Erreur lors du chargement des utilisateurs", result);
+ return;
+ }
+
+ const usersData = await Promise.all(
+ result.data.map(async (id: number): Promise => {
+ const res = await getUserById(id);
+
+ if (res.status === 200) {
+ return res.data as User;
+ }
+
+ console.warn(`Utilisateur ${id} non récupéré`, res.status);
+ return null;
+ })
+ );
+
+ setUsers(usersData.filter((user): user is User => user !== null));
+ } catch (error) {
+ console.error("Erreur réseau", error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ fetchUsers();
+ }, []);
+
+ if(loading) return ;
+
+ return (
+
+
+
+
+ {filter(users, filters, "user").map((user: User) => (
+
+ ))}
+
+
+
+ );
+};
+
+export default VolunteerPage;
diff --git a/src/pages/Volunteers/components/VolunteersCard/VolunteerCard.tsx b/src/pages/Volunteers/components/VolunteersCard/VolunteerCard.tsx
new file mode 100644
index 0000000..a3d5f01
--- /dev/null
+++ b/src/pages/Volunteers/components/VolunteersCard/VolunteerCard.tsx
@@ -0,0 +1,29 @@
+import styles from "./VolunteersCard.module.css";
+import { useNavigate } from "react-router";
+import Button from "../../../../components/ui/button/button";
+import User from "../../interfaces/user.interface"
+
+
+interface VolunteersCardProps {
+ user: User;
+}
+
+export default function VolunteerCard({ user }: VolunteersCardProps) {
+
+ const navigate = useNavigate();
+
+ const handleNavigate = (): void => { navigate(`/profile/${user.id}`) }
+
+ return (
+
+
+

+
{user.name} {user.lastname}
+
+
+
+ );
+}
diff --git a/src/pages/Volunteers/components/VolunteersCard/VolunteersCard.module.css b/src/pages/Volunteers/components/VolunteersCard/VolunteersCard.module.css
new file mode 100644
index 0000000..4ed1ccf
--- /dev/null
+++ b/src/pages/Volunteers/components/VolunteersCard/VolunteersCard.module.css
@@ -0,0 +1,47 @@
+.volunteerCard {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.header {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ min-width: 0;
+}
+
+.header p {
+ flex: 1;
+ min-width: 0;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.content {
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ min-width: 0;
+}
+
+.content p {
+ flex: 1;
+ min-width: 0;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.content button {
+ flex-shrink: 0;
+}
+
+.profilePicture {
+ background-color: #1d1d1f;
+ border-radius: 20px;
+ width: 40px;
+ height: 40px;
+ flex-shrink: 0;
+}
diff --git a/src/pages/Volunteers/interfaces/task.interface.ts b/src/pages/Volunteers/interfaces/task.interface.ts
new file mode 100644
index 0000000..b6206c9
--- /dev/null
+++ b/src/pages/Volunteers/interfaces/task.interface.ts
@@ -0,0 +1,16 @@
+export default interface Task {
+ 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;
+ }
+}
\ No newline at end of file
diff --git a/src/pages/Volunteers/interfaces/user.interface.ts b/src/pages/Volunteers/interfaces/user.interface.ts
new file mode 100644
index 0000000..e22a1cd
--- /dev/null
+++ b/src/pages/Volunteers/interfaces/user.interface.ts
@@ -0,0 +1,16 @@
+import Task from "./task.interface";
+
+export default interface User {
+ id: number;
+ name: string;
+ lastname: string;
+ email: string;
+ role: string;
+ isAdmin: boolean;
+ phone: string | null;
+ created_at: string;
+ updated_at: string;
+ verified_at: string | null;
+ validate: number;
+ tasks: Task[];
+}
\ No newline at end of file
diff --git a/src/router.js b/src/router.js
index b9137b0..662f8f8 100644
--- a/src/router.js
+++ b/src/router.js
@@ -3,12 +3,11 @@ import Layout from "./layout.jsx";
import HomePage from "./pages/Home/HomePage";
import LoginPage from "./pages/Login/LoginPage";
import RegisterPage from "./pages/Register/RegisterPage.jsx";
-import VolunteersPage from "./pages/Volunteers/VolunteersPage";
+import VolunteersPage from "./pages/Volunteers/VolunteersPage.tsx";
import ProfilePage from "./pages/Profile/ProfilePage";
import EventsPage from "./pages/Events/EventsPage.jsx";
import AdminPage from "./pages/Admin/AdminPage.jsx";
import ValidationErrorPage from "./pages/waitValidationPage/ValidationErrorPage.jsx";
-import VolunteerProfilePage from "./pages/VolunteerProfile/VolunteerProfilePage.jsx";
import PageNotFound from "./pages/PageNotFound/PageNotFound.jsx";
import eventDetail from "./pages/eventDetail/eventDetail.jsx";
import legalNotices from "./pages/LegalNotices/LegalNotices.jsx";
@@ -47,10 +46,6 @@ const router = createBrowserRouter([
path: "/admin",
Component:AdminPage,
},
- {
- path:"/profile",
- Component:ProfilePage,
- },
{
path: "/events",
Component: EventsPage,
@@ -59,9 +54,13 @@ const router = createBrowserRouter([
path: "/volunteers",
Component: VolunteersPage,
},
+ {
+ path:"/profile",
+ Component:ProfilePage,
+ },
{
path: "/profile/:id",
- Component: VolunteerProfilePage,
+ Component: ProfilePage,
},
{
path: "/events/:id",
diff --git a/src/stories/Loading.stories.jsx b/src/stories/Loading.stories.jsx
new file mode 100644
index 0000000..6986aa8
--- /dev/null
+++ b/src/stories/Loading.stories.jsx
@@ -0,0 +1,13 @@
+import Loading from "../components/ui/loading/loading.tsx";
+
+
+export default {
+ title: 'UI/Loading',
+ component: Loading,
+ parameters: {
+ layout: 'centered',
+ },
+ tags: ['autodocs'],
+};
+
+export const Primary = {};
\ No newline at end of file
diff --git a/src/utils/echo/initEcho.js b/src/utils/echo/initEcho.js
index 9d27b37..4e59d4b 100644
--- a/src/utils/echo/initEcho.js
+++ b/src/utils/echo/initEcho.js
@@ -14,8 +14,31 @@ export default function initEcho() {
encrypted: import.meta.env.VITE_ENCRYPTED === 'true',
cluster: import.meta.env.VITE_CLUSTER,
enabledTransports: ['ws', 'wss'],
+ authorizer: (channel) => {
+ return {
+ authorize: (socketId, callback) => {
+ fetch(`${import.meta.env.VITE_API_URL}/broadcasting/auth`, {
+ method: 'POST',
+ credentials: 'include',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'X-Requested-With': 'XMLHttpRequest',
+ },
+ body: JSON.stringify({
+ socket_id: socketId,
+ channel_name: channel.name,
+ }),
+ })
+ .then(res => res.json())
+ .then(data => callback(null, data))
+ .catch(err => callback(err, null));
+ },
+ };
+ },
});
+
+
window.Echo = echoInstance;
return echoInstance;
}
diff --git a/src/utils/echo/listeners/userCreatedListener.js b/src/utils/echo/listeners/userCreatedListener.js
index e2bb017..a4a36c4 100644
--- a/src/utils/echo/listeners/userCreatedListener.js
+++ b/src/utils/echo/listeners/userCreatedListener.js
@@ -1,4 +1,4 @@
-export const userCreatedListener = (echo, userData, setNotifications, setunreadNotification) => {
+export const userCreatedListener = (echo, userData, setNotifications, setunreadNotification, updatePendingMembers) => {
if (userData.isAdmin) {
const channelName = "users.registration";
echo.private(channelName)
@@ -11,6 +11,7 @@ export const userCreatedListener = (echo, userData, setNotifications, setunreadN
};
setNotifications(prev => [newNotification, ...prev]);
setunreadNotification(true);
+ updatePendingMembers();
});
return channelName;
}