From edd81b66de3754d9e7afc100ea730692ab89de17 Mon Sep 17 00:00:00 2001 From: p2405951 Date: Tue, 3 Mar 2026 12:30:32 +0100 Subject: [PATCH] fix inline code with ProfilePicture --- src/pages/Profile/ProfilePage.module.css | 16 -- src/pages/Profile/ProfilePage.tsx | 36 ++-- .../SettingsModal/SettingsModal.tsx | 186 ------------------ src/utils/users/deleteProfilePhoto.ts | 10 + src/utils/users/replaceProfilePhoto.ts | 5 + src/utils/users/uploadProfilePhoto.ts | 28 +++ 6 files changed, 56 insertions(+), 225 deletions(-) create mode 100644 src/utils/users/deleteProfilePhoto.ts create mode 100644 src/utils/users/replaceProfilePhoto.ts create mode 100644 src/utils/users/uploadProfilePhoto.ts diff --git a/src/pages/Profile/ProfilePage.module.css b/src/pages/Profile/ProfilePage.module.css index 7c2a179..2bcecee 100644 --- a/src/pages/Profile/ProfilePage.module.css +++ b/src/pages/Profile/ProfilePage.module.css @@ -7,12 +7,6 @@ } .profileboard { -<<<<<<< HEAD - width: 100%; - padding: 16px; - border-radius: 20px; - box-sizing: border-box; -======= width: 100%; padding: 16px; border-radius: 20px; @@ -23,7 +17,6 @@ display: flex; justify-content: center; align-items: center; ->>>>>>> dev } .contentWrapper { @@ -91,14 +84,6 @@ margin-bottom: 16px; } -<<<<<<< HEAD -.headerProfile h2 { - font-size: 1.6rem; - margin: 0; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; -======= .description h2 { font-size: 1.6rem; margin-bottom: 10px; @@ -126,7 +111,6 @@ height: 22px; display: block; margin: 0; ->>>>>>> dev } /* Conteneur des informations principales */ diff --git a/src/pages/Profile/ProfilePage.tsx b/src/pages/Profile/ProfilePage.tsx index fe8b82a..eddae6a 100644 --- a/src/pages/Profile/ProfilePage.tsx +++ b/src/pages/Profile/ProfilePage.tsx @@ -1,5 +1,5 @@ import getXSRFToken from "../../utils/getXSRF.js"; -import fetchWrapper from "../../utils/fetchWrapper"; +// import fetchWrapper from "../../utils/fetchWrapper"; import {useContext, useEffect, useState} from "react"; import styles from "./ProfilePage.module.css"; import {AuthContext} from "../../contexts/auth/AuthContext"; @@ -12,6 +12,9 @@ import {useRef} from "react"; import getUserById from "../../utils/users/getUserById.js"; import ManageMember from "./components/manageMember/ManageMember.jsx"; +import uploadProfilePhoto from "../../utils/users/uploadProfilePhoto"; +import deleteProfilePhoto from "../../utils/users/deleteProfilePhoto.js"; + interface TaskType { id: number; @@ -61,7 +64,6 @@ function ProfilePage() { const isOwnProfile = !id || user?.id.toString() === id; - // Charger le profil de l'utilisateur (soi-même ou un autre) useEffect(() => { (async () => { if (!isOwnProfile && id) { @@ -85,38 +87,26 @@ function ProfilePage() { })(); }, [user, id]); - // Fonctions pour la photo de profil (uniquement si c'est le profil de l'utilisateur connecté) const handleEditPictureClick = () => { if (fileInputRef.current) { fileInputRef.current.click(); } }; + // Remplacé : handleFileChange extrait vers utils/users/uploadProfilePhoto const handleFileChange = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; - const formData = new FormData(); - formData.append("photo", file); - try { - const csrfToken = await getXSRFToken(); - const response = await fetch(`${import.meta.env.VITE_API_URL}/api/profile-photo`, { - method: "POST", - headers: { "X-XSRF-TOKEN": decodeURIComponent(csrfToken) }, - credentials: "include", - body: formData, - }); - - if (response.ok) { - const data = await response.json(); - setProfilePicture(`${import.meta.env.VITE_API_URL}/storage/${data.profile_photo_path}`); + 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 { - const errorData = await response.json(); - setError(errorData.message || "Erreur lors de l'upload."); + setError(res.data?.message || res.error || "Erreur lors de l'upload."); setSuccess(null); } } catch (err) { @@ -125,17 +115,17 @@ function ProfilePage() { } }; + // Remplacé : handleDeletePicture extrait vers utils/users/deleteProfilePhoto const handleDeletePicture = async () => { try { - const response = await fetchWrapper("/api/profile-photo", null, "DELETE"); - if (response.status >= 200 && response.status < 300) { + const res = await deleteProfilePhoto(); + if (res.status >= 200 && res.status < 300) { setProfilePicture(null); setSuccess("Photo supprimée !"); setError(null); await update(); } else { - const errorData = response.data; - setError(errorData.message || "Erreur lors de la suppression."); + setError(res.data?.message || "Erreur lors de la suppression."); setSuccess(null); } } catch (err) { diff --git a/src/pages/Profile/components/SettingsModal/SettingsModal.tsx b/src/pages/Profile/components/SettingsModal/SettingsModal.tsx index 4c2e7b1..e028735 100644 --- a/src/pages/Profile/components/SettingsModal/SettingsModal.tsx +++ b/src/pages/Profile/components/SettingsModal/SettingsModal.tsx @@ -1,58 +1,3 @@ -<<<<<<< HEAD -/*import Modal from "../../../../components/ui/modal/modal.jsx"; -import Button from "../../../../components/ui/button/button.jsx"; -import styles from "./SettingsModal.module.css" -import { useContext, useState } from "react"; -import ThemeSwitcher from "../../../../components/ui/themeSwitcher/ThemeSwitcher.jsx"; -import { AuthContext } from "../../../../contexts/auth/AuthContext.js"; -import TextInput from "../../../../components/ui/input/input.jsx"; -import updateUser from "../../../../utils/users/updateUser.js"; -import deleteUser from "../../../../utils/users/deleteUser.js"; - - -export default function SettingsModal() { - - const { user, logout, update } = useContext(AuthContext); - - const [open, setOpen] = useState(false); - const [isDelete, setIsDelete] = useState(false); - - const [name, setName] = useState(user?.name); - const [lastname, setLastName] = useState(user?.lastname); - const [phone, setPhone] = useState(user?.phone); - - const handleLogout = () => { - logout(); - } - - const handleSubmit = async () => { - await updateUser(name, lastname, phone); - update(); - } - - const handleDelete = async () => { - await deleteUser(); - update(); - } - - return ( - <> - - - setOpen(false)}> -
- -
-

Compte

- - - -
-

Changer de Prénom

- setName(e.target.value)} type={"text"} /> -======= import {useContext, useState, ChangeEvent} from "react"; import Modal from "../../../../components/ui/modal/modal"; import Button from "../../../../components/ui/button/button"; @@ -164,31 +109,19 @@ export default function SettingsModal() { onChange={handleNameChange} type="text" /> ->>>>>>> dev

Changer de nom

-<<<<<<< HEAD - setLastName(e.target.value)} type={"text"} /> -======= ->>>>>>> dev

Changer de numéro de téléphone

-<<<<<<< HEAD - setPhone(e.target.value)} type={"text"} /> -
- - - -======= Confirmer ->>>>>>> dev

Apparence

-<<<<<<< HEAD - -======= ->>>>>>> dev
-<<<<<<< HEAD - - setIsDelete(false)}> -
-

Êtes vous vraiment sûr de vouloir supprimer votre compte ?

- -
-
- - ) -}*/ - -import Modal from "../../../../components/ui/modal/modal"; -import Button from "../../../../components/ui/button/button"; -import styles from "./SettingsModal.module.css"; -import { useContext, useState } from "react"; -import ThemeSwitcher from "../../../../components/ui/themeSwitcher/ThemeSwitcher"; -import { AuthContext } from "../../../../contexts/auth/AuthContext"; -import TextInput from "../../../../components/ui/input/input"; -import updateUser from "../../../../utils/users/updateUser"; -import deleteUser from "../../../../utils/users/deleteUser"; - -interface User { - name: string; - lastname: string; - phone: string | null; -} - -interface AuthContextType { - user: User | null; - logout: () => void; - update: () => void; -} - -export default function SettingsModal() { - const { user, logout, update } = useContext(AuthContext) as AuthContextType; - - const [open, setOpen] = useState(false); - const [isDelete, setIsDelete] = useState(false); - const [name, setName] = useState(user?.name || ""); - const [lastname, setLastName] = useState(user?.lastname || ""); - const [phone, setPhone] = useState(user?.phone || null); - - const handleLogout = () => { - logout(); - }; - - const handleSubmit = async () => { - await updateUser(name, lastname, phone); - update(); - }; - - const handleDelete = async () => { - await deleteUser(); - update(); - }; - - return ( - <> - - - setOpen(false)}> -
-
-

Compte

- - - -
-

Changer de Prénom

- setName(e.target.value)} type={"text"} /> -
- -
-

Changer de nom

- setLastName(e.target.value)} type={"text"} /> -
- -
-

Changer de numéro de téléphone

- setPhone(e.target.value)} type={"text"} /> -
- - -
- -
-

Apparence

- -
-
-
- - setIsDelete(false)}> -
-

Êtes-vous vraiment sûr de vouloir supprimer votre compte ?

- -
-
- - ); -} -======= ); } ->>>>>>> dev diff --git a/src/utils/users/deleteProfilePhoto.ts b/src/utils/users/deleteProfilePhoto.ts new file mode 100644 index 0000000..d0ca642 --- /dev/null +++ b/src/utils/users/deleteProfilePhoto.ts @@ -0,0 +1,10 @@ +import fetchWrapper from "../fetchWrapper"; + +export default async function deleteProfilePhoto(): Promise<{ status: number; ok: boolean; data?: any; error?: string }> { + try { + const response = await fetchWrapper("/api/profile-photo", null, "DELETE"); + return { status: response.status || 0, ok: response.status >= 200 && response.status < 300, data: response.data }; + } catch (err: any) { + return { status: 0, ok: false, error: err?.message || "Network error" }; + } +} diff --git a/src/utils/users/replaceProfilePhoto.ts b/src/utils/users/replaceProfilePhoto.ts new file mode 100644 index 0000000..92569eb --- /dev/null +++ b/src/utils/users/replaceProfilePhoto.ts @@ -0,0 +1,5 @@ +import uploadProfilePhoto from "./uploadProfilePhoto"; + +export default async function replaceProfilePhoto(file: File) { + return uploadProfilePhoto(file); +} diff --git a/src/utils/users/uploadProfilePhoto.ts b/src/utils/users/uploadProfilePhoto.ts new file mode 100644 index 0000000..ca252a2 --- /dev/null +++ b/src/utils/users/uploadProfilePhoto.ts @@ -0,0 +1,28 @@ +import getXSRFToken from "../getXSRF.js"; + +export default async function uploadProfilePhoto(file: File): Promise<{ status: number; ok: boolean; data?: any; error?: string }> { + const formData = new FormData(); + formData.append("photo", file); + + try { + const csrfToken = await getXSRFToken(); + const response = await fetch(`${import.meta.env.VITE_API_URL}/api/profile-photo`, { + method: "POST", + headers: { "X-XSRF-TOKEN": decodeURIComponent(csrfToken) }, + credentials: "include", + body: formData, + }); + + const status = response.status; + let data = null; + try { + data = await response.json(); + } catch (e) { + // no json + } + + return { status, ok: response.ok, data }; + } catch (err: any) { + return { status: 0, ok: false, error: err?.message || "Network error" }; + } +}