From 4a23ab132690fdefc0b756eb7bf33eb7e2dbe206 Mon Sep 17 00:00:00 2001 From: MaheshtheDev <38828053+MaheshtheDev@users.noreply.github.com> Date: Mon, 6 Oct 2025 16:29:39 +0000 Subject: [PATCH] feat: history view in the header and dialog modal (#456) --- apps/web/components/header.tsx | 145 +++++++++++++++++- .../components/views/chat/chat-messages.tsx | 13 +- 2 files changed, 150 insertions(+), 8 deletions(-) diff --git a/apps/web/components/header.tsx b/apps/web/components/header.tsx index 7e6c800a..23fb5cf3 100644 --- a/apps/web/components/header.tsx +++ b/apps/web/components/header.tsx @@ -12,6 +12,8 @@ import { LogOut, WaypointsIcon, Gauge, + HistoryIcon, + Trash2, } from "lucide-react" import { DropdownMenuContent, @@ -26,20 +28,57 @@ import { Tooltip, TooltipContent, TooltipTrigger } from "@ui/components/tooltip" import { useAuth } from "@lib/auth-context" import { ConnectAIModal } from "./connect-ai-modal" import { useTheme } from "next-themes" -import { cn } from "@lib/utils" import { usePathname, useRouter } from "next/navigation" import { MCPIcon } from "./menu" import { authClient } from "@lib/auth" import { analytics } from "@/lib/analytics" -import { useGraphModal, usePersistentChat } from "@/stores" +import { useGraphModal, usePersistentChat, useProject } from "@/stores" +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@ui/components/dialog" +import { ScrollArea } from "@ui/components/scroll-area" +import { formatDistanceToNow } from "date-fns" +import { cn } from "@lib/utils" +import { useMemo, useState } from "react" export function Header({ onAddMemory }: { onAddMemory?: () => void }) { const { user } = useAuth() const { theme, setTheme } = useTheme() const router = useRouter() const { setIsOpen: setGraphModalOpen } = useGraphModal() - const { getCurrentChat } = usePersistentChat() + const { + getCurrentChat, + conversations, + currentChatId, + setCurrentChatId, + deleteConversation, + } = usePersistentChat() + const { selectedProject } = useProject() const pathname = usePathname() + const [isDialogOpen, setIsDialogOpen] = useState(false) + + const sorted = useMemo(() => { + return [...conversations].sort((a, b) => + a.lastUpdated < b.lastUpdated ? 1 : -1, + ) + }, [conversations]) + + function handleNewChat() { + analytics.newChatStarted() + const newId = crypto.randomUUID() + setCurrentChatId(newId) + router.push(`/chat/${newId}`) + setIsDialogOpen(false) + } + + function formatRelativeTime(isoString: string): string { + return formatDistanceToNow(new Date(isoString), { addSuffix: true }) + } const handleSignOut = () => { analytics.userSignedOut() @@ -87,6 +126,106 @@ export function Header({ onAddMemory }: { onAddMemory?: () => void }) { c + { + setIsDialogOpen(open) + if (open) { + analytics.chatHistoryViewed() + } + }} + > + + + + + + + +

Chat History

+
+
+ + + Conversations + + Project{" "} + + {selectedProject} + + + + + +
+ {sorted.map((c) => { + const isActive = c.id === currentChatId + return ( + + + ) + })} + {sorted.length === 0 && ( +
+ No conversations yet +
+ )} +
+
+ +
+