/** * ========================================================================= * PLATEFORME ECO-PANNEAU.FR - VERSION 1.0.0 * Interface Administrateur - Onglet Base Clients * ========================================================================= */ window.AdminClientsTab = ({ data, refreshData, showToast, setActiveTab, openLocalModal, openLocalDialog, closeCurrentLayer, activeModal, activeDialog, targetId }) => { const { useState } = React; // FACTORISATION : Utilisation du Hook global de gestion des modales par URL const { activeDialog: urlDialog, openDialog, closeCurrentLayer: urlCloseLayer } = window.useUrlModal(); // Priorité aux props passées par le parent, sinon fallback sur le hook const routerActiveDialog = activeDialog || urlDialog; const routerCloseLayer = closeCurrentLayer || urlCloseLayer; const routerOpenDialog = openLocalDialog || openDialog; const [isSaving, setIsSaving] = useState(false); // Cibles des modales const [accessTarget, setAccessTarget] = useState(null); const [creditTarget, setCreditTarget] = useState(null); const [editClientTarget, setEditClientTarget] = useState(null); const [pwdRequestData, setPwdRequestData] = useState(null); const [confirmConfig, setConfirmConfig] = useState(null); // FACTORISATION : Récupération sécurisée et propre des icônes const { UsersIcon, KeyRoundIcon, ShieldAlertIcon, ShieldIcon, ZapIcon, MessageSquareIcon, Trash2Icon, EditIcon, MailIcon, CheckCircleIcon, LoaderIcon } = window.getIcons(); const Modal = window.Modal || (() => null); const ConfirmModal = window.ConfirmModal || (() => null); const PasswordPromptModal = window.PasswordPromptModal || (() => null); const Button = window.Button || (({children}) => ); const IconBadge = window.IconBadge || (() => null); const clients = data.clients || []; const sendAccessRequest = async (uid, mode) => { const d = await window.apiFetch('clients/request_access', { body: { uid, mode }, setLoading: setIsSaving, successMessage: "Demande d'accès envoyée avec succès." }); if (d) { routerCloseLayer(); refreshData(); } }; const revokeAccess = async (uid) => { setConfirmConfig({ title: "Révocation d'accès", message: "Êtes-vous sûr de vouloir révoquer l'autorisation d'accès technique pour ce client ?", confirmText: "Oui, révoquer", isDestructive: true, onConfirm: async () => { routerCloseLayer(); const d = await window.apiFetch('clients/revoke_access', { body: { uid }, setLoading: setIsSaving, successMessage: "Accès révoqué." }); if (d) refreshData(); } }); routerOpenDialog('confirm'); }; const impersonateClient = async (uid) => { const d = await window.apiFetch('auth/impersonate', { body: { uid }, setLoading: setIsSaving }); if (d) window.location.href = '?'; }; const deleteClient = (uid, clientName) => { setPwdRequestData({ title: `Suppression du compte : ${clientName}`, desc: (ATTENTION : Saisissez le mot de passe administrateur pour détruire définitivement le compte de {clientName} et toutes ses données associées. Cette action est irréversible.), onConfirm: async (pwd) => { const d = await window.apiFetch('clients/admin_delete', { body: { uid, pwd }, setLoading: setIsSaving, successMessage: "Client supprimé avec succès." }); if (d) { routerCloseLayer(); refreshData(); } } }); routerOpenDialog('pwd_request'); }; const handleAddCredit = async (e) => { e.preventDefault(); const amount = parseFloat(e.target.amount.value); const reason = e.target.reason.value; if (amount <= 0) return showToast("Montant invalide", "error"); const d = await window.apiFetch('invoices/credit', { body: { client_uid: creditTarget.client_uid, amount, reason }, setLoading: setIsSaving, successMessage: "Crédit ajouté avec succès !" }); if (d) { routerCloseLayer(); refreshData(); } }; const handleEditClientSubmit = async (e) => { e.preventDefault(); const discount = parseInt(e.target.discount.value) || 0; const discountDuration = e.target.discountDuration.value; const paymentStatus = e.target.paymentStatus.value; const d = await window.apiFetch('clients/update', { body: { uid: editClientTarget.id, discount, discountDuration, paymentStatus }, setLoading: setIsSaving, successMessage: "Client mis à jour avec succès." }); if (d) { routerCloseLayer(); refreshData(); } }; return (
Gestion des comptes et prise de contrôle.
{c.name}
{c.full_name &&{c.full_name}
}{c.email}
ID : {c.id.substring(0,8)}
{c.wallet_balance !== 0 && ( 0 ? 'bg-emerald-100 text-emerald-700' : 'bg-red-100 text-red-700'}`}> {c.wallet_balance > 0 ? `Solde: +${c.wallet_balance.toFixed(2)}€` : `Dette: ${c.wallet_balance.toFixed(2)}€`} )}Revenu (12m)
{revenue12m.toFixed(2)} €
Actifs
{activePanelsCount}
Brouillons
{draftPanelsCount}
Aucun client enregistré.