mirror of
https://github.com/ItzCrazyKns/Perplexica.git
synced 2025-06-22 09:48:36 +00:00
Made enhancements to the library interface!
1. Search Functionality: -Added a search box with search icon and "Search your threads..." placeholder -Real-time filtering of threads as you type -Clear button (X) when text is entered 2. Thread Count Display: -Added "You have X threads in Perplexica" below the search box -Only shows in normal mode (hidden during selection) 3. Multiple delete functionality: -"Select" button in the top right below Search Box -Checkboxes that appear on hover and when in selection mode -Selection mode header showing count and actions -When in selection mode, shows "X selected thread(s)" on the left -Action buttons (Select all, Cancel, Delete Selected) on the right -Disabled Delete Selected button when no threads are selected -Confirmation dialog using the new BatchDeleteChats component 4. Terminology Update: -Changed all instances of "chats" to "threads" throughout the interface
This commit is contained in:
120
ui/components/BatchDeleteChats.tsx
Normal file
120
ui/components/BatchDeleteChats.tsx
Normal file
@ -0,0 +1,120 @@
|
||||
import {
|
||||
Description,
|
||||
Dialog,
|
||||
DialogBackdrop,
|
||||
DialogPanel,
|
||||
DialogTitle,
|
||||
Transition,
|
||||
TransitionChild,
|
||||
} from '@headlessui/react';
|
||||
import { Fragment, useState } from 'react';
|
||||
import { toast } from 'sonner';
|
||||
import { Chat } from '@/app/library/page';
|
||||
|
||||
interface BatchDeleteChatsProps {
|
||||
chatIds: string[];
|
||||
chats: Chat[];
|
||||
setChats: (chats: Chat[]) => void;
|
||||
onComplete: () => void;
|
||||
isOpen: boolean;
|
||||
setIsOpen: (isOpen: boolean) => void;
|
||||
}
|
||||
|
||||
const BatchDeleteChats = ({
|
||||
chatIds,
|
||||
chats,
|
||||
setChats,
|
||||
onComplete,
|
||||
isOpen,
|
||||
setIsOpen,
|
||||
}: BatchDeleteChatsProps) => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const handleDelete = async () => {
|
||||
if (chatIds.length === 0) return;
|
||||
|
||||
setLoading(true);
|
||||
try {
|
||||
// Delete chats one by one
|
||||
for (const chatId of chatIds) {
|
||||
await fetch(`${process.env.NEXT_PUBLIC_API_URL}/chats/${chatId}`, {
|
||||
method: 'DELETE',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// Update local state
|
||||
const newChats = chats.filter(chat => !chatIds.includes(chat.id));
|
||||
setChats(newChats);
|
||||
|
||||
toast.success(`${chatIds.length} thread${chatIds.length > 1 ? 's' : ''} deleted`);
|
||||
onComplete();
|
||||
} catch (err: any) {
|
||||
toast.error('Failed to delete threads');
|
||||
} finally {
|
||||
setIsOpen(false);
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Transition appear show={isOpen} as={Fragment}>
|
||||
<Dialog
|
||||
as="div"
|
||||
className="relative z-50"
|
||||
onClose={() => {
|
||||
if (!loading) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DialogBackdrop className="fixed inset-0 bg-black/30" />
|
||||
<div className="fixed inset-0 overflow-y-auto">
|
||||
<div className="flex min-h-full items-center justify-center p-4 text-center">
|
||||
<TransitionChild
|
||||
as={Fragment}
|
||||
enter="ease-out duration-200"
|
||||
enterFrom="opacity-0 scale-95"
|
||||
enterTo="opacity-100 scale-100"
|
||||
leave="ease-in duration-100"
|
||||
leaveFrom="opacity-100 scale-200"
|
||||
leaveTo="opacity-0 scale-95"
|
||||
>
|
||||
<DialogPanel className="w-full max-w-md transform rounded-2xl bg-light-secondary dark:bg-dark-secondary border border-light-200 dark:border-dark-200 p-6 text-left align-middle shadow-xl transition-all">
|
||||
<DialogTitle className="text-lg font-medium leading-6 dark:text-white">
|
||||
Delete Confirmation
|
||||
</DialogTitle>
|
||||
<Description className="text-sm dark:text-white/70 text-black/70">
|
||||
Are you sure you want to delete {chatIds.length} selected thread{chatIds.length !== 1 ? 's' : ''}?
|
||||
</Description>
|
||||
<div className="flex flex-row items-end justify-end space-x-4 mt-6">
|
||||
<button
|
||||
onClick={() => {
|
||||
if (!loading) {
|
||||
setIsOpen(false);
|
||||
}
|
||||
}}
|
||||
className="text-black/50 dark:text-white/50 text-sm hover:text-black/70 hover:dark:text-white/70 transition duration-200"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
onClick={handleDelete}
|
||||
className="text-red-400 text-sm hover:text-red-500 transition duration-200"
|
||||
disabled={loading}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</DialogPanel>
|
||||
</TransitionChild>
|
||||
</div>
|
||||
</div>
|
||||
</Dialog>
|
||||
</Transition>
|
||||
);
|
||||
};
|
||||
|
||||
export default BatchDeleteChats;
|
Reference in New Issue
Block a user