import React, { useCallback, useEffect, useMemo, useRef, useState, } from "react"; import { TrashIcon, SparklesIcon, PaperClipIcon, MicrophoneIcon, PaperAirplaneIcon, ArrowPathIcon, DocumentDuplicateIcon, ChatBubbleLeftRightIcon, CommandLineIcon, } from "@heroicons/react/24/outline"; import ReactMarkdown from "react-markdown"; import remarkGfm from "remark-gfm"; // Internal hooks/types import { useChat } from "./useChat"; import type { ThreadMeta } from "./threads"; // --- Constants & Config --- const APP_TITLE = "Krishna's Digital Twin"; const BOT_AVATAR = "https://api.dicebear.com/9.x/bottts-neutral/svg?seed=Krishna1&backgroundColor=6366f1"; // Cleaner 3D-ish Robot /* const DID_YOU_KNOW = [ "Krishna achieved a 3.95 GPA during his M.S. at Virginia Tech.", "Krishna built an agent that automates Android UI tasks with 80%+ accuracy.", "Krishna optimized genomic ETL pipelines reducing runtime by 70%.", "Krishna specializes in building autonomous agents and RAG systems.", ]; */ const SUGGESTIONS = [ { title: "Summarize Experience", text: "Give me a 90-second intro to Krishna Vamsi Dhulipalla—recent work, top strengths, and impact.", icon: "✨", }, { title: "Download Resume", text: "Share Krishna’s latest resume and provide a download link.", icon: "📄", }, { title: "Capabilities", text: "What tools and actions can you perform for me?", icon: "🛠️", }, { title: "Schedule Meeting", text: "Schedule a 30-minute meeting with Krishna next week.", icon: "📅", }, ]; /* function DidYouKnowRotator() { const [index, setIndex] = useState(0); useEffect(() => { const interval = setInterval(() => { setIndex((prev) => (prev + 1) % DID_YOU_KNOW.length); }, 5000); // Rotate every 5 seconds return () => clearInterval(interval); }, []); return (

Did you know?

"{DID_YOU_KNOW[index]}"

); } */ // --- Helper: Date Grouping for Sidebar --- function groupThreadsByDate(threads: ThreadMeta[]) { const today = new Date(); const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1); const groups: Record = { Today: [], Yesterday: [], "Previous 7 Days": [], Older: [], }; threads.forEach((t) => { const d = new Date(t.lastAt); if (d.toDateString() === today.toDateString()) { groups["Today"].push(t); } else if (d.toDateString() === yesterday.toDateString()) { groups["Yesterday"].push(t); } else if (d.getTime() > today.getTime() - 7 * 24 * 60 * 60 * 1000) { groups["Previous 7 Days"].push(t); } else { groups["Older"].push(t); } }); return groups; } // --- Main Component --- export default function App() { const { threads, active, messages, setActiveThread, newChat, clearChat, deleteThread, send, isStreaming, hasFirstToken, } = useChat(); const [input, setInput] = useState(""); const bottomRef = useRef(null); const inputRef = useRef(null); const prevThreadId = useRef(null); // --- Voice Input Logic --- const [isListening, setIsListening] = useState(false); const recognitionRef = useRef(null); useEffect(() => { const SpeechRecognition = (window as any).SpeechRecognition || (window as any).webkitSpeechRecognition; if (SpeechRecognition) { recognitionRef.current = new SpeechRecognition(); recognitionRef.current.continuous = false; recognitionRef.current.interimResults = false; recognitionRef.current.lang = "en-US"; recognitionRef.current.onresult = (event: any) => { const transcript = event.results[0][0].transcript; setInput((prev) => (prev ? prev + " " + transcript : transcript)); setIsListening(false); }; recognitionRef.current.onerror = (event: any) => { console.error("Speech recognition error", event.error); setIsListening(false); }; recognitionRef.current.onend = () => { setIsListening(false); }; } }, []); const toggleListening = useCallback(() => { if (!recognitionRef.current) { alert("Browser does not support Speech Recognition"); return; } if (isListening) { recognitionRef.current.stop(); setIsListening(false); } else { recognitionRef.current.start(); setIsListening(true); } }, [isListening]); // Auto-scroll logic useEffect(() => { const currentThreadId = active?.id ?? null; if (currentThreadId !== prevThreadId.current) { prevThreadId.current = currentThreadId; bottomRef.current?.scrollIntoView({ behavior: "auto" }); } else { bottomRef.current?.scrollIntoView({ behavior: "smooth" }); } }, [messages, active?.id]); const sendMessage = useCallback(() => { const text = input.trim(); if (!text || isStreaming) return; send(text); setInput(""); }, [input, isStreaming, send]); const handleKeyDown = useCallback( (e: React.KeyboardEvent) => { if (e.key === "Enter" && !e.shiftKey) { e.preventDefault(); sendMessage(); } }, [sendMessage] ); const groupedThreads = useMemo(() => groupThreadsByDate(threads), [threads]); return (
{/* Background Ambience */}
{/* --- Sidebar --- */} {/* --- Main Chat Area --- */}
{/* Top Navigation */}
Bot

{APP_TITLE}

Online & Ready

{/* Chat Stream */}
{messages.length === 0 ? (

How can I help you today?

I'm Krishna's digital twin. Ask me about his architecture skills, recent projects, or schedule a meeting.

{/* */} {/*
*/} {/* Suggestions Grid */}
{SUGGESTIONS.map((s, i) => ( ))}
) : (
{messages.map((m, idx) => ( ))} {/* Streaming Indicator */} {isStreaming && !hasFirstToken && (
)}
)}
{/* --- Input Area --- */}