diff --git a/src/components/Task/Task.module.css b/src/components/Task/Task.module.css index 052d0a3..b8489f6 100644 --- a/src/components/Task/Task.module.css +++ b/src/components/Task/Task.module.css @@ -2,7 +2,6 @@ width: 100%; padding: 12px; margin-bottom: 10px; - border-radius: 8px; } .content { diff --git a/src/components/Task/Task.tsx b/src/components/Task/Task.tsx index 7c939b2..daf805d 100644 --- a/src/components/Task/Task.tsx +++ b/src/components/Task/Task.tsx @@ -52,7 +52,7 @@ const Task: React.FC = ({ task }) => { }, [task.events_id]); return ( -
+

diff --git a/src/pages/Admin/components/IncompleteEvent/IncompleteEvent.jsx b/src/pages/Admin/components/IncompleteEvent/IncompleteEvent.jsx index c7817d2..73b637c 100644 --- a/src/pages/Admin/components/IncompleteEvent/IncompleteEvent.jsx +++ b/src/pages/Admin/components/IncompleteEvent/IncompleteEvent.jsx @@ -11,7 +11,7 @@ function IncompleteEvent() {

Derniers événements

{events.map((event) => ( -
+

{event.name}

{new Date(event.start).toLocaleDateString("fr-FR")} - {new Date(event.end).toLocaleDateString("fr-FR")} diff --git a/src/pages/Admin/components/IncompleteEvent/IncompleteEvent.module.css b/src/pages/Admin/components/IncompleteEvent/IncompleteEvent.module.css index 85849fc..e9c76d2 100644 --- a/src/pages/Admin/components/IncompleteEvent/IncompleteEvent.module.css +++ b/src/pages/Admin/components/IncompleteEvent/IncompleteEvent.module.css @@ -29,17 +29,18 @@ transform: translateX(20px); animation: slideInEvent 1s ease forwards; flex-shrink: 0; + padding: 10px; } .eventCard ul { align-items: center; - margin-left: 8%; - padding-left: 15px; + margin-left: 5%; } .eventCard ul li { text-align: left; list-style-type: circle; + list-style: none; } .eventCard > h3 { diff --git a/src/pages/Admin/components/PendingMembers/PendingMembers.jsx b/src/pages/Admin/components/PendingMembers/PendingMembers.jsx index 5649826..d93714a 100644 --- a/src/pages/Admin/components/PendingMembers/PendingMembers.jsx +++ b/src/pages/Admin/components/PendingMembers/PendingMembers.jsx @@ -58,7 +58,7 @@ function PendingMembers() { {pendingMembers.map((member, index) => ( -

+

{member.name} {member.lastname}

diff --git a/src/pages/Home/HomePage.jsx b/src/pages/Home/HomePage.jsx index 3c0c5f4..1e2e3d9 100644 --- a/src/pages/Home/HomePage.jsx +++ b/src/pages/Home/HomePage.jsx @@ -1,6 +1,6 @@ import styles from "./HomePage.module.css"; import Calendar from "./components/Calendar/Calendar.jsx"; -import EventList from "./components/EventList/EventList.tsx"; +import EventList from "./components/EventList/EventList"; function HomePage() { diff --git a/src/pages/Home/components/Calendar/Calendar.jsx b/src/pages/Home/components/Calendar/Calendar.jsx index 5eeb584..53ba22a 100644 --- a/src/pages/Home/components/Calendar/Calendar.jsx +++ b/src/pages/Home/components/Calendar/Calendar.jsx @@ -4,10 +4,11 @@ import {formatDateLetterJS} from "../../../../utils/date/formatDateLetter.js"; import Button from "../../../../components/ui/Button/Button"; import {AuthContext} from "../../../../contexts/Auth/AuthContext.ts"; -function Calendar() { - +function +Calendar() { const { user } = useContext(AuthContext); + const calendarUrl = `${import.meta.env.VITE_API_URL}/api/export/ics/${user.id}`; const monthNames = [ "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", @@ -17,17 +18,17 @@ function Calendar() { const today = new Date(); const [currentMonth, setCurrentMonth] = useState(today.getMonth()); - const [currentYear] = useState(today.getFullYear()); + const [currentYear, setCurrentYear] = useState(today.getFullYear()); const [selectedDay, setSelectedDay] = useState(null); const eventsByDate = useMemo(() => { if (!user?.tasks) return {}; - return user.tasks.reduce((acc, task) => { - if (!task?.start) return acc; + return user.tasks.reduce((eventsByDate, task) => { + if (!task?.start) return eventsByDate; const dateKey = task.start.split(" ")[0]; - if (!acc[dateKey]) acc[dateKey] = []; - acc[dateKey].push(task); - return acc; + if (!eventsByDate[dateKey]) eventsByDate[dateKey] = []; + eventsByDate[dateKey].push(task); + return eventsByDate; }, {}); }, [user]); @@ -66,9 +67,31 @@ function Calendar() {
- +

{monthNames[currentMonth]} {currentYear}

- +
@@ -128,15 +151,18 @@ function Calendar() { )} )} - + > + Exporter + + ); diff --git a/src/pages/Home/components/Calendar/Calendar.module.css b/src/pages/Home/components/Calendar/Calendar.module.css index 81f529e..b70ac34 100644 --- a/src/pages/Home/components/Calendar/Calendar.module.css +++ b/src/pages/Home/components/Calendar/Calendar.module.css @@ -150,10 +150,22 @@ display: none; } -.exportbtn{ +.exportbox{ + width: 100%; + padding: 15px; margin-top: 16px; + display: flex; + align-items: center; } +.exportbtn { + display: flex; + align-items: center; + max-height: 30px; +} + + + @media (max-width: 768px) { .glassCard { width: 100%; diff --git a/src/pages/Home/components/EventList/EventList.module.css b/src/pages/Home/components/EventList/EventList.module.css index fe49f9f..7a39bf7 100644 --- a/src/pages/Home/components/EventList/EventList.module.css +++ b/src/pages/Home/components/EventList/EventList.module.css @@ -68,9 +68,12 @@ h2{ } .eventTasks { - display: flex; - flex-direction: row; - justify-content: space-between; + list-style: none; + margin: 10px; +} + +.taskDate{ + font-size: 13px; } @media (max-width: 768px) { diff --git a/src/pages/Login/LoginPage.jsx b/src/pages/Login/LoginPage.jsx index fae6422..d49724e 100644 --- a/src/pages/Login/LoginPage.jsx +++ b/src/pages/Login/LoginPage.jsx @@ -1,5 +1,5 @@ import styles from "./LoginPage.module.css"; -import LoginForm from "./components/LoginForm/LoginForm.tsx"; +import LoginForm from "./components/LoginForm/LoginForm"; import Background from "../../components/Background/Background.jsx"; import { useEffect, useContext } from "react"; import { AuthContext } from "../../contexts/Auth/AuthContext.js"; diff --git a/src/pages/Profile/ProfilePage.tsx b/src/pages/Profile/ProfilePage.tsx index 91688a1..9ec3b79 100644 --- a/src/pages/Profile/ProfilePage.tsx +++ b/src/pages/Profile/ProfilePage.tsx @@ -15,20 +15,20 @@ 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; - }; + 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; + }; } @@ -51,149 +51,162 @@ interface AuthContextType { } function ProfilePage() { - const navigate = useNavigate(); - const { id } = useParams(); - const { user, update } = useContext(AuthContext) as AuthContextType; - const [profileUser, setProfileUser] = useState(null); - const [profilePicture, setProfilePicture] = useState(null); - const [error, setError] = useState(null); - const [success, setSuccess] = useState(null); - const fileInputRef = useRef(null); + const navigate = useNavigate(); + const {id} = useParams(); + const {user, update} = useContext(AuthContext) as AuthContextType; + const [profileUser, setProfileUser] = useState(null); + const [profilePicture, setProfilePicture] = useState(null); + const [error, setError] = useState(null); + const [success, setSuccess] = useState(null); + const fileInputRef = useRef(null); - const isOwnProfile = !id || user?.id.toString() === id; + const isOwnProfile = !id || user?.id.toString() === id; - useEffect(() => { - (async () => { - console.log(JSON.stringify(import.meta.env.VITE_API_URL)); - if (!isOwnProfile && id) { - const res = await getUserById(id); - if (res.status === 404) { - navigate("/404"); - return; + useEffect(() => { + (async () => { + if (!isOwnProfile && id) { + 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; + } + setProfileUser(res.data); + } else { + update(); + setProfileUser(user); + if (user?.profile_photo_path) { + setProfilePicture(`${import.meta.env.VITE_API_URL}/storage/${user.profile_photo_path}`); + } + } + })(); + }, [user, id]); + + const handleEditPictureClick = () => { + if (fileInputRef.current) { + fileInputRef.current.click(); } - if (res.status !== 200) { - console.error("Erreur lors du chargement du profil", res); - return; + }; + + // Remplacé : handleFileChange extrait vers utils/users/uploadProfilePhoto + const handleFileChange = async (e: React.ChangeEvent) => { + const file = e.target.files?.[0]; + if (!file) return; + + try { + const res = await uploadProfilePhoto(file); + if (res.ok) { + setProfilePicture(`${import.meta.env.VITE_API_URL}/storage/${res.data.profile_photo_path}`); + setSuccess("Photo mise à jour !"); + setError(null); + await update(); + } else { + setError(res.data?.message || res.error || "Erreur lors de l'upload."); + setSuccess(null); + } + } catch (err) { + setError("Erreur réseau."); + setSuccess(null); } - setProfileUser(res.data); - } else { - //update(); - setProfileUser(user); - if (user?.profile_photo_path) { - setProfilePicture(`${import.meta.env.VITE_API_URL}/storage/${user.profile_photo_path}`); - //setProfilePicture(`${import.meta.env.VITE_API_URL}/${user.profile_photo_path}`); + }; + + // Remplacé : handleDeletePicture extrait vers utils/users/deleteProfilePhoto + const handleDeletePicture = async () => { + try { + const res = await deleteProfilePhoto(); + if (res.status >= 200 && res.status < 300) { + setProfilePicture(null); + setSuccess("Photo supprimée !"); + setError(null); + await update(); + } else { + setError(res.data?.message || "Erreur lors de la suppression."); + setSuccess(null); + } + } catch (err) { + setError("Erreur réseau."); + setSuccess(null); } - } - })(); - }, [user, id]); + }; - const handleEditPictureClick = () => { - if (fileInputRef.current) { - fileInputRef.current.click(); - } - }; + return ( +
+
+
+
+ Photo de profil +
- const handleFileChange = async (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; + {isOwnProfile && ( +
+ + {user?.profile_photo_path && ( + + )} +
+ )} - try { - const res = await uploadProfilePhoto(file); - if (res.ok) { - setProfilePicture(`${import.meta.env.VITE_API_URL}/storage/${res.data.profile_photo_path}`); - //setProfilePicture(`${import.meta.env.VITE_API_URL}/${res.data.profile_photo_path}`); - setSuccess("Photo mise à jour !"); - setError(null); - await update(); - } else { - setError(res.data?.message || res.error || "Erreur lors de l'upload."); - setSuccess(null); - } - } catch (err) { - setError("Erreur réseau."); - setSuccess(null); - } - }; - const handleDeletePicture = async () => { - - deleteProfilePhoto(); - setProfilePicture(null); - }; + + {error &&

{error}

} + {success &&

{success}

} - return ( -
-
-
-
- Photo de profil -
+
+
+

+ {profileUser?.name} {profileUser?.lastname} +

+ {user?.isAdmin && profileUser && !isOwnProfile && ( + + )} +
- {isOwnProfile && ( -
- - {user?.profile_photo_path && ( - - )} -
- )} +
+
+

Role : {profileUser?.role}

+

Membre depuis : {profileUser && formatDate(profileUser.created_at)} +

+
- - {error &&

{error}

} - {success &&

{success}

} +
+

Mail : {profileUser?.email}

+

Téléphone : {profileUser?.phone ?? "Non renseigné"}

+
-
-
-

- {profileUser?.name} {profileUser?.lastname} -

- {user?.isAdmin && profileUser && !isOwnProfile && ( - - )} -
+ {isOwnProfile && ( +
+ +
+ )} +
-
-
-

Role : {profileUser?.role}

-

Membre depuis : {profileUser && formatDate(profileUser.created_at)}

-
- -
-

Mail : {profileUser?.email}

-

Téléphone : {profileUser?.phone ?? "Non renseigné"}

-
- - {isOwnProfile && ( -
- +

Tâches :

+ {profileUser?.tasks.length ? ( + profileUser.tasks.map((task) =>) + ) : ( +

Aucune tâche.

+ )} +
- )}
- -

Tâches :

- {profileUser?.tasks.length ? ( - profileUser.tasks.map((task) => ) - ) : ( -

Aucune tâche.

- )} -
-
-
- ); + ); } export default ProfilePage; \ No newline at end of file