diff --git a/src/routes/chats.ts b/src/routes/chats.ts index aacfb60..afa74f9 100644 --- a/src/routes/chats.ts +++ b/src/routes/chats.ts @@ -40,4 +40,27 @@ router.get('/:id', async (req, res) => { } }); +router.delete(`/:id`, async (req, res) => { + try { + const chatExists = await db.query.chats.findFirst({ + where: eq(chats.id, req.params.id), + }); + + if (!chatExists) { + return res.status(404).json({ message: 'Chat not found' }); + } + + await db.delete(chats).where(eq(chats.id, req.params.id)).execute(); + await db + .delete(messages) + .where(eq(messages.chatId, req.params.id)) + .execute(); + + return res.status(200).json({ message: 'Chat deleted successfully' }); + } catch (err) { + res.status(500).json({ message: 'An error has occurred.' }); + logger.error(`Error in deleting chat: ${err.message}`); + } +}); + export default router; diff --git a/ui/app/library/page.tsx b/ui/app/library/page.tsx index 6ba2fe4..8294fc1 100644 --- a/ui/app/library/page.tsx +++ b/ui/app/library/page.tsx @@ -1,11 +1,12 @@ 'use client'; +import DeleteChat from '@/components/DeleteChat'; import { formatTimeDifference } from '@/lib/utils'; -import { BookOpenText, ClockIcon, ScanEye } from 'lucide-react'; +import { BookOpenText, ClockIcon, Delete, ScanEye } from 'lucide-react'; import Link from 'next/link'; import { useEffect, useState } from 'react'; -interface Chat { +export interface Chat { id: string; title: string; createdAt: string; @@ -92,6 +93,11 @@ const Page = () => { {formatTimeDifference(new Date(), chat.createdAt)} Ago

+ ))} diff --git a/ui/components/DeleteChat.tsx b/ui/components/DeleteChat.tsx new file mode 100644 index 0000000..165f86e --- /dev/null +++ b/ui/components/DeleteChat.tsx @@ -0,0 +1,114 @@ +import { Delete, Trash } from 'lucide-react'; +import { Dialog, Transition } from '@headlessui/react'; +import { Fragment, useState } from 'react'; +import { toast } from 'sonner'; +import { Chat } from '@/app/library/page'; + +const DeleteChat = ({ + chatId, + chats, + setChats, +}: { + chatId: string; + chats: Chat[]; + setChats: (chats: Chat[]) => void; +}) => { + const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false); + const [loading, setLoading] = useState(false); + + const handleDelete = async () => { + setLoading(true); + try { + const res = await fetch( + `${process.env.NEXT_PUBLIC_API_URL}/chats/${chatId}`, + { + method: 'DELETE', + headers: { + 'Content-Type': 'application/json', + }, + }, + ); + + if (res.status != 200) { + throw new Error('Failed to delete chat'); + } + + const newChats = chats.filter((chat) => chat.id !== chatId); + + setChats(newChats); + } catch (err: any) { + toast.error(err.message); + } finally { + setConfirmationDialogOpen(false); + setLoading(false); + } + }; + + return ( + <> + + + { + if (!loading) { + setConfirmationDialogOpen(false); + } + }} + > + +
+
+ + + + Delete Confirmation + + + Are you sure you want to delete this chat? + +
+ + +
+
+
+
+
+
+
+ + ); +}; + +export default DeleteChat;