V1Q-WebUI / V1Q
YuRiVeRTi's picture
Create V1Q
fcbbe44 verified
import React, { useState, useRef, useEffect } from 'react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Send, Bot, User, Loader2 } from 'lucide-react';
interface Message {
id: string;
content: string;
role: 'user' | 'assistant';
timestamp: Date;
}
const ChatBot = () => {
const [messages, setMessages] = useState<Message[]>([
{
id: '1',
content: 'Hello! I\'m your AI assistant powered by V1Q. How can I help you today?',
role: 'assistant',
timestamp: new Date()
}
]);
const [input, setInput] = useState('');
const [isLoading, setIsLoading] = useState(false);
const messagesEndRef = useRef<HTMLDivElement>(null);
const scrollToBottom = () => {
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
};
useEffect(() => {
scrollToBottom();
}, [messages]);
const sendMessage = async () => {
if (!input.trim() || isLoading) return;
const userMessage: Message = {
id: Date.now().toString(),
content: input,
role: 'user',
timestamp: new Date()
};
setMessages(prev => [...prev, userMessage]);
setInput('');
setIsLoading(true);
try {
// Simulate API call to V1Q model
await new Promise(resolve => setTimeout(resolve, 1000 + Math.random() * 2000));
const assistantMessage: Message = {
id: (Date.now() + 1).toString(),
content: generateResponse(input),
role: 'assistant',
timestamp: new Date()
};
setMessages(prev => [...prev, assistantMessage]);
} catch (error) {
console.error('Error sending message:', error);
const errorMessage: Message = {
id: (Date.now() + 1).toString(),
content: 'Sorry, I encountered an error. Please try again.',
role: 'assistant',
timestamp: new Date()
};
setMessages(prev => [...prev, errorMessage]);
} finally {
setIsLoading(false);
}
};
const generateResponse = (userInput: string): string => {
// Simple response generation for demo purposes
const responses = [
"That's an interesting question! Let me help you with that.",
"I understand what you're asking. Here's what I think...",
"Great question! Based on my knowledge, I can tell you that...",
"I'd be happy to help you with that. Here's my response...",
"That's a thoughtful inquiry. Let me provide you with some insights..."
];
return responses[Math.floor(Math.random() * responses.length)] +
` Regarding "${userInput}", I'm processing this with the V1Q model to provide you with the most accurate response possible.`;
};
const handleKeyPress = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
};
return (
<div className="max-w-4xl mx-auto h-[600px] flex flex-col">
<Card className="flex-1 flex flex-col">
<CardHeader className="border-b">
<CardTitle className="flex items-center gap-2">
<Bot className="h-6 w-6 text-primary" />
AI Assistant (V1Q)
</CardTitle>
</CardHeader>
<CardContent className="flex-1 flex flex-col p-0">
<div className="flex-1 overflow-y-auto p-4 space-y-4">
{messages.map((message) => (
<div
key={message.id}
className={`flex gap-3 ${
message.role === 'user' ? 'justify-end' : 'justify-start'
}`}
>
<div
className={`flex gap-3 max-w-[80%] ${
message.role === 'user' ? 'flex-row-reverse' : 'flex-row'
}`}
>
<div className="flex-shrink-0">
{message.role === 'user' ? (
<div className="w-8 h-8 bg-primary rounded-full flex items-center justify-center">
<User className="h-4 w-4 text-primary-foreground" />
</div>
) : (
<div className="w-8 h-8 bg-secondary rounded-full flex items-center justify-center">
<Bot className="h-4 w-4 text-secondary-foreground" />
</div>
)}
</div>
<div
className={`rounded-lg p-3 ${
message.role === 'user'
? 'bg-primary text-primary-foreground'
: 'bg-muted text-muted-foreground'
}`}
>
<p className="text-sm">{message.content}</p>
<p className="text-xs opacity-70 mt-1">
{message.timestamp.toLocaleTimeString([], {
hour: '2-digit',
minute: '2-digit'
})}
</p>
</div>
</div>
</div>
))}
{isLoading && (
<div className="flex gap-3 justify-start">
<div className="flex gap-3 max-w-[80%]">
<div className="w-8 h-8 bg-secondary rounded-full flex items-center justify-center">
<Bot className="h-4 w-4 text-secondary-foreground" />
</div>
<div className="rounded-lg p-3 bg-muted">
<div className="flex items-center gap-2">
<Loader2 className="h-4 w-4 animate-spin" />
<span className="text-sm text-muted-foreground">Thinking...</span>
</div>
</div>
</div>
</div>
)}
<div ref={messagesEndRef} />
</div>
<div className="p-4 border-t">
<div className="flex gap-2">
<Input
value={input}
onChange={(e) => setInput(e.target.value)}
onKeyPress={handleKeyPress}
placeholder="Type your message here..."
disabled={isLoading}
className="flex-1"
/>
<Button
onClick={sendMessage}
disabled={!input.trim() || isLoading}
size="icon"
>
<Send className="h-4 w-4" />
</Button>
</div>
</div>
</CardContent>
</Card>
</div>
);
};
export default ChatBot