diff --git a/src/pages/ExamsPage/components/AddAllowanceModal.jsx b/src/pages/ExamsPage/components/AddAllowanceModal.jsx
index dc03279..41929ab 100644
--- a/src/pages/ExamsPage/components/AddAllowanceModal.jsx
+++ b/src/pages/ExamsPage/components/AddAllowanceModal.jsx
@@ -188,7 +188,7 @@ const AddAllowanceModal = ({ isOpen, close }) => {
value={form['allowance-type']}
data-testid="allowance-type"
>
-
+
@@ -202,7 +202,7 @@ const AddAllowanceModal = ({ isOpen, close }) => {
onChange={handleChange}
data-testid="additional-time-minutes"
/>
- { additionalTimeError &&
{ formatMessage(messages.addAllowanceMinutesErrorFeedback) } }
+ { additionalTimeError && { formatMessage(messages.allowanceMinutesErrorFeedback) } }
)
: (
diff --git a/src/pages/ExamsPage/components/AddAllowanceModal.test.jsx b/src/pages/ExamsPage/components/AddAllowanceModal.test.jsx
index e97cb1c..5680d1f 100644
--- a/src/pages/ExamsPage/components/AddAllowanceModal.test.jsx
+++ b/src/pages/ExamsPage/components/AddAllowanceModal.test.jsx
@@ -79,7 +79,7 @@ describe('AddAllowanceModal', () => {
fireEvent.click(screen.getByTestId('create-allowance-stateful-button'));
expect(screen.getByText('Enter learners')).toBeInTheDocument();
expect(screen.getByText('Select exams')).toBeInTheDocument();
- expect(screen.getByText('Enter minutes')).toBeInTheDocument();
+ expect(screen.getByText('Enter minutes greater than 0')).toBeInTheDocument();
});
it('should show an alert if the request fails', () => {
diff --git a/src/pages/ExamsPage/components/AllowanceList.jsx b/src/pages/ExamsPage/components/AllowanceList.jsx
index 6e3f545..5e3f971 100644
--- a/src/pages/ExamsPage/components/AllowanceList.jsx
+++ b/src/pages/ExamsPage/components/AllowanceList.jsx
@@ -39,6 +39,7 @@ const AllowanceList = () => {
examName,
allowanceType: formatMessage(messages.allowanceTypeMinutes),
extraTimeMins,
+ username,
};
const user = acc.find(u => u.userId === userId);
diff --git a/src/pages/ExamsPage/components/AllowanceList.test.jsx b/src/pages/ExamsPage/components/AllowanceList.test.jsx
index a1091ca..666817e 100644
--- a/src/pages/ExamsPage/components/AllowanceList.test.jsx
+++ b/src/pages/ExamsPage/components/AllowanceList.test.jsx
@@ -38,6 +38,7 @@ jest.mock('../hooks', () => ({
useButtonStateFromRequestStatus: jest.fn(),
useCreateAllowance: jest.fn(),
useFilteredExamsData: jest.fn(),
+ useEditAllowance: jest.fn(),
useDeleteAllowance: jest.fn(),
}));
diff --git a/src/pages/ExamsPage/components/AllowanceListActions.jsx b/src/pages/ExamsPage/components/AllowanceListActions.jsx
index fd9cf63..cfc474a 100644
--- a/src/pages/ExamsPage/components/AllowanceListActions.jsx
+++ b/src/pages/ExamsPage/components/AllowanceListActions.jsx
@@ -1,17 +1,144 @@
import { PropTypes } from 'prop-types';
import {
- ActionRow,
+ ActionRow, Alert,
Button,
+ Form,
Icon,
IconButtonWithTooltip,
ModalDialog,
useToggle,
} from '@openedx/paragon';
-import { DeleteOutline, EditOutline } from '@openedx/paragon/icons';
+import { DeleteOutline, EditOutline, Info } from '@openedx/paragon/icons';
import { useIntl } from '@edx/frontend-platform/i18n';
+import React, { useState } from 'react';
import messages from '../messages';
-import { useDeleteAllowance } from '../hooks';
+import { useDeleteAllowance, useEditAllowance } from '../hooks';
+import { useClearRequest, useRequestError } from '../../../data/redux/hooks';
+import * as constants from '../../../data/constants';
+
+const EditModal = (isOpen, close, allowance, formatMessage) => {
+ const editAllowance = useEditAllowance();
+ const [additionalTimeError, setAdditionalTimeError] = useState(false);
+ const requestError = useRequestError(constants.RequestKeys.createAllowance);
+ const resetRequestError = useClearRequest(constants.RequestKeys.createAllowance);
+
+ const initialFormState = {
+ username: allowance.username,
+ 'exam-id': allowance.examId,
+ 'exam-name': allowance.examName,
+ };
+ const [form, setForm] = useState(initialFormState);
+
+ const handleChange = (event) => {
+ const { name, value } = event.target;
+ resetRequestError();
+ setForm(prev => ({ ...prev, [name]: value }));
+ };
+
+ const onClose = () => {
+ resetRequestError();
+ setForm(initialFormState);
+ close();
+ };
+
+ const onSubmit = () => {
+ const extraTimeMins = +form['extra-time-mins'] || 0;
+ // todo: We should maybe move the handling of this validation to the backend,
+ // as this should also be handled for the add allowance modal.
+ const valid = (
+ extraTimeMins
+ && extraTimeMins > 0
+ );
+ setAdditionalTimeError(!valid);
+ if (valid) {
+ const payload = {
+ username: form.username,
+ exam_id: form['exam-id'],
+ extra_time_mins: extraTimeMins,
+ };
+ editAllowance(allowance.id, payload, () => {
+ setForm(initialFormState);
+ onClose();
+ });
+ }
+ };
+
+ return (
+
+
+
+ {formatMessage(messages.editAllowanceHeader)}
+
+
+
+ { requestError
+ && (
+
+ { formatMessage(messages.addAllowanceFailedAlertHeader) }
+
+ { requestError.detail }
+
+
+ )}
+
+ { formatMessage(messages.allowanceUsernameField) }
+
+
+
+ { formatMessage(messages.editAllowanceExamField) }
+
+
+
+ { formatMessage(messages.allowanceTypeField) }
+
+ {formatMessage(messages.allowanceAdditionalMinutesOption)}
+
+
+
+ { formatMessage(messages.allowanceMinutesField) }
+
+ { additionalTimeError && { formatMessage(messages.allowanceMinutesErrorFeedback) } }
+
+
+
+
+
+
+ {formatMessage(messages.allowanceCancelButton)}
+
+
+
+
+
+ );
+};
const DeleteModal = (isOpen, onCancel, onDelete, formatMessage) => (
(
- {formatMessage(messages.deleteAllowanceCancel)}
+ {formatMessage(messages.allowanceCancelButton)}