11import * as yup from 'yup'
2- import { FC , useEffect , useMemo } from 'react'
2+ import { FC , useCallback , useEffect , useMemo , useRef } from 'react'
33import { useFormContext } from 'react-hook-form'
44import classNames from 'classnames'
55
@@ -70,8 +70,30 @@ const toChallengeTrackLabel = (value: string): string => (
7070)
7171
7272const legacyChallengeTrackMap : Record < string , string > = {
73- DEVELOPMENT : 'DEVELOP' ,
74- QUALITY_ASSURANCE : 'QA' ,
73+ DEVELOPMENT : 'DEVELOPMENT' ,
74+ DEVELOP : 'DEVELOPMENT' ,
75+ QUALITY_ASSURANCE : 'QUALITY_ASSURANCE' ,
76+ QA : 'QUALITY_ASSURANCE' ,
77+ }
78+
79+ const normalizeTrackOptionValue = ( track : useFetchChallengeTracksProps [ 'challengeTracks' ] [ number ] ) : string => {
80+ if ( track . track ) {
81+ return track . track
82+ }
83+
84+ const normalizedName = track . name
85+ ?. replace ( / \s + / g, '_' )
86+ . toUpperCase ( )
87+
88+ if ( normalizedName && legacyChallengeTrackMap [ normalizedName ] ) {
89+ return legacyChallengeTrackMap [ normalizedName ]
90+ }
91+
92+ if ( track . name ) {
93+ return normalizedName || track . name
94+ }
95+
96+ return track . id
7597}
7698
7799const normalizeChallengeTrackValue = (
@@ -82,21 +104,23 @@ const normalizeChallengeTrackValue = (
82104
83105 const directMatch = tracks . find ( track => track . track === value && track . isActive )
84106 if ( directMatch ) {
85- return directMatch . track
107+ return normalizeTrackOptionValue ( directMatch )
86108 }
87109
88110 const mappedValue = legacyChallengeTrackMap [ value ]
89111 if ( mappedValue ) {
90- const mappedMatch = tracks . find ( track => track . track === mappedValue && track . isActive )
112+ const mappedMatch = tracks . find ( track => (
113+ normalizeTrackOptionValue ( track ) === mappedValue && track . isActive
114+ ) )
91115 if ( mappedMatch ) {
92- return mappedMatch . track
116+ return normalizeTrackOptionValue ( mappedMatch )
93117 }
94118 }
95119
96120 const normalizedLabel = toChallengeTrackLabel ( value )
97121 const nameMatch = tracks . find ( track => track . name === normalizedLabel && track . isActive )
98122 if ( nameMatch ) {
99- return nameMatch . track
123+ return normalizeTrackOptionValue ( nameMatch )
100124 }
101125
102126 const uppercaseValue = value
@@ -109,23 +133,41 @@ const normalizeChallengeTrackValue = (
109133 && track . isActive
110134 ) )
111135
112- return fallbackMatch ?. track
136+ return fallbackMatch ? normalizeTrackOptionValue ( fallbackMatch ) : undefined
113137}
114138
115139const ScorecardInfoForm : FC = ( ) => {
116140 const form = useFormContext ( )
117141 const { challengeTracks } : useFetchChallengeTracksProps = useFetchChallengeTracks ( )
118142 const { challengeTypes } : useFetchChallengeTypesProps = useFetchChallengeTypes ( )
143+ const { getValues, setValue } = form
144+ const normalizeValue = useCallback ( (
145+ value : string | number | boolean | null | undefined ,
146+ ) : string | undefined => {
147+ if ( value === null || value === undefined ) {
148+ return undefined
149+ }
150+
151+ const normalized = String ( value ) . trim ( )
152+
153+ return normalized . length ? normalized : undefined
154+ } , [ ] )
119155
120156 const challengeTrackOptions = useMemo ( ( ) => (
121157 challengeTracks
122158 . filter ( track => track . isActive )
123159 . map ( track => ( {
124160 label : track . name ,
125- value : track . track ,
161+ value : normalizeTrackOptionValue ( track ) ,
126162 } ) )
127163 ) , [ challengeTracks ] )
128164
165+ const fallbackChallengeTrack = useMemo (
166+ ( ) => challengeTrackOptions . find ( option => option . value ) ?. value ,
167+ [ challengeTrackOptions ] ,
168+ )
169+ const shouldNormalizeTrack = useRef ( true )
170+
129171 const challengeTypeOptions = useMemo ( ( ) => (
130172 challengeTypes
131173 . filter ( type => type . isActive )
@@ -135,49 +177,97 @@ const ScorecardInfoForm: FC = () => {
135177 } ) )
136178 ) , [ challengeTypes ] )
137179
180+ const fallbackChallengeType = useMemo (
181+ ( ) => challengeTypeOptions . find ( option => option . value ) ?. value ,
182+ [ challengeTypeOptions ] ,
183+ )
184+ const shouldNormalizeType = useRef ( true )
185+
138186 useEffect ( ( ) => {
187+ if ( ! shouldNormalizeTrack . current ) {
188+ return
189+ }
190+
139191 if ( ! challengeTrackOptions . length ) {
140192 return
141193 }
142194
143- const currentValue : string = form . getValues ( 'challengeTrack' ) as string
195+ const currentValue = normalizeValue ( getValues ( 'challengeTrack' ) as string )
144196 const isCurrentValid : boolean = ! ! currentValue
145- && challengeTrackOptions . some ( option => option . value === currentValue )
197+ && challengeTrackOptions . some ( option => (
198+ normalizeValue ( option . value ) === currentValue
199+ ) )
146200
147201 if ( currentValue && ! isCurrentValid ) {
148- const normalizedValue = normalizeChallengeTrackValue ( currentValue , challengeTracks )
149- if ( normalizedValue ) {
150- form . setValue ( 'challengeTrack' , normalizedValue , {
202+ const normalizedValue = normalizeValue (
203+ normalizeChallengeTrackValue ( currentValue , challengeTracks ) ,
204+ )
205+
206+ if ( normalizedValue && normalizedValue !== currentValue ) {
207+ setValue ( 'challengeTrack' , normalizedValue , {
151208 shouldDirty : false ,
152209 shouldValidate : true ,
153210 } )
154- return
155211 }
212+
213+ return
156214 }
157215
158- if ( ! isCurrentValid ) {
159- form . setValue ( 'challengeTrack' , challengeTrackOptions [ 0 ] . value , {
160- shouldDirty : false ,
161- shouldValidate : true ,
162- } )
216+ if ( ! isCurrentValid && fallbackChallengeTrack ) {
217+ const normalizedFallback = normalizeValue ( fallbackChallengeTrack )
218+
219+ if ( normalizedFallback && normalizedFallback !== currentValue ) {
220+ setValue ( 'challengeTrack' , normalizedFallback , {
221+ shouldDirty : false ,
222+ shouldValidate : true ,
223+ } )
224+ }
163225 }
164- } , [ challengeTrackOptions , challengeTracks , form ] )
226+
227+ shouldNormalizeTrack . current = false
228+ } , [
229+ challengeTrackOptions ,
230+ challengeTracks ,
231+ fallbackChallengeTrack ,
232+ getValues ,
233+ normalizeValue ,
234+ setValue ,
235+ ] )
165236
166237 useEffect ( ( ) => {
238+ if ( ! shouldNormalizeType . current ) {
239+ return
240+ }
241+
167242 if ( ! challengeTypeOptions . length ) {
168243 return
169244 }
170245
171- const currentChallengeType : string = form . getValues ( 'challengeType' ) as string
246+ const currentChallengeType = normalizeValue ( getValues ( 'challengeType' ) as string )
172247 const partOfCategories : { label : string ; value : string } | undefined
173- = challengeTypeOptions . find ( item => item . value === currentChallengeType )
174- if ( ( ! partOfCategories || ! currentChallengeType ) && challengeTypeOptions . length > 0 ) {
175- form . setValue ( 'challengeType' , challengeTypeOptions [ 0 ] . value , {
176- shouldDirty : false ,
177- shouldValidate : true ,
178- } )
248+ = challengeTypeOptions . find ( item => (
249+ normalizeValue ( item . value ) === currentChallengeType
250+ ) )
251+
252+ if ( ( ! partOfCategories || ! currentChallengeType ) && fallbackChallengeType ) {
253+ const normalizedFallback = normalizeValue ( fallbackChallengeType )
254+
255+ if ( normalizedFallback && normalizedFallback !== currentChallengeType ) {
256+ setValue ( 'challengeType' , normalizedFallback , {
257+ shouldDirty : false ,
258+ shouldValidate : true ,
259+ } )
260+ }
179261 }
180- } , [ challengeTypeOptions , form ] )
262+
263+ shouldNormalizeType . current = false
264+ } , [
265+ challengeTypeOptions ,
266+ fallbackChallengeType ,
267+ getValues ,
268+ normalizeValue ,
269+ setValue ,
270+ ] )
181271
182272 return (
183273 < div className = { classNames ( styles . grayWrapper , styles . scorecardInfo ) } >
0 commit comments