VocRT / frontend /src /pages /Index.tsx
Anurag
version-2 initial version
5306da4
import { useEffect, useRef, useState } from "react";
import { Link } from "react-router-dom";
import ChatInterface from "@/components/ChatInterface";
import ControlPanel from "@/components/ControlPanel";
import ChatSidebar from "@/components/ChatSidebar";
import VoiceChat from "@/components/VoiceChat";
import { v4 as uuidv4 } from "uuid";
import {
Mic,
MicOff,
Settings,
Menu,
PanelLeft,
PanelLeftClose,
ArrowLeft,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { useAppSelector, useAppDispatch } from "@/redux/hooks";
import { setIsListening, setSidebarVisibility } from "@/redux/slices/chatSlice";
import {
setActiveChat,
createChat,
renameChat,
} from "@/redux/slices/chatsSlice";
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { useIsMobile } from "@/hooks/use-mobile";
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
import { useToast } from "@/hooks/use-toast";
const Index = () => {
const dispatch = useAppDispatch();
const { activeChatMessages, isListening, isSidebarVisible, isChangingChat } =
useAppSelector((state) => state.chat);
const { chats, activeChat } = useAppSelector((state) => state.chats);
const { activeVoice, temperature, maxTokens, embeddingsText } =
useAppSelector((state) => state.settings);
const isMobile = useIsMobile();
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
const [isChatSidebarOpen, setIsChatSidebarOpen] = useState(false);
const [isVoiceChatMode, setIsVoiceChatMode] = useState(true);
const { toast } = useToast();
const [sessionId] = useState(() => {
const savedSessionId = localStorage.getItem("voiceSessionId");
return savedSessionId || uuidv4();
});
const toggleListening = () => {
if (isVoiceChatMode) return;
if (chats.length === 0) {
dispatch(createChat(sessionId));
const chatId = sessionId;
dispatch(setActiveChat(chatId));
toast({
title: "New chat created",
description: "Start a fresh conversation with your AI assistant.",
});
}
dispatch(setIsListening(!isListening));
};
const handleShowSidebar = () => {
dispatch(setSidebarVisibility(true));
};
// const formattedMessages = activeChatMessages.map((msg) => ({
// ...msg,
// // timestamp: new Date().toISOString(),
// }));
const renderSettingsPanel = () => {
if (isListening && !isVoiceChatMode) {
return null;
}
const settingsContent = <ControlPanel />;
if (isMobile) {
return (
<Drawer open={isDrawerOpen} onOpenChange={setIsDrawerOpen}>
<DrawerTrigger asChild>
<Button
variant="outline"
size="icon"
className="fixed bottom-20 right-4 z-10 rounded-full bg-black border border-white/40 text-white shadow-lg"
>
<Settings className="h-5 w-5" />
</Button>
</DrawerTrigger>
<DrawerContent className="h-[85vh] bg-black">
{settingsContent}
</DrawerContent>
</Drawer>
);
}
return <div className="hidden md:block">{settingsContent}</div>;
};
const renderChatSidebar = () => {
if (isMobile) {
return (
<Sheet open={isChatSidebarOpen} onOpenChange={setIsChatSidebarOpen}>
<SheetTrigger asChild>
<Button
variant="outline"
size="icon"
onClick={() => {
setIsChatSidebarOpen(true);
}}
className="fixed top-16 left-4 rounded-full bg-black border border-white/40 text-white shadow-lg hover:cursor-pointer z-50"
>
<Menu className="h-5 w-5" />
</Button>
</SheetTrigger>
<SheetContent
side="left"
className="p-0 w-full max-w-md bg-black border-white/10"
>
<ChatSidebar
isMobileSidebar={true}
onClose={() => setIsChatSidebarOpen(false)}
/>
</SheetContent>
</Sheet>
);
}
return (
<div
className={`transition-all duration-300 ease-in-out ${
isSidebarVisible ? "block" : "hidden"
} md:w-64 h-full`}
>
<ChatSidebar />
</div>
);
};
return (
<div className="flex flex-col md:flex-row h-screen bg-black overflow-hidden">
{/* {!isListening && (
<div className="fixed top-4 left-4 z-50 md:top-4 md:left-6">
<Link to="/">
<Button
variant="outline"
size="sm"
className="bg-black/80 text-white hover:text-white/90 backdrop-blur-sm border border-white/20 shadow-md hover:bg-white/10 transition-all duration-300 ease-in-out"
>
<ArrowLeft className="h-4 w-4 mr-2 text-white" /> Back to Home
</Button>
</Link>
</div>
)} */}
{!isListening && renderChatSidebar()}
<div className="flex-1 flex flex-col h-full md:border-r border-white/10 relative">
{!isMobile && !isSidebarVisible && (
<Button
variant="outline"
size="icon"
onClick={handleShowSidebar}
className="fixed top-5 left-[20px] text-white z-50 bg-black/80 backdrop-blur-sm border border-white/20 shadow-md hover:bg-black/60 hover:border-white/60 transition-all duration-300 ease-in-out"
>
<PanelLeft className="h-5 w-5 text-white" />
</Button>
)}
{/* {!isMobile && isSidebarVisible && (
<Button
variant="ghost"
size="icon"
onClick={handleToggleSidebar}
className="absolute top-4 left-[260px] z-50 transition-all duration-300 ease-in-out"
>
<PanelLeftClose className="h-5 w-5" />
</Button>
)} */}
<ChatInterface
messages={activeChatMessages}
isListening={isListening}
/>
<div className="p-6 border-t border-white/10 bg-black/80 backdrop-blur-sm flex justify-center items-center relative overflow-hidden">
<div className="absolute inset-0 flex justify-center items-center pointer-events-none">
<div
className={`w-40 h-40 rounded-full ${
isListening ? "bg-white/5" : "bg-white/3"
} blur-3xl transition-all duration-500 ease-in-out`}
></div>
</div>
{isVoiceChatMode ? (
<div className="w-full max-w-md">
<VoiceChat activeVoice={activeVoice} temperature={temperature} />
</div>
) : (
<Button
variant="outline"
size="icon"
className={`rounded-full w-16 h-16 shadow-md relative z-10 transition-all duration-300 ${
isListening
? "bg-white text-black hover:bg-white/90 border-0"
: "bg-black text-white border border-white/40 hover:bg-white/10"
}`}
onClick={toggleListening}
>
{isListening ? (
<MicOff className="h-6 w-6" />
) : (
<Mic className="h-6 w-6" />
)}
</Button>
)}
</div>
{/* Toggle between voice chat and text chat modes */}
{/* <div className="absolute bottom-24 left-1/2 -translate-x-1/2 z-20">
<div className="flex items-center p-1 bg-gray-900/70 backdrop-blur-sm rounded-full border border-white/10">
<Button
size="sm"
variant={isVoiceChatMode ? "ghost" : "default"}
className={`rounded-full text-xs px-3 ${!isVoiceChatMode ? "" : "bg-transparent text-white/70 hover:text-white hover:bg-white/10"}`}
onClick={() => setIsVoiceChatMode(false)}
>
Text Chat
</Button>
<Button
size="sm"
variant={isVoiceChatMode ? "default" : "ghost"}
className={`rounded-full text-xs px-3 ${isVoiceChatMode ? "" : "bg-transparent text-white/70 hover:text-white hover:bg-white/10"}`}
onClick={() => setIsVoiceChatMode(true)}
>
Voice Chat
</Button>
</div>
</div> */}
</div>
{!isListening && activeChat && renderSettingsPanel()}
</div>
);
};
export default Index;