mirror of
https://github.com/Significant-Gravitas/AutoGPT.git
synced 2026-02-03 03:14:57 -05:00
add finishing touch in sidebar
This commit is contained in:
@@ -35,10 +35,10 @@ export const ChatContainer = ({messages, status, error, input, setInput, handleM
|
||||
setIsCreating(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return (
|
||||
<div className="mx-auto h-[calc(100vh-60px)] w-full max-w-3xl pb-6">
|
||||
<div className="mx-auto h-full w-full max-w-3xl pb-6">
|
||||
<div className="flex h-full flex-col">
|
||||
{sessionId ? (
|
||||
<ChatMessagesContainer
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
"use client";
|
||||
import { Sidebar, SidebarHeader, SidebarContent, SidebarFooter, SidebarTrigger, useSidebar } from "@/components/ui/sidebar";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { SparkleIcon, PlusIcon } from "@phosphor-icons/react";
|
||||
import { SparkleIcon, PlusIcon, SpinnerGapIcon } from "@phosphor-icons/react";
|
||||
import { motion } from "framer-motion";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { useState } from "react";
|
||||
import { parseAsString, useQueryState } from "nuqs";
|
||||
import { postV2CreateSession } from "@/app/api/__generated__/endpoints/chat/chat";
|
||||
import { Button } from "@/components/atoms/Button/Button";
|
||||
|
||||
export function ChatSidebar() {
|
||||
const { state } = useSidebar();
|
||||
const isCollapsed = state === "collapsed";
|
||||
const [isCreating, setIsCreating] = useState(false);
|
||||
const [, setSessionId] = useQueryState("sessionId", parseAsString);
|
||||
|
||||
function handleNewChat() {
|
||||
// TODO: Implement new chat creation
|
||||
async function handleNewChat() {
|
||||
if (isCreating) return;
|
||||
setIsCreating(true);
|
||||
try {
|
||||
const response = await postV2CreateSession({
|
||||
body: JSON.stringify({}),
|
||||
});
|
||||
if (response.status === 200 && response.data?.id) {
|
||||
setSessionId(response.data.id);
|
||||
}
|
||||
} finally {
|
||||
setIsCreating(false);
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -19,23 +35,14 @@ export function ChatSidebar() {
|
||||
collapsible="icon"
|
||||
className="!top-[60px] !h-[calc(100vh-60px)]"
|
||||
>
|
||||
<SidebarHeader
|
||||
{isCollapsed && <SidebarHeader
|
||||
className={cn(
|
||||
"flex md:pt-3.5",
|
||||
"flex ",
|
||||
isCollapsed
|
||||
? "flex-row items-center justify-between gap-y-4 md:flex-col md:items-start md:justify-start"
|
||||
: "flex-row items-center justify-between"
|
||||
)}
|
||||
>
|
||||
<a href="#" className="flex items-center gap-2">
|
||||
<SparkleIcon className="h-8 w-8" />
|
||||
{!isCollapsed && (
|
||||
<span className="font-semibold text-black dark:text-white">
|
||||
Acme
|
||||
</span>
|
||||
)}
|
||||
</a>
|
||||
|
||||
<motion.div
|
||||
key={isCollapsed ? "header-collapsed" : "header-expanded"}
|
||||
className={cn(
|
||||
@@ -46,20 +53,38 @@ export function ChatSidebar() {
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.8 }}
|
||||
>
|
||||
<SidebarTrigger />
|
||||
{isCollapsed && <div className="bg-secondary border border-neutral-400 h-fit p-1 rounded-3xl">
|
||||
<SidebarTrigger />
|
||||
|
||||
</div>}
|
||||
</motion.div>
|
||||
</SidebarHeader>
|
||||
</SidebarHeader>}
|
||||
<SidebarContent className="gap-4 px-2 py-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<Button
|
||||
variant="primary"
|
||||
size="icon"
|
||||
onClick={handleNewChat}
|
||||
disabled={isCreating}
|
||||
className={cn(
|
||||
"w-full justify-start gap-2",
|
||||
isCollapsed && "justify-center px-2"
|
||||
"w-full gap-2 rounded-3xl flex items-center justify-start h-fit px-4 py-2",
|
||||
isCollapsed && "justify-center px-1 rounded-3xl "
|
||||
)}
|
||||
>
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
{!isCollapsed && <span>New Chat</span>}
|
||||
{isCreating ? (
|
||||
<SpinnerGapIcon className="h-4 w-4 animate-spin" />
|
||||
) : (
|
||||
<PlusIcon className="h-4 w-4" />
|
||||
)}
|
||||
{!isCollapsed && <span>{isCreating ? "Creating..." : "New Chat"}</span>}
|
||||
</Button>
|
||||
{!isCollapsed && <div className="bg-secondary border border-neutral-400 h-fit p-1 rounded-3xl">
|
||||
<SidebarTrigger />
|
||||
|
||||
</div>}
|
||||
|
||||
</div>
|
||||
|
||||
</SidebarContent>
|
||||
<SidebarFooter className="px-2">
|
||||
</SidebarFooter>
|
||||
|
||||
@@ -5,18 +5,22 @@ import { DefaultChatTransport } from "ai";
|
||||
import { useState, useMemo } from "react";
|
||||
import { parseAsString, useQueryState } from "nuqs";
|
||||
import { ChatSidebar } from "./components/ChatSidebar/ChatSidebar";
|
||||
import { EmptySession } from "./components/EmptySession/EmptySession";
|
||||
import { ChatMessagesContainer } from "./components/ChatMessagesContainer/ChatMessagesContainer";
|
||||
import { postV2CreateSession } from "@/app/api/__generated__/endpoints/chat/chat";
|
||||
import { ChatInput } from "@/components/contextual/Chat/components/ChatInput/ChatInput";
|
||||
import { useSearchParams } from "next/navigation";
|
||||
import { ChatContainer } from "./components/ChatContainer/ChatContainer";
|
||||
import { SidebarProvider, SidebarInset } from "@/components/ui/sidebar";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { CopyIcon, CheckIcon } from "@phosphor-icons/react";
|
||||
|
||||
export default function Page() {
|
||||
const [input, setInput] = useState("");
|
||||
const searchParams = useSearchParams();
|
||||
const sessionId = searchParams.get("sessionId") ?? undefined;
|
||||
const [copied, setCopied] = useState(false);
|
||||
const [sessionId] = useQueryState("sessionId", parseAsString);
|
||||
|
||||
function handleCopySessionId() {
|
||||
if (!sessionId) return;
|
||||
navigator.clipboard.writeText(sessionId);
|
||||
setCopied(true);
|
||||
setTimeout(() => setCopied(false), 2000);
|
||||
}
|
||||
|
||||
const transport = useMemo(() => {
|
||||
if (!sessionId) return null;
|
||||
@@ -56,18 +60,39 @@ export default function Page() {
|
||||
}
|
||||
|
||||
return (
|
||||
<SidebarProvider className="min-h-0 h-[calc(100vh-60px)]">
|
||||
<SidebarProvider defaultOpen={false} className="min-h-0 h-[calc(100vh-72px)]">
|
||||
<ChatSidebar />
|
||||
<SidebarInset className="h-[calc(100vh-60px)]">
|
||||
<ChatContainer
|
||||
messages={messages}
|
||||
status={status}
|
||||
error={error}
|
||||
input={input}
|
||||
setInput={setInput}
|
||||
handleMessageSubmit={handleMessageSubmit}
|
||||
onSend={onSend}
|
||||
/>
|
||||
<SidebarInset className="flex h-[calc(100vh-80px)] flex-col relative">
|
||||
{sessionId && (
|
||||
<div className="flex items-center px-4 py-4 absolute">
|
||||
<div className="flex items-center gap-2 rounded-3xl border border-neutral-400 bg-neutral-100 px-3 py-1.5 text-sm text-neutral-600 dark:bg-neutral-800 dark:text-neutral-400">
|
||||
<span className=" text-xs">{sessionId.slice(0, 8)}...</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className="h-6 w-6"
|
||||
onClick={handleCopySessionId}
|
||||
>
|
||||
{copied ? (
|
||||
<CheckIcon className="h-3.5 w-3.5 text-green-500" />
|
||||
) : (
|
||||
<CopyIcon className="h-3.5 w-3.5" />
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex-1 overflow-hidden">
|
||||
<ChatContainer
|
||||
messages={messages}
|
||||
status={status}
|
||||
error={error}
|
||||
input={input}
|
||||
setInput={setInput}
|
||||
handleMessageSubmit={handleMessageSubmit}
|
||||
onSend={onSend}
|
||||
/>
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
);
|
||||
|
||||
@@ -62,7 +62,7 @@ export function Navbar() {
|
||||
<PreviewBanner branchName={previewBranchName} />
|
||||
) : null}
|
||||
<nav
|
||||
className="border-zinc-[#EFEFF0] inline-flex w-full items-center border border-[#EFEFF0] bg-[#F3F4F6]/20 p-3 backdrop-blur-[26px]"
|
||||
className="border-none inline-flex w-full items-center border bg-[#FAFAFA] p-3 backdrop-blur-[26px]"
|
||||
style={{ height: NAVBAR_HEIGHT_PX }}
|
||||
>
|
||||
{/* Left section */}
|
||||
|
||||
Reference in New Issue
Block a user