![gpt-engineer-app[bot]](/assets/img/avatar_default.png)
Create a minimal, high-end landing page with a chatbot-like interface, including dark/light mode, prewritten prompts, and animated sidebar. Design should be black and white with glassmorphism and subtle gradients.
156 lines
5.9 KiB
TypeScript
156 lines
5.9 KiB
TypeScript
|
|
import React, { useState, useEffect } from 'react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Input } from '@/components/ui/input';
|
|
import TypingAnimation from './TypingAnimation';
|
|
import { getPromptContent } from '../utils/promptContent';
|
|
|
|
interface ChatInterfaceProps {
|
|
onPromptSelect: (prompt: string, content: any) => void;
|
|
isExpanded: boolean;
|
|
}
|
|
|
|
const prompts = [
|
|
"What can you help me with?",
|
|
"What is MCP?",
|
|
"Who is this for?",
|
|
"Show me how I can earn"
|
|
];
|
|
|
|
const ChatInterface: React.FC<ChatInterfaceProps> = ({ onPromptSelect, isExpanded }) => {
|
|
const [messages, setMessages] = useState<Array<{ text: string; isUser: boolean; isTyping?: boolean }>>([]);
|
|
const [inputValue, setInputValue] = useState('');
|
|
const [isThinking, setIsThinking] = useState(false);
|
|
|
|
const handlePromptClick = (prompt: string) => {
|
|
setMessages(prev => [...prev, { text: prompt, isUser: true }]);
|
|
setIsThinking(true);
|
|
|
|
setTimeout(() => {
|
|
setIsThinking(false);
|
|
setMessages(prev => [...prev, { text: `Let me show you detailed information about "${prompt}"`, isUser: false, isTyping: true }]);
|
|
|
|
setTimeout(() => {
|
|
const content = getPromptContent(prompt);
|
|
onPromptSelect(prompt, content);
|
|
}, 1500);
|
|
}, 1000);
|
|
};
|
|
|
|
const handleSendMessage = () => {
|
|
if (!inputValue.trim()) return;
|
|
|
|
const prompt = inputValue;
|
|
setInputValue('');
|
|
handlePromptClick(prompt);
|
|
};
|
|
|
|
const handleKeyPress = (e: React.KeyboardEvent) => {
|
|
if (e.key === 'Enter') {
|
|
handleSendMessage();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex flex-col h-full p-6">
|
|
{/* Hero Section */}
|
|
{messages.length === 0 && (
|
|
<div className={`flex-1 flex flex-col justify-center items-center text-center transition-all duration-500 ${
|
|
isExpanded ? 'max-w-4xl mx-auto' : 'max-w-2xl mx-auto'
|
|
}`}>
|
|
<div className="mb-8">
|
|
<h1 className="text-4xl md:text-6xl font-bold text-gray-900 dark:text-white mb-6 leading-tight">
|
|
Build an MCP server and become part of the new world
|
|
</h1>
|
|
<p className="text-xl text-gray-600 dark:text-gray-300 mb-8">
|
|
Where AI chatbots are the modern interface
|
|
</p>
|
|
</div>
|
|
|
|
{/* Glassmorphism card with prompts */}
|
|
<div className="w-full max-w-2xl p-8 rounded-3xl border border-gray-200/20 dark:border-gray-700/20 backdrop-blur-xl bg-white/10 dark:bg-black/10 shadow-2xl">
|
|
<h3 className="text-lg font-semibold text-gray-900 dark:text-white mb-6">
|
|
How can I help you today?
|
|
</h3>
|
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
{prompts.map((prompt, index) => (
|
|
<Button
|
|
key={index}
|
|
variant="ghost"
|
|
onClick={() => handlePromptClick(prompt)}
|
|
className="p-4 h-auto text-left justify-start border border-gray-200/20 dark:border-gray-700/20 backdrop-blur-sm bg-white/5 dark:bg-black/5 hover:bg-white/10 dark:hover:bg-black/10 rounded-xl transition-all duration-300 hover:scale-105"
|
|
>
|
|
<span className="text-gray-700 dark:text-gray-300">{prompt}</span>
|
|
</Button>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Chat Messages */}
|
|
{messages.length > 0 && (
|
|
<div className="flex-1 overflow-y-auto space-y-4 mb-6">
|
|
{messages.map((message, index) => (
|
|
<div
|
|
key={index}
|
|
className={`flex ${message.isUser ? 'justify-end' : 'justify-start'}`}
|
|
>
|
|
<div
|
|
className={`max-w-xs lg:max-w-md px-4 py-3 rounded-2xl ${
|
|
message.isUser
|
|
? 'bg-blue-500 text-white'
|
|
: 'border border-gray-200/20 dark:border-gray-700/20 backdrop-blur-xl bg-white/10 dark:bg-black/10 text-gray-900 dark:text-white'
|
|
}`}
|
|
>
|
|
{message.isTyping ? (
|
|
<TypingAnimation text={message.text} />
|
|
) : (
|
|
message.text
|
|
)}
|
|
</div>
|
|
</div>
|
|
))}
|
|
|
|
{isThinking && (
|
|
<div className="flex justify-start">
|
|
<div className="max-w-xs lg:max-w-md px-4 py-3 rounded-2xl border border-gray-200/20 dark:border-gray-700/20 backdrop-blur-xl bg-white/10 dark:bg-black/10 text-gray-900 dark:text-white">
|
|
<div className="flex items-center space-x-2">
|
|
<div className="flex space-x-1">
|
|
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce"></div>
|
|
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0.1s' }}></div>
|
|
<div className="w-2 h-2 bg-gray-400 rounded-full animate-bounce" style={{ animationDelay: '0.2s' }}></div>
|
|
</div>
|
|
<span className="text-sm">AI is thinking...</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
</div>
|
|
)}
|
|
|
|
{/* Input Area */}
|
|
<div className="border border-gray-200/20 dark:border-gray-700/20 backdrop-blur-xl bg-white/10 dark:bg-black/10 rounded-2xl p-4">
|
|
<div className="flex space-x-4">
|
|
<Input
|
|
value={inputValue}
|
|
onChange={(e) => setInputValue(e.target.value)}
|
|
onKeyPress={handleKeyPress}
|
|
placeholder="Ask me anything about MCP..."
|
|
className="flex-1 border-0 bg-transparent focus:ring-0 text-gray-900 dark:text-white placeholder-gray-500 dark:placeholder-gray-400"
|
|
/>
|
|
<Button
|
|
onClick={handleSendMessage}
|
|
disabled={!inputValue.trim()}
|
|
className="bg-blue-500 hover:bg-blue-600 text-white rounded-xl px-6"
|
|
>
|
|
Send
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default ChatInterface;
|