Skip to content

Commit

Permalink
signup tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
sspenst committed May 22, 2024
1 parent 92d9e05 commit 43836a5
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 65 deletions.
95 changes: 44 additions & 51 deletions components/forms/signupFormWizard.tsx
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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...');

Expand Down Expand Up @@ -93,19 +86,15 @@ export default function SignupFormWizard() {

const [isValidUsername, setIsValidUsername] = useState<boolean>(true);
const [wizard, setWizard] = useState<StepWizardProps>();
const isLoadingExistsCheck = useRef<boolean>(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<boolean>(false);
const [isExistsLoading, setIsExistsLoading] = useState<boolean>(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
Expand All @@ -115,68 +104,72 @@ export default function SignupFormWizard() {

// check if username is valid
const handleUsernameChange = (e: React.ChangeEvent<HTMLInputElement>) => {
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 (
<FormTemplate>
<form className='flex flex-col gap-4' onSubmit={onSubmit}>
<StepWizard instance={setWizard}

>
<StepWizard instance={setWizard}>
<div className='flex flex-col gap-4'>
<label className='block text-sm font-bold ' htmlFor='username'>
What should we call you?
What should we call you?
</label>
<input required onChange={e => 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' />
<button type='button' disabled={username.length === 0 || !isValidUsername} onClick={() => (wizard as any)?.nextStep()}
className='bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline cursor-pointer disabled:opacity-50'>Next</button>
{ username.length >= 3 && (
<button
className='bg-blue-600 enabled:hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline disabled:opacity-50'
disabled={!isValidUsername || !usernameExists}
onClick={() => (wizard as any)?.nextStep()}
>
Next
</button>
{username.length >= 3 &&
<div className='flex items-center gap-2'>
{username.length > 0 && !isLoadingExistsCheck.current && (
{isExistsLoading ? <LoadingSpinner size='small' /> : <>
<span className={`text-sm ${isValidUsername ? 'text-green-600' : 'text-red-600'}`}>
{isValidUsername ? '✅' : '❌'}
{isValidUsername && usernameExists ? '✅' : '❌'}
</span>
<span>
{!isValidUsername ? 'Username is not valid' : usernameExists ? 'Username is available' : 'Username is not available'}
</span>
)}
<span className='text-sm'>
{ isLoadingExistsCheck.current ? <LoadingSpinner size='small' /> : (
isValidUsername ? 'Username is available' : 'Username is not available'
)}
</span>
</>
}
</div>
)}
}
</div>
<div className='flex flex-col gap-2'>
<p className='text-center text-lg'>
Nice to meet you, <span className='font-bold'>{username}</span>!
Nice to meet you, <span className='font-bold'>{username}</span>!
</p>
<p className='text-center text-md'>
Your Thinky.gg journey is about to launch! 🚀
Your Thinky.gg journey is about to launch! 🚀
</p>
<label className='block text-sm font-bold ' htmlFor='email'>
Email
Email
</label>
<input required onChange={e => 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' />
<div className='flex flex-col gap-4'>
<label className='block text-sm font-bold ' htmlFor='password'>
Password
Password
</label>
<input required onChange={e => 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='******************' />
<div className='flex items-center justify-between gap-1'>
Expand All @@ -187,7 +180,7 @@ export default function SignupFormWizard() {
<div className='flex items-center justify-between gap-1'>
<input type='checkbox' id='terms_agree_checkbox' required />
<label htmlFor='terms_agree_checkbox' className='text-xs p-1'>
I agree to the <a className='underline' href='https://docs.google.com/document/d/e/2PACX-1vR4E-RcuIpXSrRtR3T3y9begevVF_yq7idcWWx1A-I9w_VRcHhPTkW1A7DeUx2pGOcyuKifEad3Qokn/pub' rel='noreferrer' target='_blank'>terms of service</a> and reviewed the <a className='underline' href='https://docs.google.com/document/d/e/2PACX-1vSNgV3NVKlsgSOEsnUltswQgE8atWe1WCLUY5fQUVjEdu_JZcVlRkZcpbTOewwe3oBNa4l7IJlOnUIB/pub' rel='noreferrer' target='_blank'>privacy policy</a>.
I agree to the <a className='underline' href='https://docs.google.com/document/d/e/2PACX-1vR4E-RcuIpXSrRtR3T3y9begevVF_yq7idcWWx1A-I9w_VRcHhPTkW1A7DeUx2pGOcyuKifEad3Qokn/pub' rel='noreferrer' target='_blank'>terms of service</a> and reviewed the <a className='underline' href='https://docs.google.com/document/d/e/2PACX-1vSNgV3NVKlsgSOEsnUltswQgE8atWe1WCLUY5fQUVjEdu_JZcVlRkZcpbTOewwe3oBNa4l7IJlOnUIB/pub' rel='noreferrer' target='_blank'>privacy policy</a>.
</label>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions pages/[subdomain]/confirm-email/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ export default function ConfirmPage() {
We have sent you an email to <span className='font-bold'>confirm your email address</span>.<br />Check your inbox <span className='font-bold'>{user?.email}</span> and click the link to confirm and you will be all set!
</p>
<p className='text-lg mt-8'>
Haven&apos;t received the email? <br />Check your spam folder or <Link href={'/settings'} className='underline font-bold'>click here to resend</Link> (or update your email).
Haven&apos;t received the email? <br />Check your spam folder or <Link href={'/settings'} className='underline font-bold'>click here to resend</Link> (or update your email).
</p>
<p className='text-lg mt-8'>
Once you have confirmed your email, you will be redirected automatically.
Once you have confirmed your email, you will be redirected automatically.
</p>
</div>
</Page>
Expand Down
11 changes: 4 additions & 7 deletions pages/[subdomain]/signup/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,14 @@ export async function getServerSideProps(context: GetServerSidePropsContext) {
}

return {
props: {
},
props: {},
};
}

/* istanbul ignore next */
export default function SignUp() {
return (
<Page title={'Sign Up'}>
<Page title='Sign Up'>
<>
<div className='w-full max-w-md mx-auto mt-3 justify-center text-center'>
<div className='flex flex-col gap-2 items-center'>
Expand All @@ -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
</Link>
</div>
<div className='text-center mb-4'>
{'Already have an account? '}
<Link href='/login' passHref className='underline'>
Log In
Log In
</Link>

</div>

</div>
</>
</Page>
Expand Down
4 changes: 2 additions & 2 deletions pages/api/signup/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,16 @@ 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),
},
} }, 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;

Expand Down
4 changes: 2 additions & 2 deletions pages/api/user/exists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 });
});
2 changes: 1 addition & 1 deletion styles/global.css
Original file line number Diff line number Diff line change
Expand Up @@ -587,4 +587,4 @@ body {
*/
#headlessui-portal-root > [data-headlessui-portal]:nth-child(2) > div > div > div:first-child {
user-select: none;
}
}

0 comments on commit 43836a5

Please sign in to comment.