11import React from 'react' ;
22import { motion , AnimatePresence } from 'framer-motion' ;
3- import { Brain , X } from 'lucide-react' ;
3+ import { X , Loader2 } from 'lucide-react' ;
44import { toast } from 'sonner' ;
5+ import aiTorAvatar from '@/assets/ai-tor-avatar.jpg' ;
56
67const AIChatbot = ( ) => {
78 const [ isOpen , setIsOpen ] = React . useState ( false ) ;
9+ const [ isLoading , setIsLoading ] = React . useState ( true ) ;
810
911 const handleOpen = ( ) => {
1012 setIsOpen ( true ) ;
13+ setIsLoading ( true ) ;
1114 toast . info ( 'AI Assistant Loading' , {
1215 description : 'Opening AI Tor Assistant...'
1316 } ) ;
1417 } ;
1518
19+ const handleIframeLoad = ( ) => {
20+ setIsLoading ( false ) ;
21+ } ;
22+
1623 return (
1724 < >
18- { /* Dark overlay for mobile when chat is open */ }
25+ { /* Dark overlay when chat is open */ }
1926 < AnimatePresence >
2027 { isOpen && (
2128 < motion . div
2229 initial = { { opacity : 0 } }
2330 animate = { { opacity : 1 } }
2431 exit = { { opacity : 0 } }
2532 onClick = { ( ) => setIsOpen ( false ) }
26- className = "fixed inset-0 z-40 bg-black/60 backdrop-blur-sm sm:hidden "
33+ className = "fixed inset-0 z-40 bg-black/70 backdrop-blur-sm"
2734 />
2835 ) }
2936 </ AnimatePresence >
@@ -34,38 +41,49 @@ const AIChatbot = () => {
3441 animate = { { opacity : 1 , scale : 1 } }
3542 transition = { { delay : 0.5 } }
3643 onClick = { handleOpen }
37- className = "fixed bottom-20 right-4 sm:bottom-24 sm:right-8 z-40 p-3 sm:p-4
44+ className = "fixed bottom-20 right-4 sm:bottom-24 sm:right-8 z-40
3845 bg-gradient-to-br from-alien-gold to-alien-gold-dark backdrop-blur-md
39- border-2 border-alien-gold-light rounded-full text-alien-space-dark
46+ border-2 border-alien-gold-light rounded-full
4047 hover:scale-110 transition-all duration-300
41- shadow-2xl hover:shadow-alien-gold/50 ai-button-pulse"
48+ shadow-2xl hover:shadow-alien-gold/50 ai-button-pulse
49+ overflow-hidden w-14 h-14 sm:w-16 sm:h-16"
4250 aria-label = "Open AI Assistant"
4351 >
44- < Brain className = "h-6 w-6 sm:h-7 sm:w-7" />
52+ < img
53+ src = { aiTorAvatar }
54+ alt = "AI Tor"
55+ className = "w-full h-full object-cover"
56+ />
4557 </ motion . button >
4658
47- { /* Chat Window */ }
59+ { /* Chat Window - Fullscreen on mobile */ }
4860 < AnimatePresence >
4961 { isOpen && (
5062 < motion . div
5163 initial = { { opacity : 0 , y : 100 , scale : 0.8 } }
5264 animate = { { opacity : 1 , y : 0 , scale : 1 } }
5365 exit = { { opacity : 0 , y : 100 , scale : 0.8 } }
5466 transition = { { duration : 0.3 } }
55- className = "fixed bottom-4 right-4 sm:bottom-24 sm:right-8 z-50
56- w-[calc(100vw-2rem)] sm:w-[380px] md:w-[420px]
57- h-[calc(100vh-6rem)] sm:h-[550px] md:h-[600px]
58- max-w-[420px] max-h-[calc(100vh-4rem)] sm:max-h-[calc(100vh-8rem)]
67+ className = "fixed z-50
68+ inset-0 sm:inset-auto
69+ sm:bottom-24 sm:right-8
70+ sm:w-[380px] md:w-[420px]
71+ sm:h-[550px] md:h-[600px]
72+ sm:max-h-[calc(100vh-8rem)]
5973 bg-alien-space-dark/98 backdrop-blur-xl
60- border-2 border-alien-gold/40 rounded-2xl
74+ sm: border-2 border-alien-gold/40 sm: rounded-2xl
6175 shadow-2xl overflow-hidden chat-glow"
6276 >
6377 { /* Header */ }
6478 < div className = "bg-gradient-to-r from-alien-space-dark via-alien-space/90 to-alien-space-dark
6579 border-b border-alien-gold/30 p-3 sm:p-4 flex items-center justify-between" >
6680 < div className = "flex items-center gap-3" >
67- < div className = "p-2 bg-gradient-to-br from-alien-gold/30 to-alien-green/20 rounded-full" >
68- < Brain className = "h-5 w-5 text-alien-gold" />
81+ < div className = "w-10 h-10 sm:w-11 sm:h-11 rounded-full overflow-hidden border-2 border-alien-gold/50" >
82+ < img
83+ src = { aiTorAvatar }
84+ alt = "AI Tor"
85+ className = "w-full h-full object-cover"
86+ />
6987 </ div >
7088 < div >
7189 < h3 className = "text-alien-gold font-bold font-nasalization text-sm sm:text-base" >
@@ -81,20 +99,52 @@ const AIChatbot = () => {
8199 </ div >
82100 < button
83101 onClick = { ( ) => setIsOpen ( false ) }
84- className = "p-1.5 hover:bg-alien-gold/20 rounded-lg transition-colors"
102+ className = "p-2 hover:bg-alien-gold/20 rounded-lg transition-colors"
85103 aria-label = "Close chat"
86104 >
87105 < X className = "h-5 w-5 text-alien-gold" />
88106 </ button >
89107 </ div >
90108
109+ { /* Loading State */ }
110+ < AnimatePresence >
111+ { isLoading && (
112+ < motion . div
113+ initial = { { opacity : 0 } }
114+ animate = { { opacity : 1 } }
115+ exit = { { opacity : 0 } }
116+ className = "absolute inset-0 top-14 sm:top-16 flex flex-col items-center justify-center
117+ bg-alien-space-dark/95 z-10"
118+ >
119+ < div className = "relative" >
120+ < div className = "w-20 h-20 rounded-full overflow-hidden border-2 border-alien-gold/50 mb-4" >
121+ < img
122+ src = { aiTorAvatar }
123+ alt = "AI Tor Loading"
124+ className = "w-full h-full object-cover animate-pulse"
125+ />
126+ </ div >
127+ < Loader2 className = "absolute -bottom-1 -right-1 h-8 w-8 text-alien-gold animate-spin" />
128+ </ div >
129+ < p className = "text-alien-gold font-nasalization text-sm mt-4" > Loading AI Tor...</ p >
130+ < div className = "flex gap-1 mt-3" >
131+ < span className = "w-2 h-2 bg-alien-gold rounded-full animate-bounce" style = { { animationDelay : '0ms' } } />
132+ < span className = "w-2 h-2 bg-alien-gold rounded-full animate-bounce" style = { { animationDelay : '150ms' } } />
133+ < span className = "w-2 h-2 bg-alien-gold rounded-full animate-bounce" style = { { animationDelay : '300ms' } } />
134+ </ div >
135+ </ motion . div >
136+ ) }
137+ </ AnimatePresence >
138+
91139 { /* iframe Content */ }
92140 < iframe
93141 src = "https://aitor.lovable.app/"
94142 className = "w-full h-[calc(100%-3.5rem)] sm:h-[calc(100%-4rem)] border-none bg-alien-space-dark"
95143 title = "AI Tor Assistant"
96144 allow = "microphone; camera"
145+ onLoad = { handleIframeLoad }
97146 onError = { ( ) => {
147+ setIsLoading ( false ) ;
98148 toast . error ( 'AI Assistant Error' , {
99149 description : 'Failed to load AI assistant. Please try again.'
100150 } ) ;
0 commit comments