Skip to content

Commit

Permalink
[C-3610] Positive validation for sign up handles on web (#7148)
Browse files Browse the repository at this point in the history
  • Loading branch information
DejayJD authored Jan 11, 2024
1 parent c8bb29a commit 94b75dd
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 5 deletions.
1 change: 1 addition & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions packages/common/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
"async-retry": "1.3.3",
"bn.js": "5.1.0",
"dayjs": "1.10.7",
"formik": "2.4.1",
"fxa-common-password-list": "0.0.2",
"hashids": "2.2.1",
"immer": "9.0.1",
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ export * from './useInterval'
export * from './useCreateUserbankIfNeeded'
export * from './usePurchaseMethod'
export * from './useCoinflowAdapter'
export * from './useIsWaitingForValidation'
31 changes: 31 additions & 0 deletions packages/common/src/hooks/useIsWaitingForValidation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { useEffect, useState } from 'react'

import { useFormikContext } from 'formik'
import { usePrevious } from 'react-use'

/**
* This is a Formik workaround hook. Formik's isValidating only returns true DURING the validation.
* However this doesn't work when we want to wait for the results of the validation before doing something. (i.e. positive validation)
* To handle this we wait for Formik isValidating to change to true, then wait for it to turn back to false
* before saying we're "not waiting" for validation anymore
* @returns {isWaitingOnValidation, handleChange}
*/
export const useIsWaitingForValidation = () => {
const { isValidating } = useFormikContext()
const [isWaitingForValidation, setIsWaitingForValidation] = useState(false)
const wasValidating = usePrevious(isValidating)

// We know formik has stopped validating when it differs from our previous value
useEffect(() => {
if (wasValidating && !isValidating) {
setIsWaitingForValidation(false)
}
}, [isValidating, wasValidating])

return {
isWaitingForValidation,
handleChange: () => {
setIsWaitingForValidation(true)
}
}
}
6 changes: 4 additions & 2 deletions packages/web/src/components/form-fields/HarmonyTextField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export const HarmonyTextField = forwardRef(
transformValueOnBlur,
debouncedValidationMs = 0,
helperText,
onChange: propsOnChange,
onChange: onChangeProp,
onBlur: onBlurProp,
...other
} = props
const [field, { touched, error }, { setError }] = useField(name)
Expand Down Expand Up @@ -62,6 +63,7 @@ export const HarmonyTextField = forwardRef(
if (transformValueOnChange) {
e.target.value = transformValueOnChange(e.target.value)
}
onChangeProp?.(e)
field.onChange(e)
}}
onBlur={(e) => {
Expand All @@ -72,7 +74,7 @@ export const HarmonyTextField = forwardRef(
e.target.value = transformValueOnBlur(e.target.value)
}
field.onChange(e)
propsOnChange?.(e)
onBlurProp?.(e)
field.onBlur(e)
}}
{...other}
Expand Down
22 changes: 19 additions & 3 deletions packages/web/src/pages/sign-up-page/components/HandleField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ import { Ref, forwardRef, useCallback, useContext } from 'react'
import {
MAX_HANDLE_LENGTH,
socialMediaMessages,
pickHandleErrorMessages
pickHandleErrorMessages,
useIsWaitingForValidation
} from '@audius/common'
import { TextLink } from '@audius/harmony'
import { IconCheck } from '@audius/stems'
import { useField } from 'formik'

import {
Expand All @@ -20,7 +22,8 @@ import { SignupFlowTwitterAuth } from './SignupFlowTwitterAuth'

const messages = {
handle: 'Handle',
linkToClaim: 'Link to claim.'
linkToClaim: 'Link to claim.',
handleAvailable: 'Handle available!'
}

const handleAuthMap = {
Expand All @@ -45,12 +48,16 @@ export const HandleField = forwardRef(
onCompleteSocialMediaLogin,
onErrorSocialMediaLogin,
onStartSocialMediaLogin,
onChange,
...other
} = props

const [{ value: handle }, { error }] = useField('handle')

const { toast } = useContext(ToastContext)

const { isWaitingForValidation, handleChange } = useIsWaitingForValidation()

const handleVerifyHandleError = useCallback(() => {
toast(socialMediaMessages.verificationError)
onErrorSocialMediaLogin?.()
Expand Down Expand Up @@ -79,7 +86,7 @@ export const HandleField = forwardRef(
const AuthComponent = error ? handleAuthMap[error] : undefined

const helperText =
handle && error ? (
handle && !!error ? (
<>
{error}{' '}
{onCompleteSocialMediaLogin &&
Expand All @@ -97,6 +104,8 @@ export const HandleField = forwardRef(
</TextLink>
) : null}
</>
) : !isWaitingForValidation && handle ? (
messages.handleAvailable
) : null

return (
Expand All @@ -110,6 +119,13 @@ export const HandleField = forwardRef(
placeholder={messages.handle}
transformValueOnChange={(value) => value.replace(/\s/g, '')}
debouncedValidationMs={1000}
endIcon={
!isWaitingForValidation && !error && handle ? IconCheck : undefined
}
onChange={(e) => {
onChange?.(e)
handleChange()
}}
{...other}
/>
)
Expand Down

0 comments on commit 94b75dd

Please sign in to comment.