11import React , { useEffect } from 'react' ;
22import PropTypes from 'prop-types' ;
3+ import { getAuthenticatedHttpClient } from '@edx/frontend-platform/auth' ;
34import ExtendedProfileFieldsContext from './ExtendedProfileContext' ;
45import { getExtendedProfileFieldsV2 } from './data/service' ;
56
@@ -10,10 +11,12 @@ import { FORM_MODE } from './constants';
1011const ExtendedProfileFieldsProvider = ( {
1112 patchProfile, profileFieldErrors, components, children,
1213} ) => {
14+ const editingInputRef = React . useRef ( null ) ;
1315 const [ extendedProfileFields , setExtendedProfileFields ] = React . useState ( ) ;
1416 const [ editMode , setEditMode ] = React . useState ( FORM_MODE . EDITABLE ) ;
1517 const [ editingInput , setEditingInput ] = React . useState ( null ) ;
1618 const [ saveState , setSaveState ] = React . useState ( 'default' ) ;
19+ const [ localErrors , setLocalErrors ] = React . useState ( { } ) ;
1720
1821 React . useEffect ( ( ) => {
1922 ( async ( ) => {
@@ -23,20 +26,25 @@ const ExtendedProfileFieldsProvider = ({
2326 } , [ ] ) ;
2427
2528 useEffect ( ( ) => {
26- if ( Object . keys ( profileFieldErrors ) . length ) {
29+ const filteredKeys = Object . keys ( profileFieldErrors )
30+ . filter ( key => key !== 'extended_profile' ) ;
31+
32+ if ( filteredKeys . length > 0 || Object . keys ( localErrors ) . length ) {
2733 setSaveState ( 'error' ) ;
2834 setEditMode ( FORM_MODE . EDITING ) ;
29- setEditingInput ( Object . keys ( profileFieldErrors ) [ 0 ] ) ;
35+ setEditingInput ( filteredKeys ?. [ 0 ] ?? localErrors ? editingInputRef . current : null ) ;
3036 } else {
3137 setSaveState ( 'default' ) ;
3238 setEditMode ( FORM_MODE . EDITABLE ) ;
3339 }
3440 // eslint-disable-next-line react-hooks/exhaustive-deps
35- } , [ Object . keys ( profileFieldErrors ) . length ] ) ;
41+ } , [ Object . keys ( profileFieldErrors ) . length , Object . keys ( localErrors ) . length ] ) ;
3642
3743 const handleChangeFormMode = ( mode , fieldName = null ) => {
3844 setEditMode ( mode ) ;
3945 setEditingInput ( fieldName ) ;
46+ setSaveState ( 'default' ) ;
47+ editingInputRef . current = fieldName ;
4048 } ;
4149
4250 const handleSaveExtendedProfile = async ( { username, params } ) => {
@@ -54,13 +62,58 @@ const ExtendedProfileFieldsProvider = ({
5462 setSaveState ( state ) ;
5563 } ;
5664
65+ useEffect ( ( ) => {
66+ const httpClient = getAuthenticatedHttpClient ?. ( ) ;
67+
68+ const interceptor = httpClient . interceptors . response . use (
69+ res => {
70+ if ( res . config . url . includes ( 'user/v1/accounts/' ) ) {
71+ setLocalErrors ( ( prevState ) => {
72+ const fieldName = editingInputRef . current ;
73+
74+ if ( ! fieldName ) { return prevState ; }
75+
76+ const { [ fieldName ] : _ , ...rest } = prevState ;
77+ return rest ;
78+ } ) ;
79+ editingInputRef . current = null ;
80+ handleResetFormEdition ( ) ;
81+ }
82+ return res ;
83+ } ,
84+ error => {
85+ if (
86+ error . response ?. status === 400
87+ && error . response . config . url . includes ( 'user/v1/accounts/' )
88+ ) {
89+ const fieldErrors = error . response . data ?. field_errors ;
90+
91+ if ( fieldErrors ) {
92+ setLocalErrors ( { [ editingInputRef . current ] : fieldErrors . extended_profile . user_message } ) ;
93+ }
94+ }
95+
96+ return Promise . reject ( error ) ;
97+ } ,
98+ ) ;
99+
100+ return ( ) => {
101+ httpClient . interceptors . response . eject ( interceptor ) ;
102+ } ;
103+ } , [ ] ) ;
104+
105+ const mergedErrors = {
106+ ...profileFieldErrors ,
107+ ...localErrors ,
108+ } ;
109+
57110 const value = React . useMemo (
58111 ( ) => ( {
59112 editMode,
60113 extendedProfileFields,
61114 editingInput,
62115 saveState,
63- profileFieldErrors,
116+ profileFieldErrors : mergedErrors ,
64117 handleChangeFormMode,
65118 handleResetFormEdition,
66119 handleSaveExtendedProfile,
0 commit comments