diff --git a/components/forms/signupFormWizard.tsx b/components/forms/signupFormWizard.tsx index 9e381d772..f01ea1888 100644 --- a/components/forms/signupFormWizard.tsx +++ b/components/forms/signupFormWizard.tsx @@ -1,5 +1,5 @@ import { useRouter } from 'next/router'; -import React, { useContext, useEffect, useRef, useState } from 'react'; +import React, { useContext, useRef, useState } from 'react'; import ReCAPTCHA from 'react-google-recaptcha'; import toast from 'react-hot-toast'; import StepWizard, { StepWizardProps } from 'react-step-wizard'; @@ -28,13 +28,6 @@ export default function SignupFormWizard() { return; } - if (username.match(/[^-a-zA-Z0-9_]/)) { - toast.dismiss(); - toast.error('Username can only contain letters, numbers, underscores, and hyphens'); - - return; - } - toast.dismiss(); toast.loading('Registering...'); @@ -93,19 +86,15 @@ export default function SignupFormWizard() { const [isValidUsername, setIsValidUsername] = useState(true); const [wizard, setWizard] = useState(); - const isLoadingExistsCheck = useRef(false); - // let's check if username exists already when user types - const checkUsername = async (username: string) => { - if (username.length < 3 || username.length > 50) { - setIsValidUsername(false); - - return; - } + const [usernameExists, setUsernameExists] = useState(false); + const [isExistsLoading, setIsExistsLoading] = useState(false); + const checkUsername = async (username: string) => { const res = await fetch(`/api/user/exists?name=${username}`); + const resObj = await res.json(); - isLoadingExistsCheck.current = false; - setIsValidUsername(res.status === 404); + setIsExistsLoading(false); + setUsernameExists(!resObj.exists); }; // debounce the checkUsername function @@ -115,68 +104,72 @@ export default function SignupFormWizard() { // check if username is valid const handleUsernameChange = (e: React.ChangeEvent) => { - setUsername(e.target.value); - isLoadingExistsCheck.current = true; - debouncedCheckUsername(e.target.value); - }; + const newUserName = e.target.value; - useEffect(() => { - if (username.length < 3 || username.length > 50) { - setIsValidUsername(false); + setUsername(newUserName); - return; + let valid = true; + + if (newUserName.length < 3 || newUserName.length > 50 || newUserName.match(/[^-a-zA-Z0-9_]/)) { + valid = false; } - if (username.match(/[^-a-zA-Z0-9_]/)) { - setIsValidUsername(false); + setIsValidUsername(valid); + + if (!valid) { + setIsExistsLoading(false); return; } - }, [username]); - return ( + setIsExistsLoading(true); + debouncedCheckUsername(newUserName); + }; + return (
- +
handleUsernameChange(e)} className='shadow appearance-none border rounded w-full py-2 px-3 leading-tight focus:outline-none focus:shadow-outline' id='username' type='text' placeholder='Username' /> - - { username.length >= 3 && ( + + {username.length >= 3 &&
- {username.length > 0 && !isLoadingExistsCheck.current && ( + {isExistsLoading ? : <> - {isValidUsername ? '✅' : '❌'} + {isValidUsername && usernameExists ? '✅' : '❌'} + + + {!isValidUsername ? 'Username is not valid' : usernameExists ? 'Username is available' : 'Username is not available'} - )} - - { isLoadingExistsCheck.current ? : ( - isValidUsername ? 'Username is available' : 'Username is not available' - )} - + + }
- )} + }

- Nice to meet you, {username}! + Nice to meet you, {username}!

- Your Thinky.gg journey is about to launch! 🚀 + Your Thinky.gg journey is about to launch! 🚀

setEmail(e.target.value)} value={email} className='shadow appearance-none border rounded w-full py-2 px-3 leading-tight focus:outline-none focus:shadow-outline' id='email' type='email' placeholder='Email' />
setPassword(e.target.value)} className='shadow appearance-none border rounded w-full py-2 px-3 leading-tight focus:outline-none focus:shadow-outline' id='password' type='password' placeholder='******************' />
@@ -187,7 +180,7 @@ export default function SignupFormWizard() {
diff --git a/pages/[subdomain]/confirm-email/index.tsx b/pages/[subdomain]/confirm-email/index.tsx index 7890293b7..47291d562 100644 --- a/pages/[subdomain]/confirm-email/index.tsx +++ b/pages/[subdomain]/confirm-email/index.tsx @@ -58,10 +58,10 @@ export default function ConfirmPage() { We have sent you an email to confirm your email address.
Check your inbox {user?.email} and click the link to confirm and you will be all set!

- Haven't received the email?
Check your spam folder or click here to resend (or update your email). + Haven't received the email?
Check your spam folder or click here to resend (or update your email).

- Once you have confirmed your email, you will be redirected automatically. + Once you have confirmed your email, you will be redirected automatically.

diff --git a/pages/[subdomain]/signup/index.tsx b/pages/[subdomain]/signup/index.tsx index 4c11461c6..57e923ed3 100644 --- a/pages/[subdomain]/signup/index.tsx +++ b/pages/[subdomain]/signup/index.tsx @@ -21,15 +21,14 @@ export async function getServerSideProps(context: GetServerSidePropsContext) { } return { - props: { - }, + props: {}, }; } /* istanbul ignore next */ export default function SignUp() { return ( - + <>
@@ -46,17 +45,15 @@ export default function SignUp() { className='inline-block align-baseline font-bold text-sm hover:text-blue-400' href='/play-as-guest' > - Play as Guest + Play as Guest
{'Already have an account? '} - Log In + Log In -
-
diff --git a/pages/api/signup/index.ts b/pages/api/signup/index.ts index 6a8a930cc..7564b6ebe 100644 --- a/pages/api/signup/index.ts +++ b/pages/api/signup/index.ts @@ -64,8 +64,8 @@ async function createUser({ gameId, email, name, password, tutorialCompletedAt, export default apiWrapper({ POST: { body: { - guest: ValidType('boolean', false), email: ValidType('string'), + guest: ValidType('boolean', false), name: ValidType('string'), password: ValidType('string'), tutorialCompletedAt: ValidNumber(false), @@ -73,7 +73,7 @@ export default apiWrapper({ POST: { } }, async (req: NextApiRequestWrapper, res: NextApiResponse) => { await dbConnect(); - const { email, name, password, tutorialCompletedAt, guest, utm_source } = req.body; + const { email, guest, name, password, tutorialCompletedAt, utm_source } = req.body; let trimmedEmail: string, trimmedName: string, passwordValue: string; diff --git a/pages/api/user/exists.ts b/pages/api/user/exists.ts index f8aff4d53..a2ef06f81 100644 --- a/pages/api/user/exists.ts +++ b/pages/api/user/exists.ts @@ -10,7 +10,7 @@ export default apiWrapper({ } }, async (req: NextApiRequestWrapper, res: NextApiResponse) => { const { name } = req.query as { name: string }; - const userExists = await UserModel.exists({ name }); + const userExists = await UserModel.exists({ name: name.trim() }); - return res.status(userExists ? 200 : 404).json({ exists: userExists }); + return res.status(200).json({ exists: !!userExists }); }); diff --git a/styles/global.css b/styles/global.css index 82b3de5e3..66cbd927b 100644 --- a/styles/global.css +++ b/styles/global.css @@ -587,4 +587,4 @@ body { */ #headlessui-portal-root > [data-headlessui-portal]:nth-child(2) > div > div > div:first-child { user-select: none; -} \ No newline at end of file +}