'use client' import React, { useState, useEffect, useRef, useCallback } from 'react'; import { v4 as uuidv4 } from 'uuid'; import Cookies from 'js-cookie'; import { usePrivy, useWallets } from '@privy-io/react-auth'; import { useRouter } from 'next/navigation'; import { Providers } from '@/components/providers/privy-provider'; import { StarredChat } from '@/components/chat/sidebar/StarredChat'; import { SidebarHeader } from '@/components/chat/sidebar/SidebarHeader'; import { IntegrationButton } from '@/components/chat/IntegrationButton'; import { ChatInput } from '@/components/chat/ChatInput'; import { WelcomeHeader } from '@/components/chat/WelcomeHeader'; import MessageBubble from '@/components/chat/MessageBubble'; import { motion, AnimatePresence } from 'framer-motion'; import { Settings, LogOut, Compass ,Landmark, Wrench, ScanSearch, Computer } from 'lucide-react'; import Avatar, { genConfig } from 'react-nice-avatar'; import logo from "@/public/assets/logo/landing-logo-blue.png" import { NICKNAMES } from '@/components/chat/constants/nicknames'; interface Message { id: string; role: 'user' | 'assistant' | 'system'; content: string; timestamp: string; } interface Conversation { id: string; title: string; date: string; messages: Message[]; isStarred: boolean; } function DashboardContent() { const [conversations, setConversations] = useState([]); const [messages, setMessages] = useState([]); const [input, setInput] = useState(''); const [isLoading, setIsLoading] = useState(false); const [sessionId, setSessionId] = useState(() => uuidv4()); const [currentConversation, setCurrentConversation] = useState(null); const [isMobile, setIsMobile] = useState(false); const [isSidebarOpen, setSidebarOpen] = useState(false); const messagesEndRef = useRef(null); const [showLogout, setShowLogout] = useState(false); const [userName, setUserName] = useState('SOVIRO'); const [avatarConfig, setAvatarConfig] = useState(() => genConfig()); const { ready, authenticated, logout: privyLogout } = usePrivy(); const router = useRouter(); const { wallets } = useWallets(); const sidebarTimeoutRef = useRef(); const [isLongResponse, setIsLongResponse] = useState(false); //Random Username Generator useEffect(() => { const randomIndex = Math.floor(Math.random() * NICKNAMES.length); const selectedName = NICKNAMES[randomIndex]; setUserName(selectedName); setAvatarConfig(genConfig(selectedName)); }, []); useEffect(() => { const handleResize = () => { const mobile = window.innerWidth <= 768; setIsMobile(mobile); setSidebarOpen(false); }; handleResize(); window.addEventListener('resize', handleResize); return () => window.removeEventListener('resize', handleResize); }, []); const scrollToBottom = useCallback(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, []); const startNewChat = useCallback(() => { const newSessionId = uuidv4(); setSessionId(newSessionId); setMessages([]); setCurrentConversation(null); setSidebarOpen(false); // Force scroll to input setTimeout(() => { const inputElement = document.querySelector('input[type="text"]'); (inputElement as HTMLInputElement)?.focus(); }, 100); }, [isMobile]); const handleStarChat = useCallback((id: string) => { setConversations(prev => prev.map(conv => conv.id === id ? { ...conv, isStarred: !conv.isStarred } : conv )); }, []); const loadConversation = useCallback((conversation: Conversation) => { setSessionId(conversation.id); setMessages(conversation.messages); setCurrentConversation(conversation); if (isMobile) setSidebarOpen(false); }, [isMobile]); // Removed unused deleteConversation function const handleSidebarHover = (isHovering: boolean) => { if (isMobile) return; if (sidebarTimeoutRef.current) { clearTimeout(sidebarTimeoutRef.current); } if (isHovering) { setSidebarOpen(true); } else { sidebarTimeoutRef.current = setTimeout(() => { setSidebarOpen(false); }, 300); // Small delay before closing } }; useEffect(() => { if (ready && !authenticated) { router.push('/'); } }, [ready, authenticated, router]); const handleLogout = useCallback(async () => { try { // Disconnect any connected wallets first for (const wallet of wallets) { try { await wallet.disconnect(); } catch (e) { console.error('Error disconnecting wallet:', e); } } // Remove cookie before Privy logout to prevent race conditions Cookies.remove('privy-authenticated', { path: '/' }); // Perform Privy logout await privyLogout(); // Clear any local storage items localStorage.removeItem('privy:embedded-wallet:iframe-ready'); localStorage.removeItem('privy:embedded-wallet:ready'); // Redirect to auth page router.push('/'); } catch (error) { console.error('Logout error:', error); // Ensure redirect happens even if there's an error router.push('/'); } }, [privyLogout, router, wallets]); // console.log("Cook: ",Cookies.get("privy-authenticated")) const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!input.trim() || isLoading) return; const userMessage: Message = { id: uuidv4(), role: 'user', content: input, timestamp: new Date().toISOString() }; setMessages(prev => [...prev, userMessage]); setInput(''); setIsLoading(true); const timer = setTimeout(() => { setIsLongResponse(true); }, 10000); scrollToBottom(); try { const response = await fetch('/api/chat', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ message: input, sessionId: sessionId, }), }); if (!response.ok) throw new Error('Failed to get response'); const data = await response.json(); const messageContent = processResponse(data); const assistantMessage: Message = { id: uuidv4(), role: 'assistant', content: messageContent, timestamp: new Date().toISOString() }; setMessages(prev => [...prev, assistantMessage]); if (!currentConversation) { const newConversation: Conversation = { id: sessionId, title: input.slice(0, 30) + (input.length > 30 ? '...' : ''), date: new Date().toLocaleDateString(), messages: [userMessage, assistantMessage], isStarred: false }; setConversations(prev => [newConversation, ...prev]); setCurrentConversation(newConversation); } } catch (error) { console.error('Error:', error); setMessages(prev => [...prev, { id: uuidv4(), role: 'system', content: 'Sorry, something went wrong. Please try again.', timestamp: new Date().toISOString() }]); } finally { setIsLoading(false); setIsLongResponse(false); clearTimeout(timer); scrollToBottom(); } }; return (
{/* Always visible sidebar strip */}
handleSidebarHover(true)} onMouseLeave={() => handleSidebarHover(false)} > {/* Thin visible strip when sidebar is closed */}
{isSidebarOpen && (
{/* Starred Chats */}

STARRED CHATS

{conversations .filter(chat => chat.isStarred) .map(chat => ( loadConversation(chat)} onStar={() => handleStarChat(chat.id)} /> ))}
{/* Regular Conversations */}

CONVERSATIONS

{conversations .filter(chat => !chat.isStarred) .map(chat => ( loadConversation(chat)} onStar={() => handleStarChat(chat.id)} /> ))}
{/* User Section with Logout */}
setShowLogout(true)} onMouseLeave={() => setShowLogout(false)} >
{userName}
{sessionId}
{showLogout && ( Logout )}
)}
{/* Main Content Area with proper margin for sidebar strip */}
{/* Main Chat Area */}
{isMobile && ( )}
{messages.length === 0 ? ( <>

Ready to help you with your tasks and questions.

{/* Integration Buttons */}

EXPLORE INTEGRATIONS

setInput("How Soviro actually works?")} /> setInput("Help me design a learning path for becoming a full-stack developer")} /> setInput("What tools and resources would you recommend for learning data science?")} /> setInput("What are the latest trends in artificial intelligence and machine learning?")} /> setInput("Create an HTML/CSS template for a responsive portfolio website")} />
) : (
{messages.map((message, i) => ( ))} {isLoading && ( {/* Dots animation */}
{/* Processing message that appears after delay */} {isLongResponse && ( Hold on a moment... )}
)}
)}
); } // Helper function to process API response function processResponse(data: { response: string; agent_responses?: { agent: string; response: string }[] }): string { try { const responseObj = JSON.parse(data.response); let messageContent = ''; const compassResponse = responseObj.agent_responses?.find( (response: { agent: string }) => response.agent === "compass" ); if (compassResponse) { messageContent = compassResponse.response; } else { // Process Scout Response const scoutResponse = responseObj.agent_responses?.find( (response: { agent: string }) => response.agent === "scout" ); if (scoutResponse) { try { const researchData = JSON.parse(scoutResponse.response); messageContent = researchData.message || scoutResponse.response; } catch { messageContent = scoutResponse.response; } messageContent = messageContent .replace(/\b(bound)\b/gi, '**$1**') .replace(/(bound)/gi, '**$1**'); } // Process Tech Sage Response const techSageResponse = responseObj.agent_responses?.find( (response: { agent: string }) => response.agent === "techsage" ); if (techSageResponse) { try { const engineerData = JSON.parse(techSageResponse.response); messageContent = formatEngineerResponse(engineerData); } catch (parseError) { console.error('Error parsing techsage response:', parseError); messageContent = techSageResponse.response; } } } return messageContent || 'Received a response but couldn\'t process it properly.'; } catch (error) { console.error('Error processing response:', error); return data.response; } } // Helper function to format engineer response function formatEngineerResponse(engineerData: { status: string; message: string; suggestions?: string[]; query: string; analysis: { task_type: string; language: string; technologies: string[] }; implementation: { files: { filename: string; language: string; content: string }[]; setup?: string; usage?: string; api_docs?: string; configuration?: string }; files_created?: string[] }): string { if (engineerData.status === "error") { let content = `⚠️ Error: ${engineerData.message}\n\n`; if (engineerData.suggestions?.length) { content += "Suggestions:\n"; engineerData.suggestions.forEach((suggestion: string) => { content += `- ${suggestion}\n`; }); } return content; } let content = `# ${engineerData.query}\n\n`; content += `## Project Analysis\n`; content += `- Type: ${engineerData.analysis.task_type}\n`; content += `- Language: ${engineerData.analysis.language}\n`; content += `- Technologies: ${engineerData.analysis.technologies.join(", ")}\n\n`; content += `## Implementation\n\n`; engineerData.implementation.files.forEach((file: { filename: string; language: string; content: string }) => { content += `### File: ${file.filename}\n`; content += `\`\`\`${file.language}\n${file.content}\n\`\`\`\n\n`; }); if (engineerData.implementation.setup) { content += `## Setup Instructions\n${engineerData.implementation.setup}\n\n`; } if (engineerData.implementation.usage) { content += `## Usage Examples\n${engineerData.implementation.usage}\n\n`; } if (engineerData.implementation.api_docs) { content += `## API Documentation\n${engineerData.implementation.api_docs}\n\n`; } if (engineerData.implementation.configuration) { content += `## Configuration\n${engineerData.implementation.configuration}\n\n`; } if (engineerData.files_created?.length) { content += `## Files Created\n`; engineerData.files_created.forEach((file: string) => { content += `- \`${file}\`\n`; }); } return content; } export default function Dashboard() { return ( ); }