diff --git a/frontend-prep/src/pages/User/ProfilePage.tsx b/frontend-prep/src/pages/User/ProfilePage.tsx index ef3fd2ee..6133d074 100644 --- a/frontend-prep/src/pages/User/ProfilePage.tsx +++ b/frontend-prep/src/pages/User/ProfilePage.tsx @@ -1,307 +1,433 @@ -import { useState, useEffect } from 'react'; -import { useNavigate } from 'react-router-dom'; -import Navbar from '../../components/Navbar'; -import { isUserAuthenticated, extractUsernameFromToken, getMyProfile, updateMyProfile, getTelegramStatus, generateTelegramLinkToken, unlinkTelegram } from '../../api/api'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; +import { useState, useEffect } from "react"; +import { useNavigate } from "react-router-dom"; +import Navbar from "../../components/Navbar"; import { - faUser, faMapMarkerAlt, faPhone, faCommentDots, - faSave, faCheckCircle, faExclamationTriangle, faPaperPlane, faUnlink, faTimes, faLock, -} from '@fortawesome/free-solid-svg-icons'; -import './ProfilePage.css'; + isUserAuthenticated, + extractUsernameFromToken, + getMyProfile, + updateMyProfile, + getTelegramStatus, + generateTelegramLinkToken, + unlinkTelegram, +} from "../../api/api"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { + faUser, + faMapMarkerAlt, + faPhone, + faCommentDots, + faSave, + faCheckCircle, + faExclamationTriangle, + faPaperPlane, + faUnlink, + faTimes, + faLock, +} from "@fortawesome/free-solid-svg-icons"; +import "./ProfilePage.css"; -const STORAGE_ADDRESS = 'profile_default_address'; -const STORAGE_PHONE = 'profile_default_phone'; -const STORAGE_SIGNAL = 'profile_signal_pseudo'; +const STORAGE_ADDRESS = "profile_default_address"; +const STORAGE_PHONE = "profile_default_phone"; +const STORAGE_SIGNAL = "profile_signal_pseudo"; export default function ProfilePage() { - const navigate = useNavigate(); + const navigate = useNavigate(); - // Données compte (backend) - const [nom, setNom] = useState(''); - const [prenom, setPrenom] = useState(''); - const [telephone, setTelephone] = useState(''); - const [loadingProfile, setLoadingProfile] = useState(true); + // Données compte (backend) + const [nom, setNom] = useState(""); + const [prenom, setPrenom] = useState(""); + const [telephone, setTelephone] = useState(""); + const [loadingProfile, setLoadingProfile] = useState(true); - // Données locales (localStorage) - const [defaultAddress, setDefaultAddress] = useState(() => localStorage.getItem(STORAGE_ADDRESS) ?? ''); - const [defaultPhone, setDefaultPhone] = useState(() => localStorage.getItem(STORAGE_PHONE) ?? ''); - const [signalPseudo, setSignalPseudo] = useState(() => localStorage.getItem(STORAGE_SIGNAL) ?? ''); - - // Feedback - const [savingContact, setSavingContact] = useState(false); - const [successMsg, setSuccessMsg] = useState(''); - const [errorMsg, setErrorMsg] = useState(''); - - // Telegram - const [tgLinked, setTgLinked] = useState(false); - const [tgEnabled, setTgEnabled] = useState(false); - const [tgLoading, setTgLoading] = useState(false); - - // Modal confirmation infos par défaut - const [showSaveModal, setShowSaveModal] = useState(false); - - const username = extractUsernameFromToken() ?? ''; - - useEffect(() => { - if (!isUserAuthenticated()) { - navigate('/login/client', { replace: true }); - return; - } - // Statut Telegram - getTelegramStatus().then((s) => { setTgLinked(s.linked); setTgEnabled(s.enabled); }); - - // Charger depuis backend - getMyProfile().then((res) => { - if (res.success && res.client) { - setNom(res.client.nom ?? ''); - setPrenom(res.client.prenom ?? ''); - setTelephone(res.client.telephone ?? ''); - // Initialiser le téléphone par défaut si pas encore défini - if (!localStorage.getItem(STORAGE_PHONE) && res.client.telephone) { - setDefaultPhone(res.client.telephone); - } - } - setLoadingProfile(false); - }); - }, [navigate]); - - const showSuccess = (msg: string) => { - setSuccessMsg(msg); - setErrorMsg(''); - setTimeout(() => setSuccessMsg(''), 3000); - }; - const showError = (msg: string) => { - setErrorMsg(msg); - setSuccessMsg(''); - setTimeout(() => setErrorMsg(''), 4000); - }; - - const saveLocal = () => { - localStorage.setItem(STORAGE_ADDRESS, defaultAddress.trim()); - localStorage.setItem(STORAGE_PHONE, defaultPhone.trim()); - localStorage.setItem(STORAGE_SIGNAL, signalPseudo.trim()); - setShowSaveModal(false); - showSuccess('Informations par défaut enregistrées'); - }; - - const handleLinkTelegram = async () => { - setTgLoading(true); - const res = await generateTelegramLinkToken(); - setTgLoading(false); - if (res.error || !res.link_url) { - showError(res.error || 'Service Telegram non disponible'); - return; - } - window.open(res.link_url, '_blank'); - }; - - const handleUnlinkTelegram = async () => { - if (!window.confirm('Délier votre compte Telegram ? Vous ne recevrez plus de notifications.')) return; - await unlinkTelegram(); - setTgLinked(false); - showSuccess('Compte Telegram délié'); - }; - - const saveContact = async () => { - setSavingContact(true); - const res = await updateMyProfile({ nom: nom.trim(), prenom: prenom.trim(), telephone: telephone.trim() }); - setSavingContact(false); - if (res.success) { - showSuccess('Profil mis à jour'); - } else { - showError(res.message ?? 'Erreur lors de la mise à jour'); - } - }; - - if (loadingProfile) { - return ( - <> - -
-
-
- + // Données locales (localStorage) + const [defaultAddress, setDefaultAddress] = useState( + () => localStorage.getItem(STORAGE_ADDRESS) ?? "", + ); + const [defaultPhone, setDefaultPhone] = useState( + () => localStorage.getItem(STORAGE_PHONE) ?? "", + ); + const [signalPseudo, setSignalPseudo] = useState( + () => localStorage.getItem(STORAGE_SIGNAL) ?? "", ); - } - return ( - <> - -
-
-
- -
-
-

Mon Profil

-

@{username}

-
-
+ // Feedback + const [savingContact, setSavingContact] = useState(false); + const [successMsg, setSuccessMsg] = useState(""); + const [errorMsg, setErrorMsg] = useState(""); - {successMsg && ( -
- {successMsg} -
- )} - {errorMsg && ( -
- {errorMsg} -
- )} + // Telegram + const [tgLinked, setTgLinked] = useState(false); + const [tgEnabled, setTgEnabled] = useState(false); + const [tgLoading, setTgLoading] = useState(false); - {/* Section compte */} -
-

- - Mon compte -

-
-
-
- - setPrenom(e.target.value)} - placeholder="Votre prénom" - /> -
-
- - setNom(e.target.value)} - placeholder="Votre nom" - /> -
+ // Modal confirmation infos par défaut + const [showSaveModal, setShowSaveModal] = useState(false); + + const username = extractUsernameFromToken() ?? ""; + + useEffect(() => { + if (!isUserAuthenticated()) { + navigate("/login/client", { replace: true }); + return; + } + // Statut Telegram + getTelegramStatus().then((s) => { + setTgLinked(s.linked); + setTgEnabled(s.enabled); + }); + + // Charger depuis backend + getMyProfile().then((res) => { + if (res.success && res.client) { + setNom(res.client.nom ?? ""); + setPrenom(res.client.prenom ?? ""); + setTelephone(res.client.telephone ?? ""); + // Initialiser le téléphone par défaut si pas encore défini + if ( + !localStorage.getItem(STORAGE_PHONE) && + res.client.telephone + ) { + setDefaultPhone(res.client.telephone); + } + } + setLoadingProfile(false); + }); + }, [navigate]); + + const showSuccess = (msg: string) => { + setSuccessMsg(msg); + setErrorMsg(""); + setTimeout(() => setSuccessMsg(""), 3000); + }; + const showError = (msg: string) => { + setErrorMsg(msg); + setSuccessMsg(""); + setTimeout(() => setErrorMsg(""), 4000); + }; + + const saveLocal = () => { + localStorage.setItem(STORAGE_ADDRESS, defaultAddress.trim()); + localStorage.setItem(STORAGE_PHONE, defaultPhone.trim()); + localStorage.setItem(STORAGE_SIGNAL, signalPseudo.trim()); + setShowSaveModal(false); + showSuccess("Informations par défaut enregistrées"); + }; + + const handleLinkTelegram = async () => { + setTgLoading(true); + + // ✅ Ouvrir AVANT le await + const newWindow = window.open("", "_blank"); + + const res = await generateTelegramLinkToken(); + setTgLoading(false); + + if (res.error || !res.link_url) { + newWindow?.close(); + showError(res.error || "Service Telegram non disponible"); + return; + } + + const isIOS = /iPad|iPhone|iPod/.test(navigator.userAgent); + + if (isIOS) { + const botUsername = res.link_url.split("t.me/")[1]?.split("?")[0]; + const token = new URL(res.link_url).searchParams.get("start"); + newWindow!.location.href = `tg://resolve?domain=${botUsername}&start=${token}`; + setTimeout(() => { + newWindow!.location.href = res.link_url!; + }, 1500); + } else { + newWindow!.location.href = res.link_url; + } + }; + + const handleUnlinkTelegram = async () => { + if ( + !window.confirm( + "Délier votre compte Telegram ? Vous ne recevrez plus de notifications.", + ) + ) + return; + await unlinkTelegram(); + setTgLinked(false); + showSuccess("Compte Telegram délié"); + }; + + const saveContact = async () => { + setSavingContact(true); + const res = await updateMyProfile({ + nom: nom.trim(), + prenom: prenom.trim(), + telephone: telephone.trim(), + }); + setSavingContact(false); + if (res.success) { + showSuccess("Profil mis à jour"); + } else { + showError(res.message ?? "Erreur lors de la mise à jour"); + } + }; + + if (loadingProfile) { + return ( + <> + +
+
+
+
+
+ + ); + } + + return ( + <> + +
+
+
+ +
+
+

Mon Profil

+

@{username}

+
+
+ + {successMsg && ( +
+ {successMsg} +
+ )} + {errorMsg && ( +
+ {" "} + {errorMsg} +
+ )} + + {/* Section compte */} +
+

+ + Mon compte +

+
+
+
+ + setPrenom(e.target.value)} + placeholder="Votre prénom" + /> +
+
+ + setNom(e.target.value)} + placeholder="Votre nom" + /> +
+
+
+ + setTelephone(e.target.value)} + placeholder="+33 6 12 34 56 78" + /> +
+
+ + +
+ + {/* Section adresse par défaut */} +
+

+ + Adresse par défaut +

+

+ Sera pré-remplie dans le formulaire de commande. Vous + pourrez la modifier si vous n'êtes pas à cette adresse. +

+
+ + setDefaultAddress(e.target.value)} + placeholder="Numéro, rue, ville, code postal" + /> +
+
+ + {/* Section contact commande */} +
+

+ + Contact livraison +

+

+ Numéro utilisé par le livreur lors de la livraison. Peut + être différent du numéro de votre compte. +

+
+ + setDefaultPhone(e.target.value)} + placeholder="+33 6 12 34 56 78" + /> +
+
+ + setSignalPseudo(e.target.value)} + placeholder="@votre.pseudo.signal" + /> +
+ +
+ {/* Section Telegram */} + {tgEnabled && ( +
+

+ + Notifications Telegram +

+

+ Recevez vos notifications sur Telegram, même quand + le site est fermé. +

+ {tgLinked ? ( +
+ + {" "} + Compte Telegram lié + + +
+ ) : ( + + )} +
+ )}
-
- - setTelephone(e.target.value)} - placeholder="+33 6 12 34 56 78" - /> -
-
- - -
- {/* Section adresse par défaut */} -
-

- - Adresse par défaut -

-

- Sera pré-remplie dans le formulaire de commande. Vous pourrez la modifier si vous n'êtes pas à cette adresse. -

-
- - setDefaultAddress(e.target.value)} - placeholder="Numéro, rue, ville, code postal" - /> -
-
- - {/* Section contact commande */} -
-

- - Contact livraison -

-

- Numéro utilisé par le livreur lors de la livraison. Peut être différent du numéro de votre compte. -

-
- - setDefaultPhone(e.target.value)} - placeholder="+33 6 12 34 56 78" - /> -
-
- - setSignalPseudo(e.target.value)} - placeholder="@votre.pseudo.signal" - /> -
- -
- {/* Section Telegram */} - {tgEnabled && ( -
-

- - Notifications Telegram -

-

- Recevez vos notifications sur Telegram, même quand le site est fermé. -

- {tgLinked ? ( -
- - Compte Telegram lié - - -
- ) : ( - + {showSaveModal && ( +
setShowSaveModal(false)} + > +
e.stopPropagation()} + > + +
+ +
+

+ Enregistrer les infos par défaut ? +

+

+ Adresse, téléphone de livraison et pseudo Signal + seront sauvegardés localement et pré-remplis lors de + vos prochaines commandes. +

+
+ + +
+
+
)} -
- )} -
- - {showSaveModal && ( -
setShowSaveModal(false)}> -
e.stopPropagation()}> - -
- -
-

Enregistrer les infos par défaut ?

-

- Adresse, téléphone de livraison et pseudo Signal seront sauvegardés localement et pré-remplis lors de vos prochaines commandes. -

-
- - -
-
-
- )} - - ); + + ); }