177 lines
7.4 KiB
TypeScript
177 lines
7.4 KiB
TypeScript
import React, { useRef, useEffect } from 'react';
|
|
import { Button } from '@/components/ui/button';
|
|
import { useTheme } from '../contexts/ThemeContext';
|
|
import { FiMenu, FiX, FiHelpCircle, FiUsers, FiDollarSign, FiZap, FiExternalLink, FiMoon, FiSun } from 'react-icons/fi';
|
|
import { TbMessageChatbot } from "react-icons/tb";
|
|
import { LucideCodeXml } from 'lucide-react';
|
|
import { useNavigate } from "react-router-dom";
|
|
|
|
interface LeftSidebarProps {
|
|
onPromptSelect: (prompt: string, content: any) => void;
|
|
onStartNewChat?: () => void; // Add this prop
|
|
}
|
|
|
|
const suggestedQuestions = [
|
|
{ text: "What is MCP?", icon: FiHelpCircle },
|
|
{ text: "Who is this for?", icon: FiUsers },
|
|
{ text: "Show me how I can earn", icon: FiDollarSign },
|
|
{ text: "What can you help me with?", icon: FiZap },
|
|
];
|
|
|
|
const navLinks = [
|
|
{ text: "Chat", icon: TbMessageChatbot , to: "#" },
|
|
{ text: "Home", icon: FiHelpCircle, to: "#home" },
|
|
{ text: "MCPs", icon: FiUsers, to: "#mcps" },
|
|
{ text: "Monetize", icon: FiDollarSign, to: "#monetize" },
|
|
];
|
|
|
|
const LeftSidebar: React.FC<LeftSidebarProps> = ({ onPromptSelect, onStartNewChat }) => {
|
|
const { sidebarOpen, setSidebarOpen } = useTheme();
|
|
const { isDark, toggleTheme } = useTheme();
|
|
const sidebarRef = useRef<HTMLDivElement>(null);
|
|
const navigate = useNavigate();
|
|
|
|
// Close sidebar on outside click
|
|
useEffect(() => {
|
|
if (!sidebarOpen) return;
|
|
const handleClickOutside = (event: MouseEvent) => {
|
|
if (
|
|
sidebarRef.current &&
|
|
!sidebarRef.current.contains(event.target as Node)
|
|
) {
|
|
setSidebarOpen(false);
|
|
}
|
|
};
|
|
document.addEventListener('mousedown', handleClickOutside);
|
|
return () => {
|
|
document.removeEventListener('mousedown', handleClickOutside);
|
|
};
|
|
}, [sidebarOpen, setSidebarOpen]);
|
|
|
|
const handlePromptClick = (prompt: string) => {
|
|
// Dispatch a custom event to notify ChatInterface
|
|
const event = new CustomEvent('leftSidebarPrompt', { detail: { prompt } });
|
|
window.dispatchEvent(event);
|
|
|
|
// Trigger the same logic as in ChatInterface
|
|
onPromptSelect(prompt, null);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
{/* Toggle Button */}
|
|
{!sidebarOpen && (
|
|
<Button
|
|
variant="ghost"
|
|
onClick={() => setSidebarOpen(true)}
|
|
className="fixed top-24 left-4 z-50 w-10 h-10 rounded-xl border border-gray-200/20 dark:border-gray-700/20 backdrop-blur-md bg-white/80 dark:bg-black/80 hover:bg-white/90 dark:hover:bg-black/90 transition-all duration-300 shadow-lg"
|
|
>
|
|
<FiMenu className="w-4 h-4" />
|
|
</Button>
|
|
)}
|
|
|
|
{/* Sidebar */}
|
|
<div
|
|
ref={sidebarRef}
|
|
className={`fixed left-0 top-0 bg-clip-padding backdrop-filter backdrop-blur-sm bg-opacity-10 border border-gray-200/20 dark:border-gray-700/20 h-screen w-72 transform transition-transform duration-500 ease-in-out z-40 ${
|
|
sidebarOpen ? 'translate-x-0' : '-translate-x-full'
|
|
}`}
|
|
>
|
|
<div className="h-full border-r border-gray-200/20 dark:border-gray-700/20 bg-clip-padding backdrop-filter backdrop-blur-sm bg-white/20 dark:bg-black/20 bg-opacity-40 flex flex-col">
|
|
{/* Top Section: Logo, Navigation, Theme Toggle */}
|
|
<div className="p-6 pb-2 flex items-cneter justify-between">
|
|
{/* Logo */}
|
|
<div className="flex items-center gap-2">
|
|
{/* <img src="/logo.svg" alt="Logo" className="w-8 h-8" /> */}
|
|
<LucideCodeXml />
|
|
<span className="text-lg text-gray-900 dark:text-white">FastCode</span>
|
|
</div>
|
|
{/* Theme Toggle */}
|
|
<Button
|
|
variant="ghost"
|
|
size="sm"
|
|
onClick={toggleTheme}
|
|
className="w-10 h-10 rounded-full border border-gray-200/20 dark:border-gray-700/20 backdrop-blur-sm bg-white/10 dark:bg-black/10 hover:bg-white/20 dark:hover:bg-black/20 transition-all duration-300"
|
|
aria-label="Toggle theme"
|
|
>
|
|
{isDark ? <FiSun className="w-4 h-4" /> : <FiMoon className="w-4 h-4" />}
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Questions */}
|
|
<div className="px-6 mb-6">
|
|
<h3 className="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-4 mt-4">
|
|
Quick Start
|
|
</h3>
|
|
<div className="space-y-2">
|
|
{suggestedQuestions.map((question, index) => (
|
|
<button
|
|
key={index}
|
|
onClick={() => handlePromptClick(question.text)}
|
|
className="w-full flex justify-start p-4 h-auto text-left border-0 bg-transparent text-gray-500 hover:text-black transition-colors duration-200 group"
|
|
>
|
|
<question.icon className="w-4 h-4 mr-3 text-gray-400 group-hover:text-black dark:group-hover:text-white transition-colors" />
|
|
<span className="text-sm text-gray-500 dark:text-gray-400 group-hover:text-black dark:group-hover:text-white transition-colors">
|
|
{question.text}
|
|
</span>
|
|
</button>
|
|
))}
|
|
</div>
|
|
{/* Start New Chat Button */}
|
|
<Button
|
|
variant="outline"
|
|
className="w-full"
|
|
onClick={onStartNewChat}
|
|
>
|
|
Start New Chat
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Nav Section */}
|
|
<div className="flex-1 flex flex-col justify-between">
|
|
{/* Nav menu */}
|
|
<div className="px-6">
|
|
<h3 className="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-4 mt-4">
|
|
Navigation
|
|
</h3>
|
|
{navLinks.map((nav, index) => (
|
|
<a
|
|
href={nav.to}
|
|
key={index}
|
|
className="w-full flex justify-start p-4 h-auto text-left border-0 bg-transparent text-gray-500 hover:text-black transition-colors duration-200 group"
|
|
>
|
|
<nav.icon className="w-4 h-4 mr-3 text-gray-400 group-hover:text-black dark:group-hover:text-white transition-colors" />
|
|
<span className="text-sm text-gray-500 dark:text-gray-400 group-hover:text-black dark:group-hover:text-white transition-colors">
|
|
{nav.text}
|
|
</span>
|
|
</a>
|
|
))}
|
|
</div>
|
|
|
|
{/* Visit Website */}
|
|
<div className="p-6 mt-auto">
|
|
<h3 className="text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider mb-4">
|
|
Resources
|
|
</h3>
|
|
<Button
|
|
variant="ghost"
|
|
asChild
|
|
className="w-full justify-start p-4 h-auto text-left border-0 bg-transparent text-gray-500 hover:text-black dark:text-gray-400 dark:hover:text-white transition-colors duration-200 group"
|
|
>
|
|
<a href="https://yourdomain.com" target="_blank" rel="noopener noreferrer">
|
|
<FiExternalLink className="w-4 h-4 mr-3 text-gray-400 group-hover:text-black dark:group-hover:text-white transition-colors" />
|
|
<span className="text-sm text-gray-500 dark:text-gray-400 group-hover:text-black dark:group-hover:text-white transition-colors">
|
|
Visit Website
|
|
</span>
|
|
</a>
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default LeftSidebar;
|