/** * ========================================================================= * PLATEFORME ECO-PANNEAU.FR - VERSION 1.0.0 * Composant : Générateur d'archives sécurisées (D.O.E et RGPD) * ========================================================================= */ const { useState, useEffect, useRef } = React; window.ArchiveGeneratorModal = ({ type, panelId, onClose, showToast, refreshData }) => { const { Lock, Download, CheckCircle, AlertTriangle, Loader, Copy, Mail } = window; const [step, setStep] = useState('generating'); const [progress, setProgress] = useState(0); const [result, setResult] = useState(null); const [errorMessage, setErrorMessage] = useState(''); const [sendingEmail, setSendingEmail] = useState(false); const [copied, setCopied] = useState(false); // CORRECTION : Verrou strict pour empêcher la boucle infinie de requêtes const hasFetched = useRef(false); useEffect(() => { // Si la requête a déjà été lancée pour cette modale, on stoppe net if (hasFetched.current) return; hasFetched.current = true; let currentProgress = 0; const interval = setInterval(() => { currentProgress += (90 - currentProgress) * 0.1; setProgress(currentProgress); }, 500); const endpoint = type === 'rgpd' ? 'archives/rgpd' : 'archives/doe'; const body = type === 'rgpd' ? {} : { id: panelId }; fetch(window.ECO_CONFIG.apiBaseUrl + endpoint, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(body) }) .then(res => res.json()) .then(d => { clearInterval(interval); setProgress(100); if (d.status === 'success') { setResult(d.data); setStep('done'); // Ce rafraîchissement ne relancera plus la boucle if (refreshData) { refreshData(); } } else { setErrorMessage(d.message || "Erreur lors de la génération."); setStep('error'); } }) .catch(e => { clearInterval(interval); setErrorMessage("Erreur de connexion réseau."); setStep('error'); }); return () => clearInterval(interval); }, [type, panelId]); // CORRECTION : refreshData retiré des dépendances ! const handleCopy = () => { if (!result || !result.password) { return; } navigator.clipboard.writeText(result.password).then(() => { setCopied(true); if (showToast) { showToast("Mot de passe copié !"); } setTimeout(() => setCopied(false), 2000); }); }; const handleSendEmail = async () => { if (!result) { return; } setSendingEmail(true); try { const res = await fetch(window.ECO_CONFIG.apiBaseUrl + 'archives/send_password', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filename: result.filename, password: result.password }) }); const d = await res.json(); if (d.status === 'success') { if (showToast) { showToast("Mot de passe envoyé par e-mail avec succès.", "success"); } } else { if (showToast) { showToast(d.message, "error"); } } } catch (e) { if (showToast) { showToast("Erreur lors de l'envoi de l'e-mail.", "error"); } } setSendingEmail(false); }; return (
{step === 'generating' && (

Création de l'archive sécurisée...

Chiffrement AES-256 de vos documents en cours. Veuillez patienter.

)} {step === 'error' && (

Échec de la génération

{errorMessage}

)} {step === 'done' && result && (

Archive chiffrée avec succès

Vos données ont été regroupées dans une archive ZIP protégée par un mot de passe unique.

Copiez ce mot de passe avant de télécharger l'archive, il ne sera plus jamais affiché.

Nom du fichier : {result.filename}

{result.password}

setTimeout(onClose, 1000)} download className="flex-[2] bg-emerald-600 text-white py-3 sm:py-4 rounded-xl font-black uppercase tracking-widest hover:bg-emerald-700 transition shadow-lg flex items-center justify-center gap-2" > Télécharger l'archive
)}
); }; /* EOF ===== [_socle_archives.jsx] =============== */