import { FC, useState, useRef, useEffect } from 'react' import { CloseCircle } from 'iconsax-react' import { EmailSuggestion } from '@/services/EmailSuggestionsService' interface EmailInputProps { toEmails: string[] onAddEmail: (email: string) => void onRemoveEmail: (email: string) => void suggestions: EmailSuggestion[] onSearchSuggestions?: (query: string) => void showCcBccButton?: boolean onCcBccClick?: () => void } const EmailInput: FC = ({ toEmails, onAddEmail, onRemoveEmail, suggestions, onSearchSuggestions, showCcBccButton = false, onCcBccClick }) => { const [to, setTo] = useState('') const [filteredSuggestions, setFilteredSuggestions] = useState([]) const [showSuggestions, setShowSuggestions] = useState(false) const [selectedSuggestionIndex, setSelectedSuggestionIndex] = useState(-1) const typingTimeoutRef = useRef(null) const searchTimeoutRef = useRef(null) const inputRef = useRef(null) const isValidEmail = (email: string) => { const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/ return emailRegex.test(email) } const filterSuggestions = (input: string) => { if (!input.trim()) { setFilteredSuggestions([]) setShowSuggestions(false) return } if (onSearchSuggestions) { if (searchTimeoutRef.current) { clearTimeout(searchTimeoutRef.current) } searchTimeoutRef.current = window.setTimeout(() => { onSearchSuggestions(input) }, 300) } setSelectedSuggestionIndex(-1) } useEffect(() => { if (suggestions.length > 0) { const filtered = suggestions .filter(suggestion => !toEmails.includes(suggestion.address) ) .slice(0, 5) setFilteredSuggestions(filtered) setShowSuggestions(filtered.length > 0 && to.trim().length > 0) } else if (to.trim() === '') { setFilteredSuggestions([]) setShowSuggestions(false) } }, [suggestions, to, toEmails]) const selectSuggestion = (suggestion: EmailSuggestion) => { onAddEmail(suggestion.address) setTo('') setShowSuggestions(false) setFilteredSuggestions([]) setSelectedSuggestionIndex(-1) inputRef.current?.focus() } const addEmail = (email: string) => { if (isValidEmail(email.trim())) { onAddEmail(email.trim()) setTo('') setShowSuggestions(false) setFilteredSuggestions([]) } } const handleToChange = (e: React.ChangeEvent) => { const newValue = e.target.value setTo(newValue) filterSuggestions(newValue) if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current) } if (newValue.trim()) { typingTimeoutRef.current = window.setTimeout(() => { if (isValidEmail(newValue.trim())) { addEmail(newValue.trim()) } }, 1500) } } const handleToBlur = () => { setTimeout(() => { setShowSuggestions(false) setFilteredSuggestions([]) }, 200) if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current) } if (to.trim() && isValidEmail(to.trim())) { addEmail(to.trim()) } } const handleToFocus = () => { if (to.trim()) { filterSuggestions(to) } } const handleToKeyDown = (e: React.KeyboardEvent) => { if (showSuggestions && filteredSuggestions.length > 0) { if (e.key === 'ArrowDown') { e.preventDefault() setSelectedSuggestionIndex(prev => prev < filteredSuggestions.length - 1 ? prev + 1 : 0 ) } else if (e.key === 'ArrowUp') { e.preventDefault() setSelectedSuggestionIndex(prev => prev > 0 ? prev - 1 : filteredSuggestions.length - 1 ) } else if (e.key === 'Enter' && selectedSuggestionIndex >= 0) { e.preventDefault() selectSuggestion(filteredSuggestions[selectedSuggestionIndex]) return } else if (e.key === 'Escape') { setShowSuggestions(false) setFilteredSuggestions([]) setSelectedSuggestionIndex(-1) return } } if (e.key === 'Enter' && to.trim()) { e.preventDefault() if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current) } addEmail(to.trim()) } } useEffect(() => { return () => { if (typingTimeoutRef.current) { clearTimeout(typingTimeoutRef.current) } if (searchTimeoutRef.current) { clearTimeout(searchTimeoutRef.current) } } }, []) return (
{toEmails.map((email, index) => (
{email} onRemoveEmail(email)} />
))} {showCcBccButton && ( )}
{showSuggestions && filteredSuggestions.length > 0 && (
{filteredSuggestions.map((suggestion, index) => (
selectSuggestion(suggestion)} onMouseEnter={() => setSelectedSuggestionIndex(index)} >
{suggestion.name || suggestion.address} {suggestion.name && ( {suggestion.address} )}
))}
)}
) } export default EmailInput