Skip to content

Commit 97c5cbb

Browse files
fix: error message on specify learner
1 parent 5f481e8 commit 97c5cbb

3 files changed

Lines changed: 35 additions & 13 deletions

File tree

src/components/SpecifyLearnerField.tsx

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,24 @@ interface SpecifyLearnerFieldRef {
1818
reset: () => void,
1919
}
2020

21+
type ErrorState = 'not_enrolled' | 'not_found' | 'generic_error' | null;
22+
23+
const errorMessages = {
24+
not_found: messages.learnerNotFound,
25+
generic_error: messages.learnerGenericError,
26+
not_enrolled: messages.learnerNotEnrolled,
27+
};
28+
29+
const getErrorState = (error: Error | null, data?: SelectedLearner): ErrorState => {
30+
const isNotFoundError = isAxiosError(error)
31+
&& (error.response?.status === 404 || error.response?.status === 400);
32+
33+
if (isNotFoundError) return 'not_found';
34+
if (data && !data.isEnrolled) return 'not_enrolled';
35+
if (error && !isNotFoundError) return 'generic_error';
36+
return null;
37+
};
38+
2139
const initialLearnerState = {
2240
username: '',
2341
fullName: '',
@@ -30,18 +48,20 @@ const SpecifyLearnerField = forwardRef<SpecifyLearnerFieldRef, SpecifyLearnerFie
3048
const { courseId = '' } = useParams<{ courseId: string }>();
3149
const [identifier, setIdentifier] = useState('');
3250
const [showLearner, enableShowLearner, disableShowLearner] = useToggle(!!learner);
51+
const [errorState, setErrorState] = useState<ErrorState>(null);
3352
const { data: courseInfo } = useCourseInfo(courseId);
3453
const permissions = courseInfo?.permissions || { admin: false, dataResearcher: false };
3554
const { inputValue, handleChange, resetFilter } = useDebouncedFilter({
3655
filterValue: identifier,
3756
setFilter: setIdentifier,
3857
});
39-
const { data, refetch, error } = useLearner(courseId, inputValue);
58+
const { data, refetch } = useLearner(courseId, inputValue);
4059

4160
const resetState = () => {
4261
resetFilter();
4362
onClickSelect('');
4463
disableShowLearner();
64+
setErrorState(null);
4565
};
4666

4767
useImperativeHandle(ref, () => ({
@@ -53,6 +73,10 @@ const SpecifyLearnerField = forwardRef<SpecifyLearnerFieldRef, SpecifyLearnerFie
5373
const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => {
5474
handleChange(event.target.value);
5575

76+
if (errorState) {
77+
setErrorState(null);
78+
}
79+
5680
if (showLearner) {
5781
disableShowLearner();
5882
}
@@ -64,6 +88,8 @@ const SpecifyLearnerField = forwardRef<SpecifyLearnerFieldRef, SpecifyLearnerFie
6488
// Need to pass empty value if learner is not valid to clear out any previously selected learner
6589
// We could have other conditions/fields depending on valid learner
6690
const formValue = !result.error && result.data?.isEnrolled ? inputValue : '';
91+
92+
setErrorState(getErrorState(result.error, result?.data));
6793
onClickSelect(formValue);
6894
enableShowLearner();
6995
});
@@ -102,20 +128,11 @@ const SpecifyLearnerField = forwardRef<SpecifyLearnerFieldRef, SpecifyLearnerFie
102128
<Button onClick={handleClickSelect} disabled={!inputValue}>{intl.formatMessage(messages.select)}</Button>
103129
)}
104130
</div>
105-
{showLearner && error
106-
&& isAxiosError(error)
107-
&& error.response?.status === 404 && (
131+
{showLearner && errorState && (
108132
<p className="text-danger-500 mb-0 x-small mt-2">
109-
{intl.formatMessage(messages.learnerNotFound, { identifier })}
133+
{intl.formatMessage(errorMessages[errorState], { identifier: inputValue })}
110134
</p>
111135
)}
112-
{
113-
showLearner && !error && !selectedLearner?.isEnrolled && (
114-
<p className="text-danger-500 mb-0 x-small mt-2">
115-
{intl.formatMessage(messages.learnerNotEnrolled, { identifier })}
116-
</p>
117-
)
118-
}
119136
</FormGroup>
120137
);
121138
});

src/components/SpecifyProblemField.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ const SpecifyProblemField = forwardRef<SpecifyProblemFieldRef, SpecifyProblemFie
127127
</div>
128128
{showSelectedLocation && error
129129
&& isAxiosError(error)
130-
&& (error.response?.status === 400) && (
130+
&& ((error.response?.status === 400) || (error.response?.status === 404)) && (
131131
<p className="text-danger-500 mb-0 x-small mt-2">
132132
{intl.formatMessage(messages.problemNotFound, { identifier: inputValue })}
133133
</p>

src/components/messages.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,11 @@ const messages = defineMessages({
156156
defaultMessage: 'Selected Learner:',
157157
description: 'Label for specify learner field when a learner has been selected',
158158
},
159+
learnerGenericError: {
160+
id: 'instruct.specifyLearner.learnerGenericError',
161+
defaultMessage: 'An error occurred while looking up {identifier}. Please try again.',
162+
description: 'Generic error message displayed when there is an error looking up a learner based on the provided identifier (email or username)',
163+
}
159164
});
160165

161166
export default messages;

0 commit comments

Comments
 (0)