Replace contact menu modal with context menu

Added translation texts
Replace modal with dialog component from conversationSummaryList
Prevent extra re-renders on contact dialog component

Change-Id: Ib9d58bebab31c5283058fab2c405af34812f88c7
diff --git a/client/src/components/ContactList.tsx b/client/src/components/ContactList.tsx
index 2ff8252..02bc99a 100644
--- a/client/src/components/ContactList.tsx
+++ b/client/src/components/ContactList.tsx
@@ -16,11 +16,10 @@
  * <https://www.gnu.org/licenses/>.
  */
 
-import { Person } from '@mui/icons-material';
-import { Box, ListItem, ListItemAvatar, ListItemText } from '@mui/material';
+import { ListItem, ListItemAvatar, ListItemText } from '@mui/material';
 import List from '@mui/material/List';
-import { useMemo, useState } from 'react';
-import Modal from 'react-modal';
+import { memo, SetStateAction, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
 
 import {
   useBlockContactMutation,
@@ -29,67 +28,34 @@
   useRemoveContactMutation,
 } from '../services/contactQueries';
 import ContactDetailDialog from './ContactDetailDialog';
+import ContextMenu, { ContextMenuHandler, useContextMenuHandler } from './ContextMenu';
 import ConversationAvatar from './ConversationAvatar';
+import { ConfirmationDialog, useDialogHandler } from './Dialog';
 import LoadingPage from './Loading';
-
-const customStyles = {
-  content: {
-    top: '50%',
-    left: '50%',
-    right: 'auto',
-    bottom: 'auto',
-    marginRight: '-50%',
-    transform: 'translate(-50%, -50%)',
-  },
-};
+import { PopoverListItemData } from './PopoverList';
+import { BlockContactIcon, CancelIcon, PersonIcon } from './SvgIcon';
 
 export default function ContactList() {
   const [currentContactId, setCurrentContactId] = useState<string>('');
-  const [parentModalOpen, setParentModalOpen] = useState<boolean>(false);
-  const [childModalOpen, setChildModalOpen] = useState<boolean>(false);
   const [isBlocking, setIsBlocking] = useState(true);
 
-  const closeParentModal = () => setParentModalOpen(false);
-  const openChildModal = () => setChildModalOpen(true);
-  const closeChildModal = () => setChildModalOpen(false);
-
   const [contactDetailDialogOpen, setContactDetailDialogOpen] = useState<boolean>(false);
 
   const contactListQuery = useContactListQuery();
   const { isLoading, data: contacts } = contactListQuery;
 
-  const removeContactMutation = useRemoveContactMutation();
-  const blockContactMutation = useBlockContactMutation();
-
   const singleContactQuery = useContactQuery(currentContactId);
   const { data: contactDetail } = singleContactQuery;
 
-  const handleClickContact = (id: string): void => {
-    setCurrentContactId(id);
-    setParentModalOpen(true);
-  };
+  const contextMenuHandler = useContextMenuHandler();
 
-  const removeContact = (): void => {
-    //Not sure if the server handles empty contact id
-
-    removeContactMutation.mutate(currentContactId);
-
-    closeChildModal();
-    closeParentModal();
-  };
-
-  const blockContact = (): void => {
-    //Not sure if the server handles empty contact id
-
-    blockContactMutation.mutate(currentContactId);
-
-    closeChildModal();
-    closeParentModal();
-  };
+  const {
+    props: { open: dialogOpen, onClose: closeContactDialog },
+    openDialog: openContactDialog,
+  } = useDialogHandler();
 
   const ContactDetailDialogElement = useMemo(() => {
     const onClosingContactDetailDialog = () => setContactDetailDialogOpen(false);
-
     return (
       <ContactDetailDialog
         contactDetail={contactDetail}
@@ -102,72 +68,34 @@
   if (isLoading) {
     return <LoadingPage />;
   }
+
   return (
     <>
-      <Modal
-        isOpen={parentModalOpen}
-        onRequestClose={closeParentModal}
-        style={customStyles}
-        contentLabel="Example Modal"
-      >
-        <button onClick={closeParentModal}>close</button>
-
-        <div style={{ display: 'flex', flexDirection: 'column', rowGap: '10px' }}>
-          <button
-            onClick={() => {
-              console.log('open dialog Supprimer: ');
-              setIsBlocking(false);
-              openChildModal();
-            }}
-          >
-            <Person /> Supprimer contact
-          </button>
-
-          <button
-            onClick={() => {
-              console.log('open dialog BLOCK: ');
-              setIsBlocking(true);
-              openChildModal();
-            }}
-          >
-            <Person /> Bloquer le contact
-          </button>
-
-          <button
-            onClick={() => {
-              console.log('open details contact for: ');
-              closeParentModal();
-              setContactDetailDialogOpen(true);
-            }}
-          >
-            <Person /> Détails du contact
-          </button>
-        </div>
-      </Modal>
-
-      <Modal
-        isOpen={childModalOpen}
-        onRequestClose={closeChildModal}
-        style={customStyles}
-        contentLabel="Merci de confirmer"
-      >
-        <Box>
-          <div>
-            Voulez vous vraiment {isBlocking ? 'bloquer' : 'supprimer'} ce contact {currentContactId}?
-          </div>
-          <br />
-
-          <button onClick={isBlocking ? blockContact : removeContact}>{isBlocking ? 'bloquer' : 'supprimer'}</button>
-
-          <button onClick={closeChildModal}>Annuler</button>
-        </Box>
-      </Modal>
-
+      <ContactDialog
+        isBlocking={isBlocking}
+        open={dialogOpen}
+        closeContactDialog={closeContactDialog}
+        currentContactId={currentContactId}
+      />
       {ContactDetailDialogElement}
 
+      <ContactMenu
+        contextMenuProps={contextMenuHandler.props}
+        openContactDialog={openContactDialog}
+        setIsBlocking={setIsBlocking}
+        setContactDetailDialogOpen={setContactDetailDialogOpen}
+      />
+
       <List>
         {contacts?.map((contact) => (
-          <ListItem alignItems="flex-start" key={contact.id} onClick={() => handleClickContact(contact.id)}>
+          <ListItem
+            alignItems="flex-start"
+            key={contact.id}
+            onContextMenu={(e) => {
+              setCurrentContactId(contact.id);
+              contextMenuHandler.handleAnchorPosition(e);
+            }}
+          >
             <ListItemAvatar>
               <ConversationAvatar />
             </ListItemAvatar>
@@ -178,3 +106,82 @@
     </>
   );
 }
+
+interface ContactMenuProps {
+  contextMenuProps: ContextMenuHandler['props'];
+  openContactDialog: () => void;
+  setIsBlocking: React.Dispatch<SetStateAction<boolean>>;
+  setContactDetailDialogOpen: React.Dispatch<SetStateAction<boolean>>;
+}
+
+const ContactMenu = ({
+  contextMenuProps,
+  openContactDialog,
+  setIsBlocking,
+  setContactDetailDialogOpen,
+}: ContactMenuProps) => {
+  const { t } = useTranslation();
+  const menuOptions: PopoverListItemData[] = useMemo(
+    () => [
+      {
+        label: t('contact_details_text'),
+        Icon: PersonIcon,
+        onClick: () => {
+          setContactDetailDialogOpen(true);
+        },
+      },
+      {
+        label: t('contact_block'),
+        Icon: BlockContactIcon,
+        onClick: () => {
+          openContactDialog();
+          setIsBlocking(true);
+        },
+      },
+      {
+        label: t('contact_remove'),
+        Icon: CancelIcon,
+        onClick: () => {
+          openContactDialog();
+          setIsBlocking(false);
+        },
+      },
+    ],
+    [t, setIsBlocking, setContactDetailDialogOpen, openContactDialog]
+  );
+  return <ContextMenu {...contextMenuProps} items={menuOptions} />;
+};
+
+interface ContactDialogProps {
+  isBlocking: boolean;
+  open: boolean;
+  closeContactDialog: () => void;
+  currentContactId: string;
+}
+
+const ContactDialog = memo(({ isBlocking, open, closeContactDialog, currentContactId }: ContactDialogProps) => {
+  const removeContactMutation = useRemoveContactMutation();
+  const blockContactMutation = useBlockContactMutation();
+
+  const removeContact = (): void => {
+    removeContactMutation.mutate(currentContactId);
+    closeContactDialog();
+  };
+
+  const blockContact = (): void => {
+    blockContactMutation.mutate(currentContactId);
+    closeContactDialog();
+  };
+
+  const { t } = useTranslation();
+  return (
+    <ConfirmationDialog
+      open={open}
+      onClose={closeContactDialog}
+      title={t('dialog_confirm_title_default')}
+      content={isBlocking ? t('contact_ask_confirm_block') : t('contact_ask_confirm_remove')}
+      onConfirm={isBlocking ? blockContact : removeContact}
+      confirmButtonText={isBlocking ? t('contact_confirm_block') : t('contact_confirm_remove')}
+    />
+  );
+});