/** * ========================================================================= * PLATEFORME ECO-PANNEAU.FR - VERSION 1.0.0 * Paramètres du compte client - Sous-onglet : Profil et Facturation * ========================================================================= */ const FallbackNull = () => null; const FallbackCardGrid = ({children, className}) => (
{children}
); const FallbackTextLogo = ({ className = "" }) => eco-panneau.fr; window.pano_ClientSettingsProfile = ({ myClientData, data, showToast, refreshData }) => { const { useState } = React; const [isSaving, setIsSaving] = useState(false); const [emailChangeConfig, setEmailChangeConfig] = useState(null); const [profileData, setProfileData] = useState({ name: myClientData.name || '', full_name: myClientData.full_name || '', email: myClientData.email || '', phone: myClientData.phone || '', address: myClientData.address || '', siret: myClientData.siret || '', tva: myClientData.tva || '' }); const adminSettings = data.settings || {}; const optCollab = adminSettings.opt_collab || 'active'; const optMessaging = adminSettings.opt_messaging || 'active'; const optNewsletter = adminSettings.opt_newsletter || 'active'; const hasOptionalFeatures = [optCollab, optMessaging, optNewsletter].some(opt => opt === 'optional_on' || opt === 'optional_off' || opt === 'optional'); const getInitialOption = (adminOpt, savedVal) => { if (savedVal !== undefined) return savedVal; if (adminOpt === 'optional_on') return true; return false; }; let parsedOpts = {}; try { if (myClientData.uiMode && myClientData.uiMode.startsWith('{')) { parsedOpts = JSON.parse(myClientData.uiMode); } } catch(e) {} const [clientOptions, setClientOptions] = useState({ collab: getInitialOption(optCollab, parsedOpts.collab), messaging: getInitialOption(optMessaging, parsedOpts.messaging), newsletter: getInitialOption(optNewsletter, parsedOpts.newsletter) }); const { FileTextIcon, SaveIcon, LoaderIcon, SearchIcon, SettingsIcon, RefreshCwIcon } = window.pano_getIcons(); const FormInput = window.pano_FormInput || FallbackNull; const FormTextarea = window.pano_FormTextarea || FallbackNull; const Modal = window.pano_Modal || FallbackNull; const Button = window.pano_Button || FallbackNull; const Toggle = window.pano_Toggle || FallbackNull; const TextLogo = window.pano_TextLogo || FallbackTextLogo; const CardGrid = window.pano_CardGrid || FallbackCardGrid; const hasCollaborations = (data.panneaux || []).some(p => (p.client_uid === myClientData.id && p.collaborators && p.collaborators.length > 0) || (p.client_uid !== myClientData.id) ); const handleProfileSave = async (e) => { e.preventDefault(); if (!profileData.name.trim()) { showToast("Le nom de la société est obligatoire.", "error"); return; } if (hasCollaborations && !profileData.full_name.trim()) { showToast("Vous ne pouvez pas effacer votre nom complet car vous participez à des projets collaboratifs.", "error"); return; } const payload = { ...profileData, uiMode: JSON.stringify(clientOptions) }; const d = await window.pano_apiFetch('clients/profile/update', { body: payload, setLoading: setIsSaving, successMessage: "Profil et options mis à jour avec succès." }); if (d) refreshData(); }; const handleSiretLookup = async () => { if (!profileData.siret || profileData.siret.length < 9) { showToast("Veuillez saisir un SIREN (9 chiffres) ou SIRET (14 chiffres) valide.", "error"); return; } const d = await window.pano_apiFetch('systeme/siret_lookup', { body: { siret: profileData.siret }, setLoading: setIsSaving, successMessage: "Informations récupérées avec succès !" }); if (d) { setProfileData({ ...profileData, name: d.data.name || profileData.name, address: d.data.address || profileData.address, tva: d.data.tva || profileData.tva, siret: d.data.siret || profileData.siret }); } }; const handleEmailChangeRequest = async (e) => { e.preventDefault(); if (!emailChangeConfig.newEmail.trim() || !emailChangeConfig.newEmail.includes('@')) { showToast("Veuillez saisir un e-mail valide.", "error"); return; } const d = await window.pano_apiFetch('clients/profile/request_email', { body: { email: emailChangeConfig.newEmail }, setLoading: setIsSaving, successMessage: "Un code de vérification a été envoyé à cette nouvelle adresse." }); if (d) { setEmailChangeConfig({ ...emailChangeConfig, step: 'verify' }); } }; const handleEmailChangeVerify = async (e) => { e.preventDefault(); if (emailChangeConfig.code.length !== 6) return; const d = await window.pano_apiFetch('clients/profile/update_email', { body: { code: emailChangeConfig.code }, setLoading: setIsSaving, successMessage: "Votre adresse e-mail a été mise à jour avec succès. Veuillez vous reconnecter." }); if (d) { setEmailChangeConfig(null); setTimeout(() => window.location.href = '?', 1500); } }; const renderOption = (id, label, desc, adminStatus, clientValue, toggleKey) => { if (adminStatus === 'active' || adminStatus === 'disabled') return null; return (
{label} {desc}
setClientOptions({...clientOptions, [toggleKey]: v})} />
); }; return (
Le nom de la société est obligatoire. Cette information sera utilisée pour la facturation et apparaîtra lors de vos invitations collaboratives sur .
setProfileData({...profileData, name: e.target.value})} required /> setProfileData({...profileData, full_name: e.target.value})} required={hasCollaborations} hint={hasCollaborations ? "Vous ne pouvez pas effacer ce champ car vous participez à des projets collaboratifs." : "Obligatoire uniquement pour inviter ou rejoindre des collaborateurs."} />

Une vérification de sécurité sera exigée pour modifier votre e-mail.

setProfileData({...profileData, phone: e.target.value})} />

Informations de facturation

setProfileData({...profileData, siret: e.target.value.replace(/\s/g, '')})} placeholder="14 chiffres" className="flex-1 min-w-0 border-2 border-slate-200 rounded-xl p-3 focus:border-emerald-500 outline-none transition font-bold" maxLength={14} />
setProfileData({...profileData, tva: e.target.value})} className="col-span-full" />
setProfileData({...profileData, address: e.target.value})} rows={3} /> {hasOptionalFeatures && (

Fonctionnalités du compte

Gérez les options additionnelles de votre espace et de vos panneaux.

{renderOption('opt_collab', 'Travail en collaboration', 'Inviter des membres sur vos panneaux.', optCollab, clientOptions.collab, 'collab')} {renderOption('opt_messaging', 'Messagerie des riverains', 'Recevoir et répondre aux messages du voisinage.', optMessaging, clientOptions.messaging, 'messaging')} {renderOption('opt_newsletter', 'Info riverains', 'Informer les riverains abonnés des événements.', optNewsletter, clientOptions.newsletter, 'newsletter')}
)} {emailChangeConfig && Modal && ( setEmailChangeConfig(null)} preventClose={isSaving} zIndex="z-[250]"> {emailChangeConfig.step === 'request' ? (

Saisissez votre nouvelle adresse e-mail. Un code de vérification y sera envoyé pour confirmer qu'elle vous appartient bien.

setEmailChangeConfig({...emailChangeConfig, newEmail: e.target.value})} placeholder="Nouvelle adresse e-mail" required className="w-full border-2 border-slate-200 rounded-xl p-3 focus:border-emerald-500 outline-none transition font-bold" autoFocus />
) : (

Saisissez le code à 6 chiffres envoyé à {emailChangeConfig.newEmail}.

setEmailChangeConfig({...emailChangeConfig, code: e.target.value.replace(/\D/g, '').slice(0, 6)})} placeholder="000000" required className="w-full border-2 border-slate-200 rounded-xl p-3 focus:border-emerald-500 outline-none transition text-center text-3xl tracking-[0.25em] font-black" autoFocus />
{RefreshCwIcon && } Renvoyer le code
setEmailChangeConfig(null)} className={`text-xs font-bold text-slate-500 hover:text-slate-800 transition cursor-pointer ${isSaving ? 'opacity-50 pointer-events-none' : ''}`}> Annuler
)}
)}
); }; /* EOF ========== [_react/_clients_settings_profile.jsx] */