| import { useQueryState } from 'nuqs' | |
| import { SessionEntry } from '@/types/playground' | |
| import { Button } from '../../../ui/button' | |
| import useSessionLoader from '@/hooks/useSessionLoader' | |
| import { deletePlaygroundSessionAPI } from '@/api/playground' | |
| import { usePlaygroundStore } from '@/store' | |
| import { toast } from 'sonner' | |
| import Icon from '@/components/ui/icon' | |
| import { useState } from 'react' | |
| import DeleteSessionModal from './DeleteSessionModal' | |
| import useChatActions from '@/hooks/useChatActions' | |
| import { truncateText, cn } from '@/lib/utils' | |
| type SessionItemProps = SessionEntry & { | |
| isSelected: boolean | |
| onSessionClick: () => void | |
| } | |
| const SessionItem = ({ | |
| title, | |
| session_id, | |
| isSelected, | |
| onSessionClick | |
| }: SessionItemProps) => { | |
| const [agentId] = useQueryState('agent') | |
| const { getSession } = useSessionLoader() | |
| const [, setSessionId] = useQueryState('session') | |
| const { selectedEndpoint, sessionsData, setSessionsData } = | |
| usePlaygroundStore() | |
| const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false) | |
| const { clearChat } = useChatActions() | |
| const handleGetSession = async () => { | |
| if (agentId) { | |
| onSessionClick() | |
| await getSession(session_id, agentId) | |
| setSessionId(session_id) | |
| } | |
| } | |
| const handleDeleteSession = async () => { | |
| if (agentId) { | |
| try { | |
| const response = await deletePlaygroundSessionAPI( | |
| selectedEndpoint, | |
| agentId, | |
| session_id | |
| ) | |
| if (response.status === 200 && sessionsData) { | |
| setSessionsData( | |
| sessionsData.filter((session) => session.session_id !== session_id) | |
| ) | |
| clearChat() | |
| toast.success('Session deleted') | |
| } else { | |
| toast.error('Failed to delete session') | |
| } | |
| } catch { | |
| toast.error('Failed to delete session') | |
| } finally { | |
| setIsDeleteModalOpen(false) | |
| } | |
| } | |
| } | |
| return ( | |
| <> | |
| <div | |
| className={cn( | |
| 'group flex h-11 w-full cursor-pointer items-center justify-between rounded-lg px-3 py-2 transition-colors duration-200', | |
| isSelected | |
| ? 'cursor-default bg-primary/10' | |
| : 'bg-background-secondary hover:bg-background-secondary/80' | |
| )} | |
| onClick={handleGetSession} | |
| > | |
| <div className="flex flex-col gap-1"> | |
| <h4 | |
| className={cn('text-sm font-medium', isSelected && 'text-primary')} | |
| > | |
| {truncateText(title, 20)} | |
| </h4> | |
| </div> | |
| <Button | |
| variant="ghost" | |
| size="icon" | |
| className="transform opacity-0 transition-all duration-200 ease-in-out group-hover:opacity-100" | |
| onClick={(e) => { | |
| e.stopPropagation() | |
| setIsDeleteModalOpen(true) | |
| }} | |
| > | |
| <Icon type="trash" size="xs" /> | |
| </Button> | |
| </div> | |
| <DeleteSessionModal | |
| isOpen={isDeleteModalOpen} | |
| onClose={() => setIsDeleteModalOpen(false)} | |
| onDelete={handleDeleteSession} | |
| isDeleting={false} | |
| /> | |
| </> | |
| ) | |
| } | |
| export default SessionItem | |