1 import type { CSSProperties, ChangeEvent, DragEvent, MouseEvent } from 'react';
2 import { useState } from 'react';
4 import { c } from 'ttag';
6 import { Button } from '@proton/atoms';
7 import Copy from '@proton/components/components/button/Copy';
8 import Icon from '@proton/components/components/icon/Icon';
9 import Tooltip from '@proton/components/components/tooltip/Tooltip';
10 import useNotifications from '@proton/components/hooks/useNotifications';
11 import { addPlus } from '@proton/shared/lib/helpers/string';
12 import type { Recipient } from '@proton/shared/lib/interfaces';
13 import type { ContactFormatted, ContactGroup } from '@proton/shared/lib/interfaces/contacts';
14 import type { SimpleMap } from '@proton/shared/lib/interfaces/utils';
15 import clsx from '@proton/utils/clsx';
17 import ItemCheckbox from '../../items/ItemCheckbox';
18 import ContactGroupLabels from '../group/ContactGroupLabels';
19 import { ContactRowItemFirstLine, ContactRowItemSecondLine } from './ContactRowItem';
23 onClick: (ID: string) => void;
24 onCheck: (event: ChangeEvent) => void;
27 contactGroupsMap: SimpleMap<ContactGroup>;
28 contact: ContactFormatted;
30 onDragStart?: (event: DragEvent) => void;
31 onDragEnd?: (event: DragEvent) => void;
34 onFocus: (index: number) => void;
35 onGroupDetails: (contactGroupID: string) => void;
37 onCompose?: (recipients: Recipient[], attachments: File[]) => void;
58 const { createNotification } = useNotifications();
59 const { ID, Name, LabelIDs = [], emails = [] } = contact;
60 const [hasFocus, setHasFocus] = useState(false);
62 const contactGroups = contact.LabelIDs.map((ID) => contactGroupsMap[ID] as ContactGroup);
64 const handleFocus = () => {
69 const handleBlur = () => {
73 const handleCopyEmail = () => {
77 text: c('Success').t`Email address copied to clipboard`,
82 const handleCompose = (e: MouseEvent<HTMLButtonElement>) => {
84 if (onCompose && emails[0]) {
85 const recipient: Recipient = { Name: contact.Name, Address: emails[0] };
86 onCompose([recipient], []);
94 onClick={() => onClick(ID)}
96 onDragStart={onDragStart}
99 'contact-item-container item-contact flex cursor-pointer bg-global-white group-hover-opacity-container interactive-pseudo-inset interactive--no-background',
100 isDrawer && 'item-in-drawer',
101 dragged && 'item-dragging',
102 hasFocus && 'item-is-focused'
104 onFocus={handleFocus}
107 data-element-id={contact.ID}
108 data-shortcut-target="contact-container"
109 data-testid={`contact-item:${Name}`}
111 <div className="flex flex-nowrap w-full h-full my-auto items-start">
112 <ItemCheckbox ID={ID} name={Name} checked={checked} onChange={onCheck} />
113 <div className="flex-1 ml-2 conversation-titlesender">
114 <ContactRowItemFirstLine ID={ID} Name={Name} className={!!LabelIDs.length ? 'pr-4' : ''} />
115 <ContactRowItemSecondLine title={emails.join(', ')}>
117 addPlus(emails as any)
119 <span className="placeholder">{c('Info').t`No email address`}</span>
121 </ContactRowItemSecondLine>
122 {hasPaidMail && contactGroups && (
124 contactGroups={contactGroups}
126 onDetails={onGroupDetails}
133 <span className="flex gap-4">
135 <div className="contact-item-hover-action-buttons">
136 <Tooltip title={c('Action').t`Compose`}>
137 <Button color="weak" shape="ghost" icon onClick={handleCompose}>
138 <Icon name="pen-square" alt={c('Action').t`Compose`} />
143 <div className="contact-item-hover-action-buttons">
146 className={clsx(isDrawer && 'mr-1')}
147 onCopy={handleCopyEmail}
148 tooltipText={c('Action').t`Copy email to clipboard`}
159 export default ContactRow;