Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,30 @@ describe('TransferModal', () => {
).toBeInTheDocument();
});

it('should allow editing the transfer date for one-time transfers', async () => {
const { getByLabelText } = render(<Components />);

const transferDate = getByLabelText(/transfer date/i);
expect(transferDate).toBeEnabled();

userEvent.clear(transferDate);
userEvent.type(transferDate, '12/01/2099');
expect(transferDate).toHaveValue('12/01/2099');
});

it('should reject a past transfer date for one-time transfers', async () => {
const { getByLabelText, findByText } = render(<Components />);

const transferDate = getByLabelText(/transfer date/i);
userEvent.clear(transferDate);
userEvent.type(transferDate, '12/31/2019');
userEvent.tab();

expect(
await findByText('Transfer start date cannot be in the past'),
).toBeInTheDocument();
});

it('should show error message when monthly schedule is selected', async () => {
const { getByRole, getByLabelText, findByText } = render(<Components />);

Expand Down Expand Up @@ -464,8 +488,8 @@ describe('TransferModal', () => {
});

describe('Mutations', () => {
it('should create a one-time transfer', async () => {
const { getByRole } = render(<Components />);
it('should create a one-time transfer with the selected transfer date', async () => {
const { getByRole, getByLabelText } = render(<Components />);

const amountField = getByRole('spinbutton', { name: /amount/i });

Expand All @@ -475,6 +499,12 @@ describe('TransferModal', () => {
userEvent.clear(amountField);
userEvent.type(amountField, '100');

const transferDate = getByLabelText(/transfer date/i);
userEvent.clear(transferDate);
userEvent.type(transferDate, '12/01/2099');
expect(transferDate).toHaveValue('12/01/2099');
userEvent.tab();

userEvent.click(getByRole('button', { name: /submit/i }));

await waitFor(() => {
Expand All @@ -487,6 +517,7 @@ describe('TransferModal', () => {
sourceFundTypeName: 'Staff Account',
destinationFundTypeName: 'Staff Savings',
description: '',
transactedAt: '2099-12-01T00:00:00.000+00:00',
}),
}),
}),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,12 @@
}

return this.createError({
message: i18n.t(
'Recurring transfers must start at least one day in the future',
),
message:
schedule === ScheduleEnum.OneTime
? i18n.t('Transfer start date cannot be in the past')
: i18n.t(
'Recurring transfers must start at least one day in the future',
),
});
}),
endDate: yup
Expand Down Expand Up @@ -216,224 +219,235 @@
sourceFundTypeName: transferFrom,
destinationFundTypeName: transferTo,
description: note,
transactedAt: convertedTransferDate,
},
});
} else {
await updateRecurringTransfer({
variables: {
id: data.transfer.recurringId ?? '',
amount: amount,
recurringStart: convertedTransferDate,
recurringEnd: convertedEndDate,
},
});
}

enqueueSnackbar(successMessage, {
variant: 'success',
});
handleClose();
} catch (error) {
enqueueSnackbar(errorMessage, {
variant: 'error',
});
} finally {
setSubmitting(false);
}
};

return (
<Modal title={title} isOpen={true} handleClose={handleClose} size="md">
<Formik
initialValues={{
transferFrom: data.transfer.transferFrom ?? '',
transferTo: data.transfer.transferTo ?? '',
amount: data.transfer.amount ?? 0,
schedule: data.transfer.schedule ?? ScheduleEnum.OneTime,
status: data.transfer.status ?? '',
transferDate: data.transfer.transferDate ?? getToday(),
endDate: data.transfer.endDate ?? null,
note: data.transfer.note ?? '',
isEditing: Boolean(data.transfer.id),
originalStart: data.transfer.transferDate ?? null,
}}
validationSchema={transferSchema(locale)}
onSubmit={handleSubmit}
>
{({
values: {
transferFrom,
transferTo,
schedule,
transferDate,
endDate,
amount,
note,
},
isSubmitting,
isValid,
touched,
errors,
handleSubmit,
handleChange,
setFieldValue,
setFieldTouched,
validateField,
handleBlur,
}) => {
const locale = useLocale();

const fund = funds.find((f) => f.fundType === transferFrom);
const projected = fund ? fund.endBalance - amount : null;
const showAlert =
!!fund &&
projected !== null &&
projected < -(fund.deficitLimit ?? 0);

return (
<form onSubmit={handleSubmit} noValidate>
<DialogContent dividers>
<Box sx={{ mb: 3 }}>
<Typography variant="h6" gutterBottom>
{t('Transfer Between Accounts')}
</Typography>

{isNew ? (
<Grid container spacing={2} alignItems="center">
<Grid item xs={12} sm={5.5}>
<FormControl fullWidth>
<InputLabel id="transferFrom">
{t('From Account')}
</InputLabel>
<TransferModalSelect
funds={funds.filter(
(fund) => fund.fundType === transferFrom,
)}
label={t('From Account')}
labelId="transferFrom"
name="transferFrom"
value={transferFrom}
readOnly
IconComponent={() => null}
required
/>
</FormControl>
</Grid>

<Grid
item
xs={12}
sm={1}
sx={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
}}
>
<ArrowRightAlt />
</Grid>

<Grid item xs={12} sm={5.5}>
<FormControl fullWidth>
<InputLabel id="transferTo">
{t('To Account')}
</InputLabel>
<TransferModalSelect
notSelected={transferFrom}
funds={funds}
label={t('To Account')}
labelId="transferTo"
name="transferTo"
value={transferTo}
onChange={handleChange}
onBlur={handleBlur}
error={
touched.transferTo && Boolean(errors.transferTo)
}
required
/>
{touched.transferTo && errors.transferTo && (
<FormHelperText error={true}>
{errors.transferTo}
</FormHelperText>
)}
</FormControl>
</Grid>
</Grid>
) : (
<Grid container spacing={2} alignItems="center">
<Grid
item
xs={12}
sm={5.5}
sx={{
display: 'flex',
justifyContent: 'flex-end',
alignItems: 'center',
}}
>
<FundInfoDisplay fund={fund} />
</Grid>
<Grid item xs={12} sm={1} sx={{ textAlign: 'center' }}>
<ArrowRightAlt />
</Grid>
<Grid item xs={12} sm={5.5}>
<FundInfoDisplay
fund={funds.find((f) => f.fundType === transferTo)}
/>
</Grid>
</Grid>
)}
</Box>

{isNew && (
<Box sx={{ mb: 3 }}>
<FormControl
component="fieldset"
error={touched.schedule && Boolean(errors.schedule)}
>
<FormLabel component="legend">{t('Schedule')}</FormLabel>
<RadioGroup
row
name="schedule"
value={schedule}
onChange={(_event, value) => {
setFieldValue('schedule', value);
if (value === ScheduleEnum.Monthly) {
setFieldTouched('transferDate', true, false);
}
validateField('transferDate');
}}
>
<FormControlLabel
value={ScheduleEnum.OneTime}
control={<Radio />}
label={t('One Time')}
/>
<FormControlLabel
value={ScheduleEnum.Monthly}
control={<Radio />}
label={t('Monthly')}
/>
</RadioGroup>
{touched.schedule && errors.schedule && (
<FormHelperText error={true}>
{errors.schedule}
</FormHelperText>
)}
</FormControl>
</Box>
)}

<Box sx={{ mb: 3 }}>
<Grid container spacing={2}>
{schedule === ScheduleEnum.OneTime ? (
<Grid item xs={12}>
<TextField
fullWidth
<CustomDateField
label={t('Transfer Date')}
value={transferDate.toFormat('MM/dd/yyyy')}
disabled={true}
value={transferDate}
onChange={(date) => {
setFieldValue('transferDate', date);
setFieldTouched('transferDate', true, false);
}}
error={
touched.transferDate && Boolean(errors.transferDate)
}
helperText={
touched.transferDate &&
(errors.transferDate as string)
}
required

Check warning on line 450 in src/components/HrTools/SavingsFundTransfer/TransferModal/TransferModal.tsx

View check run for this annotation

CodeScene Delta Analysis / CodeScene Code Health Review (main)

❌ Getting worse: Complex Method

TransferModal:React.FC<TransferModalProps> increases in cyclomatic complexity from 39 to 41, threshold = 15. This function has many conditional statements (e.g. if, for, while), leading to lower code health. Avoid adding more conditionals and code to it without refactoring.
/>
</Grid>
) : (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,15 @@ mutation CreateTransfer(
$destinationFundTypeName: String!
$description: String!
$amount: Float!
$transactedAt: ISO8601DateTime!
) {
createTransfer(
input: {
sourceFundTypeName: $sourceFundTypeName
destinationFundTypeName: $destinationFundTypeName
description: $description
amount: $amount
transactedAt: $transactedAt
}
) {
message
Expand Down
Loading