import React, { useState, useEffect, useRef } from 'react'; import { Download, Upload, ShieldCheck, User, CreditCard, Settings, CheckCircle, Image as ImageIcon, Loader2 } from 'lucide-react'; export default function App() { // --- ÉTATS DES DONNÉES --- const [nom, setNom] = useState('RAOULT'); const [prenom, setPrenom] = useState('Didier'); const [numero, setNumero] = useState('0666'); const [annee, setAnnee] = useState('2026'); const [validite, setValidite] = useState('31/12/2027'); const [statut, setStatut] = useState('MEMBRE SOUTIEN'); const [includePrisme, setIncludePrisme] = useState(false); // --- LOGOS (Format Base64 forcé pour la capture) --- const [logoAstec, setLogoAstec] = useState(''); const [logoPrisme, setLogoPrisme] = useState(''); const [imagesReady, setImagesReady] = useState(false); // --- ÉTATS UI --- const [isGenerating, setIsGenerating] = useState(false); const [showSuccess, setShowSuccess] = useState(false); const [errorMsg, setErrorMsg] = useState(''); const cardRef = useRef(null); // 1. Chargement de html2canvas useEffect(() => { const script = document.createElement('script'); script.src = "https://cdnjs.cloudflare.com/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"; script.async = true; document.body.appendChild(script); return () => { if (document.body.contains(script)) document.body.removeChild(script); }; }, []); // 2. CONVERSION ANTI-CORS (Double Proxy pour garantir l'affichage au téléchargement) useEffect(() => { let isMounted = true; const fetchAsBase64 = async (url) => { const proxies = [ `https://corsproxy.io/?${encodeURIComponent(url)}`, `https://api.allorigins.win/raw?url=${encodeURIComponent(url)}` ]; for (const proxy of proxies) { try { const res = await fetch(proxy); if (res.ok) { const blob = await res.blob(); return await new Promise((resolve) => { const reader = new FileReader(); reader.onloadend = () => resolve(reader.result); reader.readAsDataURL(blob); }); } } catch (e) { console.warn("Proxy fallback...", proxy); } } return url; // Repli ultime sur l'URL brute si tout échoue }; const initImages = async () => { setImagesReady(false); const baseAstec = await fetchAsBase64('https://eglisenpq.neocities.org/image%20/Image2.png'); const basePrisme = await fetchAsBase64('https://eglisenpq.neocities.org/image%20/Capture%20d%E2%80%99%C3%A9cran%202026-03-05%20085325.jpg'); if (isMounted) { setLogoAstec(baseAstec); setLogoPrisme(basePrisme); setImagesReady(true); } }; initImages(); return () => { isMounted = false; }; }, []); const handleLogoUpload = (e) => { const file = e.target.files[0]; if (file) { const reader = new FileReader(); reader.onloadend = () => setLogoAstec(reader.result); reader.readAsDataURL(file); } }; const downloadPNG = async () => { if (!window.html2canvas || !cardRef.current) return; setIsGenerating(true); setErrorMsg(''); try { // Petite pause pour s'assurer que le DOM est rafraîchi await new Promise(r => setTimeout(r, 500)); const canvas = await window.html2canvas(cardRef.current, { scale: 4, // Échelle optimisée (4x = 1680x1060 px) pour éviter les crash mémoire du navigateur useCORS: true, allowTaint: true, backgroundColor: "#ffffff", logging: false, width: 420, height: 265 }); const link = document.createElement('a'); link.download = `carte_astec_${nom.toLowerCase().trim()}.png`; link.href = canvas.toDataURL('image/png', 1.0); link.click(); setShowSuccess(true); setTimeout(() => setShowSuccess(false), 3000); } catch (e) { console.error(e); setErrorMsg("Erreur lors de la capture. Essayez d'importer le logo manuellement."); } finally { setIsGenerating(false); } }; return (
Badge Officiel Haute Définition
Association pour la Science et
la Transmission de l'Esprit Critique
N° ADHÉRENT
{numero || '-'}
VALIDITÉ
{validite}
Système Anti-CORS Actif & Cadre CSS Vectorisé.