/** * ========================================================================= * PLATEFORME ECO-PANNEAU.FR - VERSION 1.0.0 * Composant : Modale de gestion d'équipe par panneau * ========================================================================= */ const { useState, useEffect } = React; window.ClientPanelTeamModal = ({ panneau, myClientData, teamMembers, onClose, refreshData, showToast }) => { const [inviteEmail, setInviteEmail] = useState(''); const [selectedTeamMember, setSelectedTeamMember] = useState(''); const [canEdit, setCanEdit] = useState(false); const [chatAccess, setChatAccess] = useState('none'); const [isSaving, setIsSaving] = useState(false); const [confirmDialog, setConfirmDialog] = useState(null); // État pour la saisie rapide du nom complet si manquant const [tempFullName, setTempFullName] = useState(''); const isDirty = inviteEmail.trim() !== '' || selectedTeamMember !== '' || canEdit || chatAccess !== 'none' || tempFullName.trim() !== ''; // COMPOSANTS GLOBAUX NETTOYÉS const AlertBox = window.AlertBox; const ConfirmModal = window.ConfirmModal; const Button = window.Button; const UsersIcon = window.UsersIcon || (() => null); const MailIcon = window.MailIcon || (() => null); const PlusIcon = window.PlusIcon || (() => null); const Trash2Icon = window.Trash2Icon || (() => null); const LoaderIcon = window.LoaderIcon || (() => null); const ShieldIcon = window.ShieldIcon || (() => null); const LogOutIcon = window.LogOutIcon || (() => null); const AlertTriangleIcon = window.AlertTriangleIcon || (() => null); const SaveIcon = window.SaveIcon || (() => null); // BINDING const isOwner = panneau.client_uid === myClientData.id; const collaborators = panneau.collaborators || []; // CORRECTION UX : Vérification de la présence du nom complet pour autoriser la collaboration const hasFullName = !!(myClientData.full_name && myClientData.full_name.trim()); // Saisie rapide du nom complet directement depuis la modale const handleSaveFullName = async (e) => { e.preventDefault(); if (!tempFullName.trim()) return; const payload = { ...myClientData, full_name: tempFullName }; const d = await window.apiFetch('clients/profile/update', { body: payload, setLoading: setIsSaving, successMessage: "Identité enregistrée avec succès." }); if (d) { if (refreshData) refreshData(); } }; const handleInvite = async (e) => { e.preventDefault(); const targetEmail = selectedTeamMember || inviteEmail; if (!targetEmail) return; const d = await window.apiFetch('panneaux/collaborators/invite', { body: { panneau_id: panneau.id, email: targetEmail, can_edit: canEdit, chat_access: chatAccess }, setLoading: setIsSaving, successMessage: "Invitation envoyée avec succès." }); if (d) { setInviteEmail(''); setSelectedTeamMember(''); setCanEdit(false); setChatAccess('none'); refreshData(); } }; const handleRemove = (uid) => { setConfirmDialog({ title: "Retirer l'accès", message: "Êtes-vous sûr de vouloir retirer ce collaborateur du projet ?", confirmText: "Oui, retirer", isDestructive: true, onConfirm: async () => { setConfirmDialog(null); const d = await window.apiFetch('panneaux/collaborators/remove', { body: { panneau_id: panneau.id, target_uid: uid }, setLoading: setIsSaving, successMessage: "Collaborateur retiré du panneau." }); if (d) refreshData(); } }); }; const handleUpdateRights = async (uid, can_edit, chat_access) => { const d = await window.apiFetch('panneaux/collaborators/update', { body: { panneau_id: panneau.id, target_uid: uid, rights: { can_edit, chat_access } }, setLoading: setIsSaving, successMessage: "Droits mis à jour avec succès." }); if (d) refreshData(); }; const handleLeave = () => { setConfirmDialog({ title: "Quitter le projet", message: "Êtes-vous sûr de vouloir quitter ce projet ? Vous perdrez l'accès à ce panneau et à son groupe de discussion.", confirmText: "Oui, quitter", isDestructive: true, onConfirm: async () => { setConfirmDialog(null); const d = await window.apiFetch('panneaux/collaborators/leave', { body: { panneau_id: panneau.id }, setLoading: setIsSaving, successMessage: "Vous avez quitté le projet." }); if (d) { onClose(); refreshData(); } } }); }; return (
Gérez les accès à ce panneau. Chaque membre invité aura accès au groupe de discussion intégré. {!hasFullName && isOwner && (

Identité requise

Pour inviter des collaborateurs, vous devez renseigner votre nom complet afin qu'ils puissent vous identifier dans l'e-mail d'invitation.

setTempFullName(e.target.value)} placeholder="Prénom et Nom" required disabled={isSaving} className="flex-1 border-2 border-orange-200 rounded-xl p-3 text-sm outline-none focus:border-orange-500 bg-white disabled:opacity-50" />
)} {isOwner && hasFullName && (

Inviter un collaborateur

setInviteEmail(e.target.value)} placeholder="architecte@exemple.com" className="w-full border-2 border-slate-200 rounded-lg p-2.5 text-sm outline-none focus:border-blue-500 disabled:bg-slate-50" />
Accès aux conversations avec les riverains :
)}

Membres du projet

{isOwner ? "Vous (Propriétaire)" : `${panneau.owner_company || 'Propriétaire'} (${panneau.owner_name || ''})`}

{isOwner ? "Tous les droits" : "Propriétaire"}

{collaborators.map(c => (

{c.company} ({c.name})

{c.email}

{c.status === 'pending' ? ( En attente ) : ( Actif )}
{isOwner && (
Riverains:
)}
))} {collaborators.length === 0 && (

Aucun collaborateur invité sur ce projet.

)} {!isOwner && (
)}
{confirmDialog && ConfirmModal && ( setConfirmDialog(null)} zIndex="z-[350]" /> )}
); }; /* EOF ========== [_react/_clients_modals_team.jsx] */