import { SyntheticEvent, useEffect, useRef, useState, useCallback, } from 'react'; import { useSelector } from 'react-redux'; import Edit from '../assets/edit.svg'; import Exit from '../assets/exit.svg'; import { useDarkTheme } from '../hooks'; import ConfirmationModal from '../modals/ConfirmationModal'; import CheckMark2 from '../assets/checkMark2.svg'; import Trash from '../assets/red-trash.svg'; import Share from '../assets/share.svg'; import threeDots from '../assets/three-dots.svg'; import { selectConversationId } from '../preferences/preferenceSlice'; import { ActiveState } from '../models/misc'; import { ShareConversationModal } from '../modals/ShareConversationModal'; import { useTranslation } from 'react-i18next'; import ContextMenu from '../components/ContextMenu'; import { MenuOption } from '../components/ContextMenu'; import { useOutsideAlerter } from '../hooks'; interface ConversationProps { name: string; id: string; } interface ConversationTileProps { conversation: ConversationProps; selectConversation: (arg1: string) => void; onCoversationClick: () => void; //Callback to handle click on conversation tile regardless of selected or not onDeleteConversation: (arg1: string) => void; onSave: ({ name, id }: ConversationProps) => void; } export default function ConversationTile({ conversation, selectConversation, onCoversationClick, onDeleteConversation, onSave, }: ConversationTileProps) { const conversationId = useSelector(selectConversationId); const tileRef = useRef(null); const [isDarkTheme] = useDarkTheme(); const [isEdit, setIsEdit] = useState(false); const [conversationName, setConversationsName] = useState(''); const [isOpen, setOpen] = useState(false); const [isShareModalOpen, setShareModalState] = useState(false); const [isHovered, setIsHovered] = useState(false); const [deleteModalState, setDeleteModalState] = useState('INACTIVE'); const menuRef = useRef(null); const { t } = useTranslation(); useEffect(() => { setConversationsName(conversation.name); }, [conversation.name]); function handleEditConversation(event: SyntheticEvent) { event.stopPropagation(); setIsEdit(true); setOpen(false); } function handleSaveConversation(changedConversation: ConversationProps) { if (changedConversation.name.trim().length) { onSave(changedConversation); setIsEdit(false); } else { onClear(); } } const handleClickOutside = (event: MouseEvent) => { if (menuRef.current && !menuRef.current.contains(event.target as Node)) { setOpen(false); } }; useEffect(() => { document.addEventListener('mousedown', handleClickOutside); return () => { document.removeEventListener('mousedown', handleClickOutside); }; }, []); const preventScroll = useCallback((event: WheelEvent | TouchEvent) => { event.preventDefault(); }, []); useEffect(() => { const conversationsMainDiv = document.getElementById( 'conversationsMainDiv', ); if (conversationsMainDiv) { if (isOpen) { conversationsMainDiv.addEventListener('wheel', preventScroll, { passive: false, }); conversationsMainDiv.addEventListener('touchmove', preventScroll, { passive: false, }); } else { conversationsMainDiv.removeEventListener('wheel', preventScroll); conversationsMainDiv.removeEventListener('touchmove', preventScroll); } return () => { conversationsMainDiv.removeEventListener('wheel', preventScroll); conversationsMainDiv.removeEventListener('touchmove', preventScroll); }; } }, [isOpen]); function onClear() { setConversationsName(conversation.name); setIsEdit(false); } const handleRenameKeyDown = (e: React.KeyboardEvent) => { e.stopPropagation(); if (e.key === 'Enter') { handleSaveConversation({ id: conversation.id, name: conversationName, }); } else if (e.key === 'Escape') { onClear(); } }; const menuOptions: MenuOption[] = [ { icon: Share, label: t('convTile.share'), onClick: (event: SyntheticEvent) => { event.stopPropagation(); setShareModalState(true); setOpen(false); }, variant: 'primary', iconWidth: 14, iconHeight: 14, }, { icon: Edit, label: t('convTile.rename'), onClick: handleEditConversation, variant: 'primary', }, { icon: Trash, label: t('convTile.delete'), onClick: (event: SyntheticEvent) => { event.stopPropagation(); setDeleteModalState('ACTIVE'); setOpen(false); }, iconWidth: 18, iconHeight: 18, variant: 'danger', }, ]; useOutsideAlerter( tileRef, () => { if (isEdit) { onClear(); } }, [isEdit], true, ); return ( <>
{ setIsHovered(true); }} onMouseLeave={() => { if (!isEdit) { setIsHovered(false); } }} onClick={() => { onCoversationClick(); conversationId !== conversation.id && selectConversation(conversation.id); }} className={`my-auto mx-4 mt-4 flex h-9 cursor-pointer items-center justify-between pl-4 gap-4 rounded-3xl hover:bg-bright-gray dark:hover:bg-dark-charcoal ${ conversationId === conversation.id || isOpen || isHovered || isEdit ? 'bg-bright-gray dark:bg-dark-charcoal' : '' }`} >
{isEdit ? ( setConversationsName(e.target.value)} onKeyDown={handleRenameKeyDown} /> ) : (

{conversationName}

)}
{(conversationId === conversation.id || isHovered || isOpen) && (
{isEdit ? (
Edit { event.stopPropagation(); handleSaveConversation({ id: conversation.id, name: conversationName, }); }} /> Exit { event.stopPropagation(); onClear(); }} />
) : ( )}
)}
onDeleteConversation(conversation.id)} submitLabel={t('convTile.delete')} /> {isShareModalOpen && ( { setShareModalState(false); isHovered && setIsHovered(false); }} conversationId={conversation.id} /> )} ); }