import React, { useState, useEffect } from 'react';
import { MessageCircle, HelpCircle, Activity, Settings, Trash2 } from 'lucide-react';
// Mock components if you don't have the actual UI components
const Alert = ({ children, variant }) => (
{children}
);
const AlertTitle = ({ children }) => {children}
;
const AlertDescription = ({ children }) => {children}
;
const Dialog = ({ open, children }) => open ? {children}
: null;
const DialogContent = ({ children }) => {children}
;
const DialogHeader = ({ children }) => {children}
;
const DialogTitle = ({ children }) => {children}
;
const DialogFooter = ({ children }) => {children}
;
const Input = (props) => ;
const Button = ({ children, ...props }) => (
);
// Error Boundary Component
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error("Caught an error:", error, errorInfo);
}
render() {
if (this.state.hasError) {
return Something went wrong. Please refresh the page.
;
}
return this.props.children;
}
}
const GeminiChatInterface = () => {
const [conversations, setConversations] = useState([{ id: Date.now(), messages: [] }]);
const [currentMessage, setCurrentMessage] = useState('');
const [apiKey, setApiKey] = useState('');
const [isSettingsOpen, setIsSettingsOpen] = useState(false);
const [error, setError] = useState('');
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
try {
const savedApiKey = localStorage.getItem('geminiApiKey');
if (savedApiKey) {
setApiKey(savedApiKey);
}
} catch (err) {
console.error("Error accessing localStorage:", err);
}
}, []);
const handleNewChat = () => {
setConversations(prev => [...prev, { id: Date.now(), messages: [] }]);
};
const handleDeleteChat = (id) => {
setConversations(prev => prev.filter(conv => conv.id !== id));
};
const handleSendMessage = async () => {
if (!apiKey) {
setError('Please set up your API key in Settings first.');
return;
}
if (currentMessage.trim()) {
setIsLoading(true);
setError('');
setConversations(prev => {
const updated = [...prev];
const current = updated[updated.length - 1];
current.messages.push({
text: currentMessage,
sender: 'user'
});
return updated;
});
setCurrentMessage('');
try {
const response = await fetch('https://generativelanguage.googleapis.com/v1beta/models/gemini-1.0-pro:generateContent', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify({
contents: [{
parts: [{
text: currentMessage
}]
}]
})
});
if (!response.ok) {
throw new Error(`Error in Gemini API response. Status: ${response.status}`);
}
const data = await response.json();
if (!data.candidates || data.candidates.length === 0 || !data.candidates[0].content || !data.candidates[0].content.parts || data.candidates[0].content.parts.length === 0) {
throw new Error('Unexpected response structure from Gemini API');
}
const aiResponse = data.candidates[0].content.parts[0].text;
setConversations(prev => {
const updated = [...prev];
const current = updated[updated.length - 1];
current.messages.push({
text: aiResponse,
sender: 'ai'
});
return updated;
});
} catch (error) {
console.error('Error:', error);
setError(`Error communicating with Gemini API: ${error.message}`);
} finally {
setIsLoading(false);
}
}
};
const handleKeyPress = (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
handleSendMessage();
}
};
return (
{/* Sidebar */}
Recent
{conversations.map((conv) => (
Conversation {conv.id}
handleDeleteChat(conv.id)}
/>
))}
Help
setIsSettingsOpen(true)}
>
Settings
{/* Main content */}
{/* Top bar */}
{/* Chat area */}
{error && (
Error
{error}
)}
{conversations[conversations.length - 1].messages.map((msg, index) => (
))}
{isLoading &&
Loading...
}
{/* Input area */}
{/* Settings Dialog */}
);
};
export default GeminiChatInterface;