Skip to content

Commit c2764de

Browse files
authored
Update AIChatbot.tsx
Signed-off-by: Aitor Alien <[email protected]>
1 parent 9e208f1 commit c2764de

1 file changed

Lines changed: 60 additions & 203 deletions

File tree

src/components/AIChatbot.tsx

Lines changed: 60 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -1,259 +1,116 @@
1-
import React, { useEffect, useCallback, useState, useMemo } from 'react';
1+
import React, { useEffect, useState, useMemo, useCallback } from 'react';
22
import { motion, AnimatePresence } from 'framer-motion';
3-
import { X, Loader2, Zap, Sparkles, Rocket, HeadphonesIcon, Shield } from 'lucide-react';
4-
import { toast } from 'sonner';
3+
import { X, Loader2, Sparkles, Rocket, Zap } from 'lucide-react';
54
import aiTorAvatar from '@/assets/ai-tor-avatar.jpg';
65

7-
// Configuración de Personalidades/Roles basada en tus versiones previas
86
const AI_DAPP_ROLES = [
9-
{
10-
id: 'welcome',
11-
name: 'AI Tor',
12-
role: 'Sistemas Tor',
13-
icon: Rocket,
14-
color: 'from-alien-green to-emerald-500',
15-
borderColor: 'rgba(57,255,20,0.5)',
16-
messages: [
17-
"👽 ¡Conexión establecida! Soy AI Tor. ¿Exploramos el ecosistema juntas?",
18-
"✨ ¿Buscas algo específico en la DAO? Estoy sincronizado y listo.",
19-
"🌌 Tu viaje cósmico empieza aquí. Pregúntame lo que necesites."
20-
]
21-
},
22-
{
23-
id: 'promo',
24-
name: 'AI Tor',
25-
role: 'Oportunidad',
26-
icon: Sparkles,
27-
color: 'from-pink-500 to-rose-500',
28-
borderColor: 'rgba(236,72,153,0.6)',
29-
messages: [
30-
"🚀 ¡Misión Especial! Únete a la DAO y desbloquea NFTs exclusivos.",
31-
"🔥 Academy, Clubs y CoNetWorKing... todo a tu alcance.",
32-
"💎 Coleccionables únicos detectados. ¿Quieres verlas?"
33-
]
34-
},
35-
{
36-
id: 'dao',
37-
name: 'Voz de la DAO',
38-
role: 'Estrategia',
39-
icon: Zap,
40-
color: 'from-alien-gold to-yellow-500',
41-
borderColor: 'rgba(240,216,130,0.6)',
42-
messages: [
43-
"⚖️ Alerta de Gobernanza: ¡Hay nuevas propuestas! Tu voto es tu poder.",
44-
"🏛️ ¿Listo para influir en el presente? Mira cómo participar en la DAO.",
45-
"🌟 Formar parte de la DAO es decidir el presente."
46-
]
47-
}
7+
{ id: 'welcome', role: 'Sistemas Tor', icon: Rocket, color: '#39FF14', messages: ["👽 ¡Conexión establecida! Soy AI Tor. ¿Exploramos el ecosistema?"] },
8+
{ id: 'promo', role: 'Oportunidad', icon: Sparkles, color: '#EC4899', messages: ["🚀 ¡Misión Especial! Únete a la DAO y desbloquea NFTs."] },
9+
{ id: 'dao', role: 'Voz de la DAO', icon: Zap, color: '#F0D882', messages: ["⚖️ ¡Nuevas propuestas de gobernanza! Tu voto es tu poder."] }
4810
];
4911

5012
const AIChatbot = () => {
5113
const [isOpen, setIsOpen] = useState(false);
5214
const [isLoading, setIsLoading] = useState(true);
5315
const [showProactive, setShowProactive] = useState(false);
54-
const [proactiveMessage, setProactiveMessage] = useState('');
5516
const [hasInteracted, setHasInteracted] = useState(false);
5617
const [currentRoleIndex, setCurrentRoleIndex] = useState(0);
57-
const [messageCount, setMessageCount] = useState(0);
5818

5919
const currentRole = useMemo(() => AI_DAPP_ROLES[currentRoleIndex], [currentRoleIndex]);
6020

61-
// 1. Gestión Proactiva con tus tiempos: 18s y 33s
21+
// Gestión Proactiva (Tiempos 18s / 33s)
6222
useEffect(() => {
6323
if (hasInteracted || isOpen) return;
64-
65-
const delay = messageCount === 0 ? 18000 : 33000;
66-
6724
const timer = setTimeout(() => {
68-
let nextIndex = messageCount === 0 ? 0 : Math.floor(Math.random() * AI_DAPP_ROLES.length);
69-
70-
const role = AI_DAPP_ROLES[nextIndex];
71-
const randomMsg = role.messages[Math.floor(Math.random() * role.messages.length)];
72-
73-
setCurrentRoleIndex(nextIndex);
74-
setProactiveMessage(randomMsg);
25+
setCurrentRoleIndex(Math.floor(Math.random() * AI_DAPP_ROLES.length));
7526
setShowProactive(true);
76-
setMessageCount(prev => prev + 1);
77-
78-
// Auto-ocultar después de 10 segundos
7927
setTimeout(() => setShowProactive(false), 10000);
80-
}, delay);
81-
28+
}, 18000);
8229
return () => clearTimeout(timer);
83-
}, [hasInteracted, isOpen, messageCount]);
30+
}, [hasInteracted, isOpen]);
8431

85-
// 2. Tracking de interacción robusto (Cualquier interacción humana real)
32+
// Tracking de interacción (Escucha si el usuario mueve el mouse o tecla)
8633
useEffect(() => {
8734
const handleInteraction = () => setHasInteracted(true);
88-
const events = ['mousedown', 'keydown', 'touchstart', 'wheel'];
89-
90-
events.forEach(event => window.addEventListener(event, handleInteraction, { once: true }));
91-
return () => events.forEach(event => window.removeEventListener(event, handleInteraction));
92-
}, []);
93-
94-
// 3. Handlers con Feedback (Toast)
95-
const handleOpen = useCallback(() => {
96-
setIsOpen(true);
97-
setIsLoading(true);
98-
setShowProactive(false);
99-
setHasInteracted(true);
100-
toast.info('AI Assistant', {
101-
description: 'Estableciendo enlace con AI Tor...',
102-
duration: 3000,
103-
});
104-
}, []);
105-
106-
const handleIframeLoad = useCallback(() => {
107-
setIsLoading(false);
108-
}, []);
109-
110-
const handleIframeError = useCallback(() => {
111-
setIsLoading(false);
112-
toast.error('Error de Enlace', {
113-
description: 'No se pudo conectar con AI Tor. Reintenta más tarde.'
114-
});
35+
const events = ['mousedown', 'keydown', 'touchstart'];
36+
events.forEach(e => window.addEventListener(e, handleInteraction, { once: true }));
37+
return () => events.forEach(e => window.removeEventListener(e, handleInteraction));
11538
}, []);
11639

11740
return (
11841
<>
119-
{/* Overlay con Blur dinámico */}
120-
<AnimatePresence>
121-
{isOpen && (
122-
<motion.div
123-
initial={{ opacity: 0 }}
124-
animate={{ opacity: 1 }}
125-
exit={{ opacity: 0 }}
126-
onClick={() => setIsOpen(false)}
127-
className="fixed inset-0 z-40 bg-black/80 backdrop-blur-sm"
128-
/>
129-
)}
130-
</AnimatePresence>
42+
{/* Botón Avatar con entrada desde el Hiperespacio */}
43+
<motion.button
44+
initial={{ scale: 0, rotate: -180, filter: "blur(20px)" }}
45+
animate={{ scale: 1, rotate: 0, filter: "blur(0px)" }}
46+
transition={{ type: "spring", stiffness: 200, damping: 20, delay: 1.5 }}
47+
whileHover={{ scale: 1.1, boxShadow: `0 0 25px ${currentRole.color}44` }}
48+
onClick={() => setIsOpen(!isOpen)}
49+
className="fixed bottom-6 right-6 z-[120] w-14 h-14 sm:w-16 sm:h-16 rounded-full border-2 border-alien-gold/40 overflow-hidden bg-black shadow-2xl"
50+
>
51+
<img src={aiTorAvatar} alt="AI Tor" className="w-full h-full object-cover" />
52+
</motion.button>
13153

132-
{/* Burbuja Proactiva / Promocional */}
54+
{/* Burbuja Proactiva */}
13355
<AnimatePresence>
13456
{showProactive && !isOpen && (
13557
<motion.div
136-
initial={{ opacity: 0, x: 20, scale: 0.8, y: 0 }}
137-
animate={{ opacity: 1, x: 0, scale: 1, y: 0 }}
138-
exit={{ opacity: 0, x: 20, scale: 0.8 }}
139-
className="fixed bottom-36 right-4 sm:bottom-40 sm:right-8 z-40
140-
max-w-[300px] p-4 rounded-2xl rounded-br-sm border-2
141-
shadow-[0_10px_40px_rgba(0,0,0,0.5)] cursor-pointer"
142-
style={{
143-
background: 'linear-gradient(135deg, rgba(15,15,25,0.98) 0%, rgba(30,30,45,0.98) 100%)',
144-
borderColor: currentRole.borderColor
145-
}}
146-
onClick={handleOpen}
58+
initial={{ opacity: 0, x: 50, scale: 0.8 }}
59+
animate={{ opacity: 1, x: 0, scale: 1 }}
60+
exit={{ opacity: 0, x: 50, scale: 0.8 }}
61+
onClick={() => setIsOpen(true)}
62+
className="fixed bottom-24 right-6 z-[121] max-w-[260px] p-4 rounded-2xl bg-black/90 backdrop-blur-xl border border-white/10 shadow-2xl cursor-pointer"
63+
style={{ borderLeft: `4px solid ${currentRole.color}` }}
14764
>
148-
<div className="flex gap-3">
149-
<div className="shrink-0 relative">
150-
<div className="w-12 h-12 rounded-full overflow-hidden border border-alien-gold/30">
151-
<img src={aiTorAvatar} alt="AI Tor" className="w-full h-full object-cover" />
152-
</div>
153-
<div className="absolute -bottom-1 -right-1 bg-alien-space-dark rounded-full p-1 border border-alien-gold/40">
154-
<currentRole.icon className="w-3 h-3 text-alien-gold" />
155-
</div>
156-
</div>
157-
<div className="flex-1">
158-
<div className="flex items-center justify-between mb-1">
159-
<span className="text-[10px] font-nasalization text-alien-gold tracking-widest uppercase italic">
160-
{currentRole.role}
161-
</span>
162-
</div>
163-
<p className="text-gray-200 font-exo text-[13px] leading-snug">
164-
{proactiveMessage}
165-
</p>
166-
{currentRole.id === 'promo' && (
167-
<span className="text-[10px] text-alien-gold mt-2 block font-bold animate-pulse">
168-
VER MÁS AHORA →
169-
</span>
170-
)}
171-
</div>
65+
<div className="flex items-center gap-2 mb-1">
66+
<currentRole.icon size={12} style={{ color: currentRole.color }} />
67+
<span className="text-[10px] font-nasalization text-alien-gold tracking-widest uppercase">{currentRole.role}</span>
17268
</div>
173-
<button
174-
onClick={(e) => { e.stopPropagation(); setShowProactive(false); }}
175-
className="absolute -top-2 -right-2 w-6 h-6 bg-alien-space-dark rounded-full
176-
flex items-center justify-center border border-white/10 hover:bg-red-900/40 transition-colors"
177-
>
178-
<X className="w-3 h-3 text-gray-400" />
179-
</button>
69+
<p className="text-white text-xs font-exo leading-tight">{currentRole.messages[0]}</p>
18070
</motion.div>
18171
)}
18272
</AnimatePresence>
18373

184-
{/* Botón Flotante Principal (Avatar) */}
185-
<motion.button
186-
initial={{ opacity: 0, scale: 0.5 }}
187-
animate={{ opacity: 1, scale: 1 }}
188-
whileHover={{ scale: 1.1 }}
189-
whileTap={{ scale: 0.9 }}
190-
onClick={handleOpen}
191-
className="fixed bottom-20 right-4 sm:bottom-24 sm:right-8 z-40
192-
w-14 h-14 sm:w-16 sm:h-16 rounded-full border-2 border-alien-gold-light/50
193-
shadow-2xl overflow-hidden ai-button-pulse"
194-
>
195-
<img src={aiTorAvatar} alt="AI Tor" className="w-full h-full object-cover" />
196-
</motion.button>
197-
198-
{/* Ventana de Chat (Iframe de Lovable) */}
74+
{/* Interfaz de Chat Adaptable (Móvil/Tablet/PC) */}
19975
<AnimatePresence>
20076
{isOpen && (
20177
<motion.div
202-
initial={{ opacity: 0, y: 100, scale: 0.8 }}
203-
animate={{ opacity: 1, y: 0, scale: 1 }}
204-
exit={{ opacity: 0, y: 100, scale: 0.8 }}
205-
className="fixed z-50 inset-2 sm:inset-auto sm:bottom-24 sm:right-8
206-
sm:w-[360px] md:w-[400px] sm:h-[550px] md:h-[600px]
207-
bg-alien-space-dark/98 backdrop-blur-xl border-2 border-alien-gold/40
208-
rounded-2xl shadow-2xl overflow-hidden flex flex-col chat-glow"
78+
initial={{ opacity: 0, scale: 0, x: 150, y: 150, filter: "blur(20px)" }}
79+
animate={{ opacity: 1, scale: 1, x: 0, y: 0, filter: "blur(0px)" }}
80+
exit={{ opacity: 0, scale: 0, x: 150, y: 150, filter: "blur(20px)" }}
81+
transition={{ duration: 0.5, ease: "circOut" }}
82+
className="fixed z-[9999] bottom-6 right-6 left-6 sm:left-auto sm:w-[380px] md:w-[420px] h-[75vh] max-h-[600px] bg-alien-space-dark rounded-[2.5rem] border-2 border-alien-gold/30 shadow-[0_0_80px_rgba(0,0,0,0.9)] overflow-hidden flex flex-col"
20983
>
210-
{/* Header de la Interfaz */}
211-
<div className="bg-gradient-to-r from-alien-space-dark via-alien-space to-alien-space-dark
212-
border-b border-alien-gold/20 p-4 flex items-center justify-between">
84+
{/* Header Interface */}
85+
<div className="p-5 bg-black/60 border-b border-white/10 flex justify-between items-center">
21386
<div className="flex items-center gap-3">
214-
<div className="w-10 h-10 rounded-full border-2 border-alien-gold/40 overflow-hidden">
215-
<img src={aiTorAvatar} alt="AI Tor" className="w-full h-full object-cover" />
87+
<div className="w-9 h-9 rounded-full border border-alien-green/50 p-0.5">
88+
<img src={aiTorAvatar} alt="AI" className="w-full h-full rounded-full object-cover" />
21689
</div>
21790
<div>
218-
<h3 className="text-alien-gold font-bold font-nasalization text-[12px] tracking-wider">AI TOR INTERFACE</h3>
219-
<div className="flex items-center gap-1.5">
220-
<span className="w-2 h-2 bg-alien-green rounded-full animate-pulse" />
221-
<span className="text-[10px] text-alien-green font-exo uppercase tracking-tighter">Sincronización Cuántica</span>
222-
</div>
91+
<h3 className="text-alien-gold font-nasalization text-[10px] tracking-widest leading-none">AI TOR INTERFACE</h3>
92+
<span className="text-alien-green text-[8px] font-exo uppercase animate-pulse">Online • Quantum Link</span>
22393
</div>
22494
</div>
225-
<button onClick={() => setIsOpen(false)} className="p-2 hover:bg-white/10 rounded-lg text-alien-gold">
226-
<X size={20} />
95+
<button onClick={() => setIsOpen(false)} className="p-2 hover:bg-white/10 rounded-full text-white/50 hover:text-alien-green transition-all">
96+
<X size={22} />
22797
</button>
22898
</div>
22999

230-
{/* Contenedor del Iframe con Loading State */}
231-
<div className="flex-1 relative bg-black">
100+
{/* Iframe & Radar de Carga */}
101+
<div className="flex-1 bg-black relative">
232102
{isLoading && (
233-
<div className="absolute inset-0 flex flex-col items-center justify-center bg-alien-space-dark/95 z-10">
234-
<div className="relative mb-4">
235-
<div className="w-20 h-20 rounded-full overflow-hidden border-2 border-alien-gold/30">
236-
<img src={aiTorAvatar} alt="Loading" className="w-full h-full object-cover animate-pulse opacity-50" />
237-
</div>
238-
<Loader2 className="absolute -bottom-2 -right-2 h-8 w-8 text-alien-gold animate-spin" />
239-
</div>
240-
<p className="text-alien-gold font-nasalization text-[10px] tracking-widest uppercase">Enlazando Red Neural...</p>
241-
{/* Animación de puntos que pedías */}
242-
<div className="flex gap-1.5 mt-4">
243-
<div className="w-1.5 h-1.5 bg-alien-gold rounded-full animate-bounce" />
244-
<div className="w-1.5 h-1.5 bg-alien-gold rounded-full animate-bounce [animation-delay:-.3s]" />
245-
<div className="w-1.5 h-1.5 bg-alien-gold rounded-full animate-bounce [animation-delay:-.5s]" />
246-
</div>
103+
<div className="absolute inset-0 flex flex-col items-center justify-center bg-alien-space-dark z-10">
104+
<motion.div
105+
animate={{ scale: [1, 1.3, 1], opacity: [0.2, 0.5, 0.2] }}
106+
transition={{ repeat: Infinity, duration: 1.5 }}
107+
className="w-24 h-24 rounded-full border border-alien-green absolute"
108+
/>
109+
<Loader2 className="w-10 h-10 text-alien-green animate-spin mb-4" />
110+
<p className="text-alien-green font-nasalization text-[8px] tracking-[0.4em]">SYNCHRONIZING...</p>
247111
</div>
248112
)}
249-
<iframe
250-
src="https://aitor.lovable.app/"
251-
className="w-full h-full border-none"
252-
title="AI Tor Assistant"
253-
allow="microphone; camera; clipboard-write; geolocation"
254-
onLoad={handleIframeLoad}
255-
onError={handleIframeError}
256-
/>
113+
<iframe src="https://aitor.lovable.app/" className="w-full h-full border-none" onLoad={() => setIsLoading(false)} title="AI Tor" />
257114
</div>
258115
</motion.div>
259116
)}

0 commit comments

Comments
 (0)