Files
KLC-Website-Frontend/src/components/Chatbot.tsx
priyanshuvish b9bf8ce99e first commit
2025-08-28 13:14:51 +05:30

250 lines
11 KiB
TypeScript

import React, { useState, useRef, useEffect } from 'react';
import { MessageCircle, X, Send, User, Bot, Minimize2 } from 'lucide-react';
import { Button } from './ui/button';
import exampleImage from 'figma:asset/a28d79dd35b730f689b77dbb30452ca27bd25759.png';
interface Message {
id: string;
text: string;
sender: 'user' | 'bot';
timestamp: Date;
}
export function Chatbot() {
const [isOpen, setIsOpen] = useState(false);
const [messages, setMessages] = useState<Message[]>([
{
id: '1',
text: 'Hello! I\'m here to help you learn more about Kautilya Leadership Centre. How can I assist you today?',
sender: 'bot',
timestamp: new Date()
}
]);
const [inputValue, setInputValue] = useState('');
const [isTyping, setIsTyping] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
scrollToBottom();
}, [messages]);
const predefinedResponses: { [key: string]: string } = {
'hello': 'Hello! Welcome to Kautilya Leadership Centre. I\'m here to help you with information about our programs, services, and how we can support your leadership development journey.',
'programs': 'We offer comprehensive leadership development programs including executive coaching, team development, strategic leadership training, and virtual learning experiences. Would you like to know more about any specific program?',
'services': 'Our services include Leadership Development, Executive Coaching, Team Building, Strategic Planning, Organizational Development, and Virtual Learning Platforms. Each is designed to enhance leadership capabilities.',
'contact': 'You can reach us through our contact form on the website, or feel free to schedule a consultation. We\'d be happy to discuss how we can support your leadership development goals.',
'virtual': 'Our virtual learning platform offers flexible, interactive leadership development experiences. You can access courses, participate in live sessions, and connect with other leaders from anywhere.',
'coaching': 'Our executive coaching program provides personalized one-on-one guidance to help leaders develop their skills, overcome challenges, and achieve their professional goals.',
'team': 'Our team development services focus on building high-performing teams through collaborative workshops, communication training, and strategic alignment exercises.',
'webinar': 'Join our upcoming leadership webinars! We regularly host sessions covering various leadership topics. Check our webinars section for schedules and registration.',
'default': 'That\'s a great question! For detailed information about our specific programs and services, I\'d recommend exploring our website or contacting our team directly. Is there anything specific about leadership development I can help you with?'
};
const getBotResponse = (userMessage: string): string => {
const lowerMessage = userMessage.toLowerCase();
for (const [key, response] of Object.entries(predefinedResponses)) {
if (key !== 'default' && lowerMessage.includes(key)) {
return response;
}
}
return predefinedResponses.default;
};
const handleSendMessage = async () => {
if (!inputValue.trim()) return;
const userMessage: Message = {
id: Date.now().toString(),
text: inputValue,
sender: 'user',
timestamp: new Date()
};
setMessages(prev => [...prev, userMessage]);
setInputValue('');
setIsTyping(true);
// Simulate typing delay
setTimeout(() => {
const botMessage: Message = {
id: (Date.now() + 1).toString(),
text: getBotResponse(inputValue),
sender: 'bot',
timestamp: new Date()
};
setMessages(prev => [...prev, botMessage]);
setIsTyping(false);
}, 1500);
};
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSendMessage();
}
};
const formatTime = (date: Date) => {
return date.toLocaleTimeString('en-US', {
hour: '2-digit',
minute: '2-digit',
hour12: true
});
};
return (
<>
{/* Chatbot Toggle Button */}
<div className="fixed bottom-6 right-6 z-50">
<button
onClick={() => setIsOpen(!isOpen)}
className="w-16 h-16 rounded-full shadow-xl transition-all duration-300 hover:scale-105 focus:outline-none focus:ring-4 focus:ring-blue-300 chatbot-button"
style={{
backgroundColor: '#04045B',
boxShadow: '0 8px 32px rgba(4, 4, 91, 0.3)'
}}
aria-label="Open chat"
>
{isOpen ? (
<X className="w-7 h-7 text-white mx-auto" />
) : (
<MessageCircle className="w-7 h-7 text-white mx-auto" />
)}
</button>
</div>
{/* Chatbot Window */}
{isOpen && (
<div
className="fixed bottom-24 right-6 w-80 bg-white rounded-2xl shadow-2xl border-0 z-50 flex flex-col overflow-hidden"
style={{
height: '500px',
boxShadow: '0 25px 50px -12px rgba(0, 0, 0, 0.25), 0 0 0 1px rgba(255, 255, 255, 0.1)'
}}
>
{/* Header with gradient background */}
<div
className="p-6 flex items-center justify-between relative"
style={{
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
borderRadius: '16px 16px 0 0'
}}
>
<div className="flex items-center space-x-3">
<div className="w-10 h-10 bg-white/20 backdrop-blur-sm rounded-full flex items-center justify-center">
<Bot className="w-6 h-6 text-white" />
</div>
<div>
<h3 className="text-white font-semibold text-lg">Welcome to KLC</h3>
<p className="text-white/80 text-sm">How can I help you today?</p>
</div>
</div>
<div className="flex items-center space-x-2">
<button
onClick={() => setIsOpen(false)}
className="text-white/70 hover:text-white transition-colors p-1"
>
<Minimize2 className="w-4 h-4" />
</button>
<button
onClick={() => setIsOpen(false)}
className="text-white/70 hover:text-white transition-colors p-1"
>
<X className="w-5 h-5" />
</button>
</div>
</div>
{/* Messages Container */}
<div className="flex-1 p-5 overflow-y-auto space-y-4" style={{ backgroundColor: '#f8fafc' }}>
{messages.map((message) => (
<div
key={message.id}
className={`flex ${message.sender === 'user' ? 'justify-end' : 'justify-start'}`}
>
<div className={`flex items-start space-x-3 max-w-[85%] ${message.sender === 'user' ? 'flex-row-reverse space-x-reverse' : ''}`}>
<div className={`w-8 h-8 rounded-full flex items-center justify-center flex-shrink-0 ${
message.sender === 'user'
? 'bg-gradient-to-r from-blue-500 to-purple-600'
: 'bg-gradient-to-r from-purple-500 to-pink-500'
}`}>
{message.sender === 'user' ? (
<User className="w-4 h-4 text-white" />
) : (
<Bot className="w-4 h-4 text-white" />
)}
</div>
<div>
<div className={`p-4 rounded-2xl ${
message.sender === 'user'
? 'bg-gradient-to-r from-blue-500 to-purple-600 text-white'
: 'bg-white text-gray-800 shadow-sm border border-gray-100'
}`}>
<p className="text-sm leading-relaxed">{message.text}</p>
</div>
<p className="text-xs text-gray-400 mt-2 px-2">
{formatTime(message.timestamp)}
</p>
</div>
</div>
</div>
))}
{/* Typing Indicator */}
{isTyping && (
<div className="flex justify-start">
<div className="flex items-start space-x-3">
<div className="w-8 h-8 rounded-full bg-gradient-to-r from-purple-500 to-pink-500 flex items-center justify-center">
<Bot className="w-4 h-4 text-white" />
</div>
<div className="bg-white p-4 rounded-2xl shadow-sm border border-gray-100">
<div className="flex space-x-1">
<div className="w-2 h-2 bg-purple-400 rounded-full animate-bounce"></div>
<div className="w-2 h-2 bg-purple-400 rounded-full animate-bounce" style={{ animationDelay: '0.1s' }}></div>
<div className="w-2 h-2 bg-purple-400 rounded-full animate-bounce" style={{ animationDelay: '0.2s' }}></div>
</div>
</div>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
{/* Input Area */}
<div className="p-5 bg-white border-t border-gray-100">
<div className="flex space-x-3">
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Type your message..."
className="flex-1 px-4 py-3 border border-gray-200 rounded-xl focus:outline-none focus:ring-2 focus:ring-purple-500 focus:border-transparent text-sm bg-gray-50"
style={{ fontFamily: 'var(--font-family-brand)' }}
/>
<button
onClick={handleSendMessage}
disabled={!inputValue.trim()}
className="px-4 py-3 rounded-xl text-white transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed focus:outline-none focus:ring-2 focus:ring-purple-500"
style={{
background: inputValue.trim()
? 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'
: '#e5e7eb'
}}
>
<Send className="w-5 h-5" />
</button>
</div>
</div>
</div>
)}
</>
);
}