Skip to content

Commit 265de5b

Browse files
authored
fix(experience): the sub-component optional config should be respected (#7677)
* fix(experience): the sub-component optional config should be respected * refactor(experience): improve composition profile field error handling
1 parent 4076be5 commit 265de5b

File tree

4 files changed

+58
-8
lines changed

4 files changed

+58
-8
lines changed

packages/experience/src/pages/Continue/ExtraProfileForm/AddressSubForm/index.module.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,13 @@
2525

2626
.errorMessage {
2727
color: var(--color-danger-default);
28+
display: flex;
29+
flex-direction: column;
30+
gap: _.unit(1);
31+
32+
> p {
33+
margin: 0;
34+
}
2835
}
2936

3037
@media only screen and (max-width: 580px) {

packages/experience/src/pages/Continue/ExtraProfileForm/AddressSubForm/index.tsx

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as s from 'superstruct';
88
import PrimitiveProfileInputField from '@/components/InputFields/PrimitiveProfileInputField';
99
import { addressFieldConfigGuard } from '@/types/guard';
1010

11+
import useFieldLabel from '../use-field-label';
1112
import useValidateField from '../use-validate-field';
1213

1314
import styles from './index.module.scss';
@@ -38,6 +39,7 @@ type Props = {
3839
const AddressSubForm = ({ field }: Props) => {
3940
const { t } = useTranslation();
4041
const validateField = useValidateField();
42+
const getFieldLabel = useFieldLabel();
4143

4244
const {
4345
control,
@@ -47,7 +49,7 @@ const AddressSubForm = ({ field }: Props) => {
4749
formState: { errors },
4850
} = useFormContext<AddressSubFormType>();
4951

50-
const { description, config, required } = field;
52+
const { description, config } = field;
5153

5254
const enabledParts = useMemo(() => {
5355
s.assert(config, addressFieldConfigGuard);
@@ -68,14 +70,24 @@ const AddressSubForm = ({ field }: Props) => {
6870
return null;
6971
}
7072

73+
const hasNonRequiredErrors = Object.entries(errors.address ?? {}).some(
74+
([_, error]) => typeof error === 'object' && error.type !== 'required'
75+
);
7176
return (
7277
<div className={styles.addressContainer}>
7378
{enabledParts.map((part) => (
7479
<Controller
7580
key={part.name}
7681
name={`address.${part.name}`}
7782
control={control}
78-
rules={{ required, validate: (value) => validateField(value, part) }}
83+
rules={{
84+
required:
85+
part.required &&
86+
t('error.general_required', {
87+
types: [getFieldLabel(`address.${part.name}`, part.label)],
88+
}),
89+
validate: (value) => validateField(value, part),
90+
}}
7991
render={({ field: { onBlur, onChange, value } }) => (
8092
<PrimitiveProfileInputField
8193
{...part}
@@ -104,7 +116,17 @@ const AddressSubForm = ({ field }: Props) => {
104116
{description && <div className={styles.description}>{description}</div>}
105117
{errors.address && (
106118
<div className={styles.errorMessage}>
107-
{t('error.general_required', { types: [t('profile.address.formatted')] })}
119+
{hasNonRequiredErrors ? (
120+
<>
121+
{Object.entries(errors.address).map(([errorKey, error]) => (
122+
<p key={errorKey}>
123+
{typeof error === 'object' && 'message' in error ? error.message : String(error)}
124+
</p>
125+
))}
126+
</>
127+
) : (
128+
<p>{t('error.general_required', { types: [t('profile.address.formatted')] })}</p>
129+
)}
108130
</div>
109131
)}
110132
</div>

packages/experience/src/pages/Continue/ExtraProfileForm/FullnameSubForm/index.module.scss

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@
3333
font: var(--font-body-2);
3434
color: var(--color-danger-default);
3535
margin-inline-start: _.unit(0.5);
36+
display: flex;
37+
flex-direction: column;
38+
gap: _.unit(1);
39+
40+
> p {
41+
margin: 0;
42+
}
3643
}
3744

3845
@media only screen and (max-width: 580px) {

packages/experience/src/pages/Continue/ExtraProfileForm/FullnameSubForm/index.tsx

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ const FullnameSubForm = ({ field }: Props) => {
2424
const getFieldLabel = useFieldLabel();
2525
const validateField = useValidateField();
2626

27-
const { required, name, label, description, config } = field;
27+
const { name, label, description, config } = field;
2828
s.assert(config, fullnameFieldConfigGuard);
2929

3030
const {
@@ -33,9 +33,10 @@ const FullnameSubForm = ({ field }: Props) => {
3333
} = useFormContext<FullnameFormType>();
3434

3535
const enabledParts = useMemo(() => config.parts.filter(({ enabled }) => enabled), [config.parts]);
36-
const hasFullnameError = Object.entries(errors).some(([errorKey]) =>
36+
const fullnameErrors = Object.entries(errors).filter(([errorKey]) =>
3737
enabledParts.some(({ name }) => name === errorKey)
3838
);
39+
const hasNonRequiredErrors = fullnameErrors.some(([_, error]) => error.type !== 'required');
3940

4041
return (
4142
<div className={styles.fullnameContainer}>
@@ -47,7 +48,12 @@ const FullnameSubForm = ({ field }: Props) => {
4748
key={part.name}
4849
name={part.name}
4950
control={control}
50-
rules={{ required, validate: (value) => validateField(value, part) }}
51+
rules={{
52+
required:
53+
part.required &&
54+
t('error.general_required', { types: [getFieldLabel(part.name, part.label)] }),
55+
validate: (value) => validateField(value, part),
56+
}}
5157
render={({ field: { onBlur, onChange, value } }) => (
5258
<PrimitiveProfileInputField
5359
{...part}
@@ -64,9 +70,17 @@ const FullnameSubForm = ({ field }: Props) => {
6470
))}
6571
</div>
6672
{description && <div className={styles.description}>{description}</div>}
67-
{hasFullnameError && (
73+
{fullnameErrors.length > 0 && (
6874
<div className={styles.errorMessage}>
69-
{t('error.general_required', { types: [getFieldLabel(name, label)] })}
75+
{hasNonRequiredErrors ? (
76+
<>
77+
{fullnameErrors.map(([errorKey, error]) => (
78+
<p key={errorKey}>{error.message}</p>
79+
))}
80+
</>
81+
) : (
82+
<p>{t('error.general_required', { types: [getFieldLabel(name, label)] })}</p>
83+
)}
7084
</div>
7185
)}
7286
</div>

0 commit comments

Comments
 (0)