Skip to content

Commit 1176486

Browse files
committed
fix: enhance error handling and validation in profile form fields
1 parent 55ecc1e commit 1176486

File tree

3 files changed

+45
-9
lines changed

3 files changed

+45
-9
lines changed

src/profile/forms/ExtendedProfileFields.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ const ExtendedProfileFields = (props) => {
5252

5353
const commonProps = {
5454
...field,
55+
errorMessage: field.error_message,
5556
formId: `${formId}/${field.name}`,
5657
changeHandler: handleChangeExtendedField,
5758
submitHandler: handleSubmitExtendedField,
@@ -92,10 +93,10 @@ ExtendedProfileFields.propTypes = {
9293
})),
9394
error_message: PropTypes.shape({
9495
required: PropTypes.string,
95-
invalid: PropTypes.string,
9696
}),
9797
restrictions: PropTypes.shape({
9898
max_length: PropTypes.number,
99+
min_length: PropTypes.number,
99100
}),
100101
type: PropTypes.string.isRequired,
101102
})).isRequired,

src/profile/forms/elements/FormControls.jsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import messages from './FormControls.messages';
88
import { VisibilitySelect } from './Visibility';
99

1010
const FormControls = ({
11-
cancelHandler, changeHandler, visibility, visibilityId, saveState, intl, showVisibilitySelect,
11+
cancelHandler, changeHandler, visibility, visibilityId, saveState, intl, showVisibilitySelect, disabled,
1212
}) => {
1313
// Eliminate error/failed state for save button
1414
const buttonState = saveState === 'error' ? null : saveState;
@@ -52,6 +52,7 @@ const FormControls = ({
5252
}
5353
}}
5454
disabledStates={[]}
55+
disabled={disabled}
5556
/>
5657
<Button variant="link" onClick={cancelHandler}>
5758
{intl.formatMessage(messages['profile.formcontrols.button.cancel'])}
@@ -70,6 +71,7 @@ FormControls.propTypes = {
7071
cancelHandler: PropTypes.func.isRequired,
7172
changeHandler: PropTypes.func.isRequired,
7273
showVisibilitySelect: PropTypes.bool,
74+
disabled: PropTypes.bool,
7375

7476
// i18n
7577
intl: intlShape.isRequired,
@@ -79,4 +81,5 @@ FormControls.defaultProps = {
7981
visibility: 'private',
8082
saveState: null,
8183
showVisibilitySelect: true,
84+
disabled: false,
8285
};

src/profile/forms/elements/TextField.jsx

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React from 'react';
1+
import React, { useEffect, useState } from 'react';
22
import PropTypes from 'prop-types';
33

44
// Components
@@ -16,15 +16,37 @@ const TextField = ({
1616
visibility,
1717
editMode,
1818
saveState,
19-
error,
2019
label,
2120
placeholder,
2221
instructions,
22+
restrictions,
23+
errorMessage,
2324
changeHandler,
2425
submitHandler,
2526
closeHandler,
2627
openHandler,
2728
}) => {
29+
const [displayedMessage, setErrorMessage] = useState('');
30+
31+
useEffect(() => {
32+
if (!value && errorMessage?.required) {
33+
setErrorMessage(errorMessage.required);
34+
} else if (restrictions.max_length && value.length > restrictions.max_length) {
35+
setErrorMessage(errorMessage.max_length);
36+
} else if (restrictions.min_length && value.length < restrictions.min_length) {
37+
setErrorMessage(errorMessage.min_length);
38+
} else {
39+
setErrorMessage(null);
40+
}
41+
}, [
42+
errorMessage.max_length,
43+
errorMessage.min_length,
44+
errorMessage.required,
45+
restrictions.max_length,
46+
restrictions.min_length,
47+
value,
48+
]);
49+
2850
const handleChange = (e) => {
2951
const { name, value: newValue } = e.target;
3052
changeHandler(name, newValue);
@@ -52,7 +74,7 @@ const TextField = ({
5274
<form data-testid="test-form" onSubmit={handleSubmit}>
5375
<Form.Group
5476
controlId={formId}
55-
isInvalid={error !== null}
77+
isInvalid={displayedMessage !== null}
5678
>
5779
<label className="edit-section-header" htmlFor={formId}>
5880
{label}
@@ -63,10 +85,12 @@ const TextField = ({
6385
name={formId}
6486
value={value}
6587
onChange={handleChange}
88+
minLength={restrictions.min_length}
89+
maxLength={restrictions.max_length}
6690
/>
67-
{error !== null && (
91+
{displayedMessage !== null && (
6892
<Form.Control.Feedback hasIcon={false}>
69-
{error}
93+
{displayedMessage}
7094
</Form.Control.Feedback>
7195
)}
7296
</Form.Group>
@@ -77,6 +101,7 @@ const TextField = ({
77101
saveState={saveState}
78102
cancelHandler={handleClose}
79103
changeHandler={handleChange}
104+
disabled={displayedMessage !== null}
80105
/>
81106
</form>
82107
</div>
@@ -121,7 +146,15 @@ TextField.propTypes = {
121146
visibility: PropTypes.oneOf(['private', 'all_users']),
122147
editMode: PropTypes.oneOf(['editing', 'editable', 'empty', 'static']),
123148
saveState: PropTypes.string,
124-
error: PropTypes.string,
149+
errorMessage: PropTypes.shape({
150+
required: PropTypes.string,
151+
max_length: PropTypes.string,
152+
min_length: PropTypes.string,
153+
}),
154+
restrictions: PropTypes.shape({
155+
max_length: PropTypes.number,
156+
min_length: PropTypes.number,
157+
}),
125158
placeholder: PropTypes.string,
126159
instructions: PropTypes.string,
127160
label: PropTypes.string.isRequired,
@@ -138,7 +171,6 @@ TextField.defaultProps = {
138171
placeholder: '',
139172
instructions: '',
140173
visibility: 'private',
141-
error: null,
142174
};
143175

144176
export default connect(editableFormSelector, {})(TextField);

0 commit comments

Comments
 (0)