diff --git a/autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx b/autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx index 0d403b1a79..384c52dcc2 100644 --- a/autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/copilot/CopilotPage.tsx @@ -1,6 +1,8 @@ "use client"; import { SidebarProvider } from "@/components/ui/sidebar"; +// TODO: Replace with modern Dialog component when available +import DeleteConfirmDialog from "@/components/__legacy__/delete-confirm-dialog"; import { ChatContainer } from "./components/ChatContainer/ChatContainer"; import { ChatSidebar } from "./components/ChatSidebar/ChatSidebar"; import { MobileDrawer } from "./components/MobileDrawer/MobileDrawer"; @@ -31,6 +33,12 @@ export function CopilotPage() { handleDrawerOpenChange, handleSelectSession, handleNewChat, + // Delete functionality + sessionToDelete, + isDeleting, + handleDeleteClick, + handleConfirmDelete, + handleCancelDelete, } = useCopilotPage(); if (isUserLoading || !isLoggedIn) { @@ -64,16 +72,27 @@ export function CopilotPage() { {isMobile && ( - + <> + + !open && handleCancelDelete()} + onDoDelete={handleConfirmDelete} + /> + )} ); diff --git a/autogpt_platform/frontend/src/app/(platform)/copilot/components/MobileDrawer/MobileDrawer.tsx b/autogpt_platform/frontend/src/app/(platform)/copilot/components/MobileDrawer/MobileDrawer.tsx index 80ccfc9c03..f8cf40d7e3 100644 --- a/autogpt_platform/frontend/src/app/(platform)/copilot/components/MobileDrawer/MobileDrawer.tsx +++ b/autogpt_platform/frontend/src/app/(platform)/copilot/components/MobileDrawer/MobileDrawer.tsx @@ -3,7 +3,7 @@ import { Button } from "@/components/atoms/Button/Button"; import { Text } from "@/components/atoms/Text/Text"; import { scrollbarStyles } from "@/components/styles/scrollbars"; import { cn } from "@/lib/utils"; -import { PlusIcon, SpinnerGapIcon, X } from "@phosphor-icons/react"; +import { PlusIcon, SpinnerGapIcon, TrashIcon, X } from "@phosphor-icons/react"; import { Drawer } from "vaul"; interface Props { @@ -11,10 +11,15 @@ interface Props { sessions: SessionSummaryResponse[]; currentSessionId: string | null; isLoading: boolean; + isDeleting?: boolean; onSelectSession: (sessionId: string) => void; onNewChat: () => void; onClose: () => void; onOpenChange: (open: boolean) => void; + onDeleteSession?: ( + sessionId: string, + title: string | null | undefined, + ) => void; } function formatDate(dateString: string) { @@ -47,10 +52,12 @@ export function MobileDrawer({ sessions, currentSessionId, isLoading, + isDeleting, onSelectSession, onNewChat, onClose, onOpenChange, + onDeleteSession, }: Props) { return ( @@ -88,35 +95,52 @@ export function MobileDrawer({

) : ( sessions.map((session) => ( - + + {onDeleteSession && ( + + )} + )) )} diff --git a/autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts b/autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts index 28e9ba7cfb..444e745ec6 100644 --- a/autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts +++ b/autogpt_platform/frontend/src/app/(platform)/copilot/useCopilotPage.ts @@ -1,10 +1,15 @@ -import { useGetV2ListSessions } from "@/app/api/__generated__/endpoints/chat/chat"; +import { + getGetV2ListSessionsQueryKey, + useDeleteV2DeleteSession, + useGetV2ListSessions, +} from "@/app/api/__generated__/endpoints/chat/chat"; import { toast } from "@/components/molecules/Toast/use-toast"; import { useBreakpoint } from "@/lib/hooks/useBreakpoint"; import { useSupabase } from "@/lib/supabase/hooks/useSupabase"; import { useChat } from "@ai-sdk/react"; +import { useQueryClient } from "@tanstack/react-query"; import { DefaultChatTransport } from "ai"; -import { useEffect, useMemo, useRef, useState } from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useChatSession } from "./useChatSession"; import { useLongRunningToolPolling } from "./hooks/useLongRunningToolPolling"; @@ -14,6 +19,11 @@ export function useCopilotPage() { const { isUserLoading, isLoggedIn } = useSupabase(); const [isDrawerOpen, setIsDrawerOpen] = useState(false); const [pendingMessage, setPendingMessage] = useState(null); + const [sessionToDelete, setSessionToDelete] = useState<{ + id: string; + title: string | null | undefined; + } | null>(null); + const queryClient = useQueryClient(); const { sessionId, @@ -24,6 +34,30 @@ export function useCopilotPage() { isCreatingSession, } = useChatSession(); + const { mutate: deleteSessionMutation, isPending: isDeleting } = + useDeleteV2DeleteSession({ + mutation: { + onSuccess: () => { + queryClient.invalidateQueries({ + queryKey: getGetV2ListSessionsQueryKey(), + }); + if (sessionToDelete?.id === sessionId) { + setSessionId(null); + } + setSessionToDelete(null); + }, + onError: (error) => { + toast({ + title: "Failed to delete chat", + description: + error instanceof Error ? error.message : "An error occurred", + variant: "destructive", + }); + setSessionToDelete(null); + }, + }, + }); + const breakpoint = useBreakpoint(); const isMobile = breakpoint === "base" || breakpoint === "sm" || breakpoint === "md"; @@ -143,6 +177,24 @@ export function useCopilotPage() { if (isMobile) setIsDrawerOpen(false); } + const handleDeleteClick = useCallback( + (id: string, title: string | null | undefined) => { + if (isDeleting) return; + setSessionToDelete({ id, title }); + }, + [isDeleting], + ); + + const handleConfirmDelete = useCallback(() => { + if (sessionToDelete) { + deleteSessionMutation({ sessionId: sessionToDelete.id }); + } + }, [sessionToDelete, deleteSessionMutation]); + + const handleCancelDelete = useCallback(() => { + setSessionToDelete(null); + }, []); + return { sessionId, messages, @@ -165,5 +217,11 @@ export function useCopilotPage() { handleDrawerOpenChange, handleSelectSession, handleNewChat, + // Delete functionality + sessionToDelete, + isDeleting, + handleDeleteClick, + handleConfirmDelete, + handleCancelDelete, }; }