Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[C-5492] Guest sign-up copy and improvements #10682

Merged
merged 7 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions packages/common/src/messages/sign-on/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ export const confirmEmailMessages = {
otpPlaceholder: '123 456',
noEmailNotice: "Didn't get an email?",
resendCode: 'Resend Code',
resentToast: 'Verification code resent.'
resentToast: 'Verification code resent.',
finishSigningUp: 'Finish Signing Up'
}

export const createEmailPageMessages = {
Expand All @@ -30,7 +31,8 @@ export const createEmailPageMessages = {
unknownError: 'Unknown error occurred.',
metaMaskNotRecommended: 'Signing up with MetaMask is not recommended.',
signUpMetamask: 'Sign Up With MetaMask',
learnMore: 'Learn More'
learnMore: 'Learn More',
finishSigningUp: 'Finish Signing Up'
}

export type CompletionChecklistType =
Expand Down
8 changes: 3 additions & 5 deletions packages/common/src/schemas/sign-on/emailSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@ export const emailSchemaMessages = {
invalidEmail: 'Please enter a valid email.',
emailInUse: 'Email already taken.',
somethingWentWrong: 'Something went wrong. Try again later.',
completeYourProfile: 'Complete your profile.'
guestAccountExists: 'Guest account exists.'
}

export const emailSchema = <T extends AudiusQueryContextType>(
queryContext: T
) =>
export const emailSchema = (queryContext: AudiusQueryContextType) =>
z.object({
email: z
.string({ required_error: emailSchemaMessages.emailRequired })
Expand All @@ -31,7 +29,7 @@ export const emailSchema = <T extends AudiusQueryContextType>(
// complete guest accounts only
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: emailSchemaMessages.completeYourProfile
message: emailSchemaMessages.guestAccountExists
})
return true
} else if (isEmailInUse) {
Expand Down
37 changes: 28 additions & 9 deletions packages/common/src/schemas/sign-on/signInSchema.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,40 @@
import { z } from 'zod'

import { signUpFetch } from '~/api'
import { AudiusQueryContextType } from '~/audius-query'

export const messages = {
emailRequired: 'Please enter an email.',
email: 'Please enter a valid email.',
passwordRequired: 'Please enter a password.',
invalidCredentials: 'Invalid credentials.'
invalidCredentials: 'Invalid credentials.',
guestAccountExists: 'Guest account exists.'
}

export const signInSchema = z.object({
email: z
.string({
required_error: messages.emailRequired
export const signInSchema = (queryContext: AudiusQueryContextType) =>
z.object({
email: z
.string({
required_error: messages.emailRequired
})
.email(messages.email)
.superRefine(async (email, ctx) => {
const { isGuest } = await signUpFetch.isEmailInUse(
{ email },
queryContext
)
if (isGuest) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
message: messages.guestAccountExists
})
return true
}
return z.NEVER // The return value is not used, but we need to return something to satisfy the typing
}),
password: z.string({
required_error: messages.passwordRequired
})
.email(messages.email),
password: z.string({
required_error: messages.passwordRequired
})
})

export { messages as signInErrorMessages }
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export const NewEmailField = (props: NewEmailFieldProps) => {
const [{ value: email }, { error }] = useField(name)
const { isValidating } = useFormikContext()
const emailInUse = error === emailSchemaMessages.emailInUse
const isGuest = error === emailSchemaMessages.completeYourProfile
const isGuest = error === emailSchemaMessages.guestAccountExists
const hasError = emailInUse || isGuest

// Track which specific error was shown last
Expand All @@ -55,7 +55,7 @@ export const NewEmailField = (props: NewEmailFieldProps) => {

const showGuestError =
isGuest ||
(isValidating && lastShownError === emailSchemaMessages.completeYourProfile)
(isValidating && lastShownError === emailSchemaMessages.guestAccountExists)

const showEmailInUseError =
emailInUse ||
Expand All @@ -70,7 +70,7 @@ export const NewEmailField = (props: NewEmailFieldProps) => {
/>
{showGuestError ? (
<Hint icon={IconError}>
{emailSchemaMessages.completeYourProfile}{' '}
{emailSchemaMessages.guestAccountExists}{' '}
<TextLink variant='visible' onPress={handlePressConfirmEmail}>
{confirmEmailMessages.title}
</TextLink>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback, useEffect, useState } from 'react'

import { confirmEmailMessages } from '@audius/common/messages'
import { confirmEmailMessages as messages } from '@audius/common/messages'
import {
confirmEmailSchema,
formatOtp,
Expand All @@ -10,7 +10,8 @@ import { setValueField, signIn } from 'common/store/pages/signon/actions'
import {
getEmailField,
getOtpField,
getPasswordField
getPasswordField,
getIsGuest
} from 'common/store/pages/signon/selectors'
import { Formik, useField } from 'formik'
import { useDispatch, useSelector } from 'react-redux'
Expand Down Expand Up @@ -39,6 +40,7 @@ export const ConfirmEmailScreen = () => {
const { value: email } = useSelector(getEmailField)
const { value: password } = useSelector(getPasswordField)
const { value: otp } = useSelector(getOtpField)
const isGuest = useSelector(getIsGuest)
const isSubmitting = !!otp

useTrackScreen('ConfirmEmail')
Expand All @@ -62,12 +64,12 @@ export const ConfirmEmailScreen = () => {
>
<Page>
<Heading
heading={confirmEmailMessages.title}
description={confirmEmailMessages.description}
heading={isGuest ? messages.finishSigningUp : messages.title}
description={messages.description}
/>
<VerificationCodeField />
<Text variant='body'>
{confirmEmailMessages.noEmailNotice} <ResendCodeLink />
{messages.noEmailNotice} <ResendCodeLink />
</Text>
<PageFooter
shadow='flat'
Expand Down Expand Up @@ -97,8 +99,8 @@ const VerificationCodeField = () => {
<HarmonyTextField
name='otp'
keyboardType='number-pad'
label={confirmEmailMessages.otpLabel}
placeholder={confirmEmailMessages.otpPlaceholder}
label={messages.otpLabel}
placeholder={messages.otpPlaceholder}
transformValueOnChange={formatOtp}
/>
)
Expand All @@ -113,7 +115,7 @@ const ResendCodeLink = () => {

const handleClick = useCallback(() => {
dispatch(signIn(email, password))
toast({ content: confirmEmailMessages.resentToast })
toast({ content: messages.resentToast })
setHasResendCode(true)
}, [dispatch, email, password, toast])

Expand All @@ -123,7 +125,7 @@ const ResendCodeLink = () => {
onPress={handleClick}
disabled={hasResentCode}
>
{confirmEmailMessages.resendCode}
{messages.resendCode}
</TextLink>
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback } from 'react'

import { createPasswordPageMessages } from '@audius/common/messages'
import { createPasswordPageMessages as messages } from '@audius/common/messages'
import { passwordSchema } from '@audius/common/schemas'
import { setValueField } from 'common/store/pages/signon/actions'
import { getEmailField } from 'common/store/pages/signon/selectors'
Expand Down Expand Up @@ -58,22 +58,20 @@ export const CreatePasswordScreen = () => {
<KeyboardAvoidingView keyboardShowingOffset={220}>
<Flex direction='column' h='100%' gap='l'>
<Heading
heading={createPasswordPageMessages.createYourPassword}
description={createPasswordPageMessages.description}
/>
<ReadOnlyField
label={createPasswordPageMessages.yourEmail}
value={email}
heading={messages.createYourPassword}
description={messages.description}
/>

<ReadOnlyField label={messages.yourEmail} value={email} />
<PasswordField
name='password'
clearErrorOnChange={false}
label={createPasswordPageMessages.passwordLabel}
label={messages.passwordLabel}
/>
<PasswordField
name='confirmPassword'
clearErrorOnChange={false}
label={createPasswordPageMessages.confirmPasswordLabel}
label={messages.confirmPasswordLabel}
/>
<PasswordCompletionChecklist />
<SignUpAgreementText />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useCallback, useEffect } from 'react'
import { useCallback, useEffect, useMemo } from 'react'

import { useAudiusQueryContext } from '@audius/common/audius-query'
import { signInPageMessages } from '@audius/common/messages'
import { signInSchema, signInErrorMessages } from '@audius/common/schemas'
import {
Expand All @@ -24,8 +25,6 @@ import { Heading } from '../components/layout'
import type { SignUpScreenParamList } from '../types'
import { useTrackScreen } from '../utils/useTrackScreen'

const SignInSchema = toFormikValidationSchema(signInSchema)

type SignInValues = {
email: string
password: string
Expand All @@ -41,6 +40,12 @@ export const SignInScreen = () => {
const navigation = useNavigation<SignUpScreenParamList>()
useTrackScreen('SignIn')

const audiusQueryContext = useAudiusQueryContext()
const SignInSchema = useMemo(
() => toFormikValidationSchema(signInSchema(audiusQueryContext)),
[audiusQueryContext]
)

useEffect(() => {
if (requiresOtp) {
navigation.navigate('ConfirmEmail')
Expand Down
3 changes: 2 additions & 1 deletion packages/web/src/common/store/pages/signon/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1079,8 +1079,9 @@ function* signIn(action: ReturnType<typeof signOnActions.signIn>) {
}
})
)

yield* put(toastActions.toast({ content: messages.incompleteAccount }))
}
yield* put(toastActions.toast({ content: messages.incompleteAccount }))

yield* put(
make(Name.SIGN_IN_WITH_INCOMPLETE_ACCOUNT, {
Expand Down
20 changes: 11 additions & 9 deletions packages/web/src/pages/sign-in-page/ConfirmEmailPage.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback, useContext, useEffect, useState } from 'react'

import { confirmEmailMessages } from '@audius/common/messages'
import { confirmEmailMessages as messages } from '@audius/common/messages'
import {
confirmEmailSchema,
formatOtp,
Expand All @@ -19,7 +19,8 @@ import {
import {
getEmailField,
getOtpField,
getPasswordField
getPasswordField,
getIsGuest
} from 'common/store/pages/signon/selectors'
import { HarmonyTextField } from 'components/form-fields/HarmonyTextField'
import { ToastContext } from 'components/toast/ToastContext'
Expand All @@ -43,6 +44,7 @@ export const ConfirmEmailPage = () => {
const { value: email } = useSelector(getEmailField)
const { value: password } = useSelector(getPasswordField)
const { value: otp } = useSelector(getOtpField)
const isGuest = useSelector(getIsGuest)
const isSubmitting = !!otp

const handleSubmit = useCallback(
Expand All @@ -65,12 +67,12 @@ export const ConfirmEmailPage = () => {
>
<Page as={Form} transition={isMobile ? undefined : 'horizontal'}>
<Heading
heading={confirmEmailMessages.title}
description={confirmEmailMessages.description}
heading={isGuest ? messages.finishSigningUp : messages.title}
description={messages.description}
/>
<VerificationCodeField />
<Text variant='body'>
{confirmEmailMessages.noEmailNotice} <ResendCodeLink />
{messages.noEmailNotice} <ResendCodeLink />
</Text>
<PageFooter shadow='flat' buttonProps={{ isLoading: isSubmitting }} />
</Page>
Expand All @@ -95,8 +97,8 @@ const VerificationCodeField = () => {
return (
<HarmonyTextField
name='otp'
label={confirmEmailMessages.otpLabel}
placeholder={confirmEmailMessages.otpPlaceholder}
label={messages.otpLabel}
placeholder={messages.otpPlaceholder}
transformValueOnChange={formatOtp}
/>
)
Expand All @@ -111,7 +113,7 @@ const ResendCodeLink = () => {

const handleClick = useCallback(() => {
dispatch(signIn(email, password))
toast(confirmEmailMessages.resentToast)
toast(messages.resentToast)
setHasResendCode(true)
}, [dispatch, email, password, toast])

Expand All @@ -121,7 +123,7 @@ const ResendCodeLink = () => {
onClick={handleClick}
disabled={hasResentCode}
>
{confirmEmailMessages.resendCode}
{messages.resendCode}
</TextLink>
)
}
13 changes: 10 additions & 3 deletions packages/web/src/pages/sign-in-page/SignInPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { useCallback, useEffect, useState } from 'react'
import { useCallback, useEffect, useMemo, useState } from 'react'

import { useAudiusQueryContext } from '@audius/common/audius-query'
import { signInPageMessages } from '@audius/common/messages'
import { signInSchema, signInErrorMessages } from '@audius/common/schemas'
import { route } from '@audius/common/utils'
Expand Down Expand Up @@ -29,6 +30,7 @@ import { HarmonyPasswordField } from 'components/form-fields/HarmonyPasswordFiel
import PreloadImage from 'components/preload-image/PreloadImage'
import { useMedia } from 'hooks/useMedia'
import { useNavigateToPage } from 'hooks/useNavigateToPage'
import { GuestEmailHint } from 'pages/sign-on-page/GuestEmailHint'
import { EmailField } from 'pages/sign-up-page/components/EmailField'
import { ForgotPasswordModal } from 'pages/sign-up-page/components/ForgotPasswordModal'
import { Heading, ScrollView } from 'pages/sign-up-page/components/layout'
Expand All @@ -38,8 +40,6 @@ import { SignInWithMetaMaskButton } from './SignInWithMetaMaskButton'

const { SIGN_IN_CONFIRM_EMAIL_PAGE, SIGN_UP_PAGE } = route

const SignInSchema = toFormikValidationSchema(signInSchema)

const smallDesktopWindowHeight = 900

type SignInValues = {
Expand All @@ -58,6 +58,12 @@ export const SignInPage = () => {
const { value: existingPassword } = useSelector(getPasswordField)
const requiresOtp = useSelector(getRequiresOtp)

const audiusQueryContext = useAudiusQueryContext()
const SignInSchema = useMemo(
() => toFormikValidationSchema(signInSchema(audiusQueryContext)),
[audiusQueryContext]
)

useEffect(() => {
if (requiresOtp) {
navigate(SIGN_IN_CONFIRM_EMAIL_PAGE)
Expand Down Expand Up @@ -124,6 +130,7 @@ export const SignInPage = () => {
<Flex direction='column' gap='l'>
<EmailField />
<SignInPasswordField />
<GuestEmailHint />
</Flex>
<Flex direction='column' gap='l' w='100%'>
<Button
Expand Down
Loading