diff --git a/src/components/IncompleteEvent/IncompleteEvent.module.css b/src/components/IncompleteEvent/IncompleteEvent.module.css
index b3f1d70..cce5be6 100644
--- a/src/components/IncompleteEvent/IncompleteEvent.module.css
+++ b/src/components/IncompleteEvent/IncompleteEvent.module.css
@@ -27,7 +27,7 @@
list-style-type: circle;
}
-.eventsContainer::-webkit-scrollbar {
+/*.eventsContainer::-webkit-scrollbar {
height: 8px;
}
@@ -43,7 +43,7 @@
.eventsContainer::-webkit-scrollbar-thumb:hover {
background: rgba(30, 96, 249, 0.7);
-}
+}*/
.eventCard {
min-width: calc((100% - 20px) / 3);
diff --git a/src/components/PendingMembers/PendingMembers.jsx b/src/components/PendingMembers/PendingMembers.jsx
index 8b43ca1..828a056 100644
--- a/src/components/PendingMembers/PendingMembers.jsx
+++ b/src/components/PendingMembers/PendingMembers.jsx
@@ -1,8 +1,10 @@
-import React, { useState, useEffect } from "react";
+/*import React, { useState, useEffect } from "react";
import Button from "../ui/button/button";
import styles from "./PendingMembers.module.css";
import getInvalidUsers from "../../utils/users/getUserToValidate";
import getUserById from "../../utils/users/getUserById";
+import validateUser from "../../utils/users/validateUser";
+import deleteUser from "../../utils/users/deleteUser";
function pendingMembers() {
const [pendingMembers, setPendingMembers] = useState([]);
@@ -30,15 +32,31 @@ function pendingMembers() {
fetchPendingMembers();
}, []);
- const handleValidate = async (id) => {
- console.log(`Valider l'utilisateur ID: ${id}`);
- setPendingMembers(pendingMembers.filter(member => member.id !== id));
- };
+const handleReject = async (id) => {
+ const res = await deleteUser(id);
+
+ if (!res.ok) {
+ console.error(res.status, res.data);
+ alert(res.data?.message || "Action refusée");
+ return;
+ }
+
+ setPendingMembers(prev => prev.filter(u => u.id !== id));
+};
+
+const handleValidate = async (id) => {
+ const res = await validateUser(id);
+
+ if (!res.ok) {
+ alert(res.data?.message || "Validation refusée");
+ return;
+ }
+
+ setPendingMembers(prev => prev.filter(u => u.id !== id));
+};
+
+
- const handleReject = async (id) => {
- console.log(`Refuser l'utilisateur ID: ${id}`);
- setPendingMembers(pendingMembers.filter(member => member.id !== id));
- };
if (loading) {
return
Chargement des membres en attente...
;
@@ -65,4 +83,103 @@ function pendingMembers() {
);
}
-export default pendingMembers;
+export default pendingMembers;*/
+import React, { useState, useEffect } from "react";
+import Button from "../ui/button/button";
+import styles from "./PendingMembers.module.css";
+
+import getInvalidUsers from "../../utils/users/getUserToValidate";
+import getUserById from "../../utils/users/getUserById";
+import validateUser from "../../utils/users/validateUser";
+import deleteUser from "../../utils/users/deleteUser";
+
+function PendingMembers() {
+ const [pendingMembers, setPendingMembers] = useState([]);
+ const [loading, setLoading] = useState(true);
+
+ useEffect(() => {
+ const fetchPendingMembers = async () => {
+ setLoading(true);
+
+ const userIds = await getInvalidUsers();
+
+ if (userIds && userIds.length > 0) {
+ const users = await Promise.all(
+ userIds.map((id) => getUserById(id))
+ );
+ setPendingMembers(users.filter(Boolean));
+ } else {
+ setPendingMembers([]);
+ }
+
+ setLoading(false);
+ };
+
+ fetchPendingMembers();
+ }, []);
+
+ const handleValidate = async (id) => {
+ const ok = await validateUser(id);
+
+ if (!ok) return;
+
+ setPendingMembers((prev) =>
+ prev.filter((member) => member.id !== id)
+ );
+ };
+
+ const handleReject = async (id) => {
+ const ok = await deleteUser(id);
+
+ if (!ok) return;
+
+ setPendingMembers((prev) =>
+ prev.filter((member) => member.id !== id)
+ );
+ };
+
+ if (loading) {
+ return Chargement des membres en attente...
;
+ }
+
+ return (
+
+
Membres en attente de validation
+
+
+ {pendingMembers.length === 0 && (
+
Aucun membre en attente
+ )}
+
+ {pendingMembers.map((member) => (
+
+
+ {member.name} {member.lastname}
+
+
+
+
+
+
+
+
+ ))}
+
+
+ );
+}
+
+export default PendingMembers;
diff --git a/src/components/PendingMembers/PendingMembers.module.css b/src/components/PendingMembers/PendingMembers.module.css
index 9eaef39..c87d933 100644
--- a/src/components/PendingMembers/PendingMembers.module.css
+++ b/src/components/PendingMembers/PendingMembers.module.css
@@ -18,7 +18,7 @@
}
-.membersContainer::-webkit-scrollbar {
+/*.membersContainer::-webkit-scrollbar {
width: 8px;
}
@@ -34,7 +34,7 @@
.membersContainer::-webkit-scrollbar-thumb:hover {
background: rgba(125, 249, 30, 0.7);
-}
+}*/
.memberCard {
display: flex;
diff --git a/src/components/chart/ParticipationChart.jsx b/src/components/chart/ParticipationChart.jsx
index 7ebd731..cfee6da 100644
--- a/src/components/chart/ParticipationChart.jsx
+++ b/src/components/chart/ParticipationChart.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+/*import React, { useState } from "react";
import { Doughnut } from "react-chartjs-2";
import { Chart, ArcElement } from "chart.js";
import { MenuItem, Select, FormControl } from "@mui/material";
@@ -87,4 +87,83 @@ function participationChart() {
);
}
-export default participationChart;
+export default participationChart;*/
+import React, { useState } from "react";
+import { Doughnut } from "react-chartjs-2";
+import { Chart, ArcElement } from "chart.js";
+import { MenuItem, Select, FormControl } from "@mui/material";
+import styles from "./ParticipationChart.module.css";
+
+Chart.register(ArcElement);
+
+function ParticipationChart() {
+ const [selected, setSelected] = useState("3");
+ const [participationRate, setParticipationRate] = useState(78);
+
+ const chartData = {
+ labels: ["Progress", "Background"],
+ datasets: [
+ {
+ data: [participationRate, 100 - participationRate],
+ backgroundColor: ["#1e60f9ff", "#ffffffff"],
+ borderWidth: 0,
+ weight: 10,
+ cutout: "93%",
+ circumference: 360,
+ rotation: -90,
+ },
+ ],
+ };
+
+ const chartOptions = {
+ responsive: true,
+ maintainAspectRatio: true,
+ plugins: {
+ legend: { display: false },
+ tooltip: { enabled: false },
+ },
+ animation: {
+ animateScale: true,
+ animateRotate: true,
+ },
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
{participationRate}%
+
+
+
+ );
+}
+
+export default ParticipationChart;
+
diff --git a/src/components/chart/ParticipationChart.module.css b/src/components/chart/ParticipationChart.module.css
index 7fa3515..0da2f5c 100644
--- a/src/components/chart/ParticipationChart.module.css
+++ b/src/components/chart/ParticipationChart.module.css
@@ -3,15 +3,18 @@
display: flex;
flex-direction: column;
align-items: center;
- height: calc(100vh - 260px);
- /* Exemple: calc(100vh - 60px) */
- margin-bottom: auto;
+ height: 100%;
+ min-height: calc(100vh - 260px);
+ box-sizing: border-box;
+ padding: 20px;
+ margin: 0;
}
.participationHeader {
display: flex;
align-items: center;
width: 100%;
+ margin-bottom: 10px;
}
.partiText {
@@ -27,14 +30,15 @@
.partiText label {
font-size: 20px;
- text-align: right;
+ text-align: center;
transition: all 0.3s ease;
+ width: 100%;
}
-
.chartContainer {
- max-width: 80%;
- width: 400px;
+ width: 80%;
+ max-width: 400px;
height: auto;
+ aspect-ratio: 1/1;
margin: 0 auto;
position: relative;
animation: slideEvent2 2s;
@@ -59,12 +63,70 @@
color: #333;
}
+.formControl {
+ display: flex;
+ justify-content: center;
+ width: 100%;
+ margin-top: 10px;
+}
+
+.formDesign {
+ margin: 0 auto;
+ width: fit-content;
+}
+
+.selectRoot {
+ width: 100px;
+ height: 35px;
+ font-size: 19px;
+ border:none;
+}
+
+.selectRoot .MuiOutlinedInput-notchedOutline {
+ border: none;
+}
+
+.selectRoot .MuiSelect-select {
+ padding: 8px;
+ padding-right: 24px;
+}
+
+.selectRoot .MuiSvgIcon-root {
+ font-size: 20px;
+}
+
+.selectRoot .MuiMenu-paper {
+ border-radius: 7px;
+ width: 100px;
+ max-width: 100px;
+}
+
+.selectRoot .MuiMenuItem-root {
+ font-size: 18px;
+}
+
+.selectMenuPaper {
+ border-radius: 7px;
+ width: 100px;
+ max-width: 120px;
+ max-height: 300px;
+ overflow-y: auto;
+ border:none;
+}
+
+.selectMenuItem {
+ font-size: 18px;
+ min-height: 40px;
+ display: flex;
+ align-items: center;
+}
+
+
@keyframes slideEvent2 {
from {
opacity: 0;
transform: translateX(-20px);
}
-
to {
opacity: 1;
transform: translateX(0);
@@ -76,45 +138,32 @@
opacity: 0;
transform: translateX(20px);
}
-
to {
opacity: 1;
transform: translateX(0);
}
}
-.formControl {
- display: flex;
- justify-content: center;
- width: 100%;
-}
-
-.formDesign {
- margin: 0 auto;
- width: fit-content;
-}
-
@media screen and (max-width: 760px) {
- .partiText {
- flex-direction: column;
- justify-content: center;
+ .leftBlock {
+ width: 100%;
+ height: auto;
+ min-height: auto;
+ margin-bottom: 20px;
+ }
+
+ .chartContainer {
+ width: 90%;
+ max-width: 300px;
+ height: auto;
+ aspect-ratio: 1/1;
}
.partiText label {
- text-align: center;
+ font-size: 18px;
}
- .leftBlock {
- width: 100%;
- display: flex;
- flex-direction: column;
- align-items: center;
- height: fit-content;
- margin-bottom: auto;
- margin-top: 30px;
+ .chartPercentage {
+ font-size: 48px;
}
- .chartContainer{
- height:fit-content;
- }
-
-}
\ No newline at end of file
+}
diff --git a/src/utils/users/deleteUser.js b/src/utils/users/deleteUser.js
index ff88d96..b8ae5b2 100644
--- a/src/utils/users/deleteUser.js
+++ b/src/utils/users/deleteUser.js
@@ -1,22 +1,14 @@
export default async function deleteUser(userId) {
- try {
- const res = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users/${userId}`, {
- method: 'DELETE',
- credentials: 'include',
+ const res = await fetch(
+ `http://${import.meta.env.VITE_API_URL}/api/users/${userId}`,
+ {
+ method: "DELETE",
+ credentials: "include",
headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json',
+ Accept: "application/json",
},
- });
-
- if (!res.ok) {
- throw new Error(`Erreur serveur : ${res.status}`);
}
+ );
- const data = await res.json();
- return data;
- } catch (err) {
- console.error('Erreur lors de la suppression :', err);
- return null;
- }
+ return res.ok;
}
diff --git a/src/utils/users/validateUser b/src/utils/users/validateUser
index f366a2b..f5611c8 100644
--- a/src/utils/users/validateUser
+++ b/src/utils/users/validateUser
@@ -1,22 +1,14 @@
export default async function validateUser(userId) {
- try {
- const res = await fetch(`http://${import.meta.env.VITE_API_URL}/api/users/${userId}/validate`, {
- method: 'POST',
- credentials: 'include',
+ const res = await fetch(
+ `http://${import.meta.env.VITE_API_URL}/api/users/${userId}/validate`,
+ {
+ method: "POST",
+ credentials: "include",
headers: {
- 'Accept': 'application/json',
- 'Content-Type': 'application/json',
+ Accept: "application/json",
},
- });
-
- if (!res.ok) {
- throw new Error(`Erreur serveur : ${res.status}`);
}
+ );
- const data = await res.json();
- return data;
- } catch (err) {
- console.error('Erreur lors de la validation :', err);
- return null;
- }
+ return res.ok;
}