'use client'; import * as React from 'react'; import Avatar from '@mui/material/Avatar'; import Box from '@mui/material/Box'; import Chip from '@mui/material/Chip'; import ClickAwayListener from '@mui/material/ClickAwayListener'; import InputAdornment from '@mui/material/InputAdornment'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; import ListItemAvatar from '@mui/material/ListItemAvatar'; import ListItemButton from '@mui/material/ListItemButton'; import ListItemText from '@mui/material/ListItemText'; import OutlinedInput from '@mui/material/OutlinedInput'; import Paper from '@mui/material/Paper'; import Popper from '@mui/material/Popper'; import Stack from '@mui/material/Stack'; import Typography from '@mui/material/Typography'; import { MagnifyingGlass as MagnifyingGlassIcon } from '@phosphor-icons/react/dist/ssr/MagnifyingGlass'; import { logger } from '@/lib/default-logger'; import type { Contact } from './types'; export interface GroupRecipientsProps { contacts: Contact[]; onRecipientAdd?: (contact: Contact) => void; onRecipientRemove?: (recipientId: string) => void; recipients?: Contact[]; } export function GroupRecipients({ contacts, onRecipientAdd, onRecipientRemove, recipients = [], }: GroupRecipientsProps): React.JSX.Element { const searchRef = React.useRef(null); const [searchFocused, setSearchFocused] = React.useState(false); const [searchQuery, setSearchQuery] = React.useState(''); const [searchResults, setSearchResults] = React.useState([]); const showSearchResults = searchFocused && Boolean(searchQuery); const hasSearchResults = searchResults.length > 0; const handleSearchChange = React.useCallback( async (event: React.ChangeEvent): Promise => { const query = event.target.value; setSearchQuery(query); if (!query) { setSearchResults([]); return; } try { // This is where you would make an API request for a real search. For the sake of simplicity, we are just // filtering the data in the client. const results = contacts.filter((contact) => { // Filter already picked recipients if (recipients.find((recipient) => recipient.id === contact.id)) { return false; } return contact.name.toLowerCase().includes(query.toLowerCase()); }); setSearchResults(results); } catch (err) { logger.error(err); } }, [contacts, recipients] ); const handleSearchClickAway = React.useCallback(() => { if (showSearchResults) { setSearchFocused(false); } }, [showSearchResults]); const handleSearchFocus = React.useCallback(() => { setSearchFocused(true); }, []); const handleSearchSelect = React.useCallback( (contact: Contact) => { setSearchQuery(''); onRecipientAdd?.(contact); }, [onRecipientAdd] ); return (
} sx={{ minWidth: '260px' }} value={searchQuery} /> {showSearchResults ? ( {hasSearchResults ? ( Contacts {searchResults.map((contact) => ( { handleSearchSelect(contact); }} > {contact.name} } /> ))} ) : ( Nothing found We couldn't find any matches for "{searchQuery}". Try checking for typos or using complete words. )} ) : null}
To: {recipients.map((recipient) => ( } key={recipient.id} label={recipient.name} onDelete={() => { onRecipientRemove?.(recipient.id); }} /> ))}
); }