blob: 02bc99a15dc09537986050a5affe8e109714b528 [file] [log] [blame]
/*
* Copyright (C) 2022 Savoir-faire Linux Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this program. If not, see
* <https://www.gnu.org/licenses/>.
*/
import { ListItem, ListItemAvatar, ListItemText } from '@mui/material';
import List from '@mui/material/List';
import { memo, SetStateAction, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
useBlockContactMutation,
useContactListQuery,
useContactQuery,
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';
import { PopoverListItemData } from './PopoverList';
import { BlockContactIcon, CancelIcon, PersonIcon } from './SvgIcon';
export default function ContactList() {
const [currentContactId, setCurrentContactId] = useState<string>('');
const [isBlocking, setIsBlocking] = useState(true);
const [contactDetailDialogOpen, setContactDetailDialogOpen] = useState<boolean>(false);
const contactListQuery = useContactListQuery();
const { isLoading, data: contacts } = contactListQuery;
const singleContactQuery = useContactQuery(currentContactId);
const { data: contactDetail } = singleContactQuery;
const contextMenuHandler = useContextMenuHandler();
const {
props: { open: dialogOpen, onClose: closeContactDialog },
openDialog: openContactDialog,
} = useDialogHandler();
const ContactDetailDialogElement = useMemo(() => {
const onClosingContactDetailDialog = () => setContactDetailDialogOpen(false);
return (
<ContactDetailDialog
contactDetail={contactDetail}
open={contactDetailDialogOpen}
onClose={onClosingContactDetailDialog}
/>
);
}, [contactDetail, contactDetailDialogOpen]);
if (isLoading) {
return <LoadingPage />;
}
return (
<>
<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}
onContextMenu={(e) => {
setCurrentContactId(contact.id);
contextMenuHandler.handleAnchorPosition(e);
}}
>
<ListItemAvatar>
<ConversationAvatar />
</ListItemAvatar>
<ListItemText primary={contact.id} secondary={contact.id} />
</ListItem>
))}
</List>
</>
);
}
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')}
/>
);
});