diff --git a/src/components/Tool/FixEmailAddresses/EmailValidationForm.tsx b/src/components/Tool/FixEmailAddresses/EmailValidationForm.tsx index 14753e151..50c50579a 100644 --- a/src/components/Tool/FixEmailAddresses/EmailValidationForm.tsx +++ b/src/components/Tool/FixEmailAddresses/EmailValidationForm.tsx @@ -1,18 +1,50 @@ -import { Grid, IconButton, TextField } from '@mui/material'; +import { + Box, + FormControl, + FormHelperText, + Grid, + IconButton, + TextField, + Theme, + Tooltip, +} from '@mui/material'; import { styled } from '@mui/material/styles'; -import { Form, Formik } from 'formik'; +import clsx from 'clsx'; +import { Formik } from 'formik'; import { useSnackbar } from 'notistack'; import { useTranslation } from 'react-i18next'; +import { makeStyles } from 'tss-react/mui'; import * as yup from 'yup'; import { AddIcon } from 'src/components/Contacts/ContactDetails/ContactDetailsTab/StyledComponents'; import i18n from 'src/lib/i18n'; import { useEmailAddressesMutation } from './AddEmailAddress.generated'; -import { RowWrapper } from './FixEmailAddressPerson/FixEmailAddressPerson'; import { GetInvalidEmailAddressesDocument, GetInvalidEmailAddressesQuery, } from './FixEmailAddresses.generated'; +const useStyles = makeStyles()((theme: Theme) => ({ + responsiveBorder: { + [theme.breakpoints.down('xs')]: { + paddingBottom: theme.spacing(2), + borderBottom: `1px solid ${theme.palette.cruGrayMedium.main}`, + }, + }, + paddingX: { + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + }, + paddingB2: { + paddingBottom: theme.spacing(1), + }, + iconButton: { + display: 'flex', + alignItems: 'center', + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + }, +})); + const ContactInputField = styled(TextField, { shouldForwardProp: (prop) => prop !== 'destroyed', })(({ destroyed }: { destroyed: boolean }) => ({ @@ -52,6 +84,7 @@ const EmailValidationForm = ({ const { t } = useTranslation(); const [emailAddressesMutation] = useEmailAddressesMutation(); const { enqueueSnackbar } = useSnackbar(); + const { classes } = useStyles(); const initialEmail = { email: '', @@ -134,34 +167,60 @@ const EmailValidationForm = ({ validationSchema={validationSchema} onSubmit={onSubmit} > - {({ values, handleChange, handleBlur, isValid, touched, errors }) => ( -
- - - + {({ + values, + handleChange, + handleBlur, + touched, + errors, + handleSubmit, + isValid, + }) => ( + <> + + + + + + handleSubmit()} + className={classes.iconButton} disabled={!isValid || values.email === ''} data-testid={`addButton-${initialEmail.personId}`} > - + + + - - -
+ + + + {touched.email && Boolean(errors.email) && ( + <> + + + + {errors.email} + + + + )} + )} ); diff --git a/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.test.tsx b/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.test.tsx index d7b4a9963..a5f4e6e5b 100644 --- a/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.test.tsx +++ b/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.test.tsx @@ -24,6 +24,7 @@ const person: PersonInvalidEmailFragment = { firstName: 'Test', lastName: 'Contact', contactId: 'contactTestId', + avatar: '', emailAddresses: { nodes: [ { diff --git a/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.tsx b/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.tsx index 2d02bb4a5..bc9b3382e 100644 --- a/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.tsx +++ b/src/components/Tool/FixEmailAddresses/FixEmailAddressPerson/FixEmailAddressPerson.tsx @@ -1,18 +1,25 @@ import React, { Fragment, useMemo } from 'react'; -import { mdiDelete, mdiLock, mdiStar, mdiStarOutline } from '@mdi/js'; +import { mdiCheckboxMarkedCircle, mdiDelete, mdiLock } from '@mdi/js'; import { Icon } from '@mdi/react'; +import StarIcon from '@mui/icons-material/Star'; +import StarOutlineIcon from '@mui/icons-material/StarOutline'; import { Avatar, Box, Button, + Card, + CardContent, + CardHeader, + FormControl, Grid, Hidden, Link, TextField, Theme, + Tooltip, Typography, } from '@mui/material'; -import { styled } from '@mui/material/styles'; +import clsx from 'clsx'; import { DateTime } from 'luxon'; import { useSnackbar } from 'notistack'; import { useTranslation } from 'react-i18next'; @@ -24,75 +31,65 @@ import useGetAppSettings from 'src/hooks/useGetAppSettings'; import { useLocale } from 'src/hooks/useLocale'; import { dateFormatShort } from 'src/lib/intlFormat'; import theme from 'src/theme'; -import { ConfirmButtonIcon } from '../../ConfirmButtonIcon'; import EmailValidationForm from '../EmailValidationForm'; import { EmailAddressData, PersonEmailAddresses } from '../FixEmailAddresses'; import { PersonInvalidEmailFragment } from '../FixEmailAddresses.generated'; -const PersonCard = styled(Box)(({ theme }) => ({ - [theme.breakpoints.up('md')]: { - border: `1px solid ${theme.palette.cruGrayMedium.main}`, +const useStyles = makeStyles()((theme: Theme) => ({ + responsiveBorder: { + [theme.breakpoints.down('xs')]: { + paddingBottom: theme.spacing(2), + borderBottom: `1px solid ${theme.palette.cruGrayMedium.main}`, + }, }, -})); - -const Container = styled(Grid)(({ theme }) => ({ - display: 'flex', - flexDirection: 'row', - justifyContent: 'flex-end', - [theme.breakpoints.down('sm')]: { - border: `1px solid ${theme.palette.cruGrayMedium.main}`, + paddingX: { + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), }, -})); - -const EmailAddressListWrapper = styled(Grid)(({ theme }) => ({ - backgroundColor: theme.palette.cruGrayLight.main, - width: '100%', - [theme.breakpoints.down('xs')]: { - paddingTop: theme.spacing(2), + paddingY: { + paddingTop: theme.spacing(1), + paddingBottom: theme.spacing(1), }, -})); - -const ConfirmButtonWrapper = styled(Box)(({ theme }) => ({ - marginLeft: theme.spacing(2), - [theme.breakpoints.down('sm')]: { - marginLeft: theme.spacing(1), - marginRight: theme.spacing(2), - marginTop: theme.spacing(2), - marginBottom: theme.spacing(2), + paddingB2: { + paddingBottom: theme.spacing(1), }, - '& .MuiButton-root': { - backgroundColor: theme.palette.mpdxBlue.main, - color: 'white', + hoverHighlight: { + '&:hover': { + color: theme.palette.mpdxBlue.main, + cursor: 'pointer', + }, }, -})); - -const BoxWithResponsiveBorder = styled(Box)(({ theme }) => ({ - [theme.breakpoints.down('xs')]: { + contactAvatar: { + width: theme.spacing(4), + height: theme.spacing(4), + }, + contactCardContent: { + paddingLeft: theme.spacing(2), + paddingRight: theme.spacing(2), + paddingTop: theme.spacing(2), paddingBottom: theme.spacing(2), - borderBottom: `1px solid ${theme.palette.cruGrayMedium.main}`, }, -})); - -const ColumnHeaderWrapper = styled(Grid)(({ theme }) => ({ - paddingTop: theme.spacing(2), - paddingBottom: theme.spacing(2), -})); - -export const RowWrapper = styled(Grid)(({ theme }) => ({ - paddingBottom: theme.spacing(2), -})); - -const HoverableIcon = styled(Icon)(({ theme }) => ({ - '&:hover': { - color: theme.palette.mpdxBlue.main, - cursor: 'pointer', + confirmButon: { + marginRight: theme.spacing(1), }, -})); - -const useStyles = makeStyles()((theme: Theme) => ({ - avatar: { - width: theme.spacing(7), - height: theme.spacing(7), + contactCard: { + marginBottom: theme.spacing(2), + }, + contactContainer: { + display: 'block', + alignItems: 'center', + width: '99%', + margin: 'auto', + height: '100%', + marginBottom: theme.spacing(3), + }, + contactHeader: { + '.MuiCardHeader-action': { + alignSelf: 'center', + }, + }, + buttonIcon: { + marginRight: theme.spacing(1), }, })); @@ -227,186 +224,270 @@ export const FixEmailAddressPerson: React.FC = ({ return ( <> - + - - + + - - - + + } + action={ + + } + title={ - {name} + + {name} + - - + } + /> - - - - + + + + + - - {t('Source')} + + {t('Source')} - - {t('Primary')} + + + + + + {t('Primary')} - - + + - - {t('Address')} + + {t('Email Address')} - + {emails.map((email, index) => ( - + - - {t('Source')}: + + {t('Source')}: - + {`${email.source} (${dateFormatShort( DateTime.fromISO(email.updatedAt), locale, )})`} - {email.isPrimary ? ( - handleChangePrimary(id, index)} - > - - - ) : ( - handleChangePrimary(id, index)} - > - - - )} - - - + + + + + {email.isPrimary ? ( + <> + + + {t('Source')}: + + + + handleChangePrimary(id, index) + } + /> + + ) : ( + <> + + + {t('Source')}: + + + + + handleChangePrimary(id, index) + } + /> + + + )} + + + + + - , - ) => handleChange(id, index, event)} - value={email.email} - disabled={email.source !== appName} - /> + + , + ) => handleChange(id, index, event)} + value={email.email} + disabled={email.source !== appName} + /> + {email.source === appName ? ( handleDeleteEmailOpen({ id, email }) } + className={classes.paddingX} > - + + + ) : ( - + + + )} - - + + ))} - - + + + - - {t('Source')}: + + {t('Source')}: - {appName} + + {appName} + - - - - - - + + + - + - - - - - - - - + - - + {deleteModalOpen && emailToDelete && ( ({ })); const ConfirmButton = styled(Button)(({ theme }) => ({ - backgroundColor: theme.palette.mpdxBlue.main, - paddingRight: theme.spacing(1.5), color: 'white', [theme.breakpoints.down('xs')]: { marginTop: theme.spacing(1), marginBottom: theme.spacing(2), }, - '&:hover': { - backgroundColor: theme.palette.mpdxBlue.main, - }, })); const DefaultSourceWrapper = styled(Box)(({ theme }) => ({ @@ -338,6 +333,7 @@ export const FixEmailAddresses: React.FC = ({ ))} setShowBulkConfirmModal(true)} > @@ -352,29 +348,24 @@ export const FixEmailAddresses: React.FC = ({ {!!data.people.nodes.length ? ( - <> + ( - - + + + + )} endReached={() => @@ -409,7 +400,7 @@ export const FixEmailAddresses: React.FC = ({ - + ) : ( )} diff --git a/src/components/Tool/FixEmailAddresses/FixEmailAddressesMocks.ts b/src/components/Tool/FixEmailAddresses/FixEmailAddressesMocks.ts index 5cca43e5b..232252842 100644 --- a/src/components/Tool/FixEmailAddresses/FixEmailAddressesMocks.ts +++ b/src/components/Tool/FixEmailAddresses/FixEmailAddressesMocks.ts @@ -63,6 +63,7 @@ export const mockInvalidEmailAddressesResponse: ErgonoMockShape[] = [ firstName: 'Test', lastName: 'Contact', contactId, + avatar: '', emailAddresses: { nodes: contactOneEmailAddressNodes, }, @@ -72,6 +73,7 @@ export const mockInvalidEmailAddressesResponse: ErgonoMockShape[] = [ firstName: 'Simba', lastName: 'Lion', contactId: 'contactId2', + avatar: '', emailAddresses: { nodes: contactTwoEmailAddressNodes, },