Refactor email sign up form

pull/3813/head
Kamran Ahmed 2 years ago
parent 9c8cd71ed2
commit 1ea66824d0
  1. 144
      src/components/Login/EmailSignupForm.tsx
  2. 2
      src/components/SocialAuth/GitHubButton.tsx
  3. 5
      src/components/SocialAuth/GoogleButton.tsx

@ -1,76 +1,63 @@
import Cookies from 'js-cookie';
import type { FunctionComponent } from 'preact'; import type { FunctionComponent } from 'preact';
import { useState } from 'preact/hooks'; import { useState } from 'preact/hooks';
import { TOKEN_COOKIE_NAME } from '../../lib/constants';
import Spinner from '../Spinner';
const EmailSignupForm: FunctionComponent<{}> = () => { const EmailSignupForm: FunctionComponent = () => {
const [email, setEmail] = useState<string>(''); const [email, setEmail] = useState('');
const [password, setPassword] = useState<string>(''); const [password, setPassword] = useState('');
const [name, setName] = useState<string>(''); const [name, setName] = useState('');
const [isLoading, setIsLoading] = useState<boolean>(false); const [error, setError] = useState('');
const [message, setMessage] = useState<{ const [isLoading, setIsLoading] = useState(false);
type: 'success' | 'error' | 'verification' | 'warning';
message: string; const handleRegisterResponse = async (res: Response) => {
} | null>(null); const json = await res.json();
if (!res.ok) {
setError(json.message || 'Something went wrong. Please try again later.');
setIsLoading(false);
return;
}
window.location.href = `/verify?email=${email}`;
};
const onSubmit = (e: Event) => {
e.preventDefault();
setIsLoading(true);
fetch(`${import.meta.env.PUBLIC_API_URL}/v1-register`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
password,
name,
}),
})
.then(handleRegisterResponse)
.catch((err) => {
setIsLoading(false);
setError('Something went wrong. Please try again later.');
});
};
return ( return (
<form <form className="flex w-full flex-col gap-2" onSubmit={onSubmit}>
className="w-full"
onSubmit={(e) => {
e.preventDefault();
setIsLoading(true);
fetch('http://localhost:8080/v1-register', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
password,
name,
}),
})
.then(async (res) => {
const json = await res.json();
if (res.status === 200) {
window.location.href = `/verify?email=${email}`;
setName('');
setEmail('');
setPassword('');
setMessage({
type: 'success',
message:
'We have sent you an email with the verification link. Please follow the instructions to login.',
});
} else {
const error = new Error(json.message) as any;
error.status = res.status;
throw error;
}
setIsLoading(false);
})
.catch((err) => {
setIsLoading(false);
setMessage({
type: 'error',
message: err.message,
});
});
}}
>
<label htmlFor="name" className="sr-only"> <label htmlFor="name" className="sr-only">
Name Name
</label> </label>
<input <input
id="name"
name="name" name="name"
type="name" type="text"
autoComplete="name" autoComplete="name"
min={3}
max={50}
required required
className="block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1" className="block w-full rounded-lg border border-gray-300 px-3 py-2 outline-none placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
placeholder="John Doe" placeholder="Full Name"
value={name} value={name}
onInput={(e) => setName(String((e.target as any).value))} onInput={(e) => setName(String((e.target as any).value))}
/> />
@ -78,13 +65,12 @@ const EmailSignupForm: FunctionComponent<{}> = () => {
Email address Email address
</label> </label>
<input <input
id="email"
name="email" name="email"
type="email" type="email"
autoComplete="email" autoComplete="email"
required required
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1" className="block w-full rounded-lg border border-gray-300 px-3 py-2 outline-none placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
placeholder="john@example.com" placeholder="Email Address"
value={email} value={email}
onInput={(e) => setEmail(String((e.target as any).value))} onInput={(e) => setEmail(String((e.target as any).value))}
/> />
@ -92,42 +78,28 @@ const EmailSignupForm: FunctionComponent<{}> = () => {
Password Password
</label> </label>
<input <input
id="password"
name="password" name="password"
type="password" type="password"
autoComplete="current-password" autoComplete="current-password"
min={6}
max={50}
required required
className="mt-2 block w-full appearance-none rounded-lg border border-gray-300 px-3 py-2 shadow-sm outline-none transition duration-150 ease-in-out placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1" className="block w-full rounded-lg border border-gray-300 px-3 py-2 outline-none placeholder:text-gray-400 focus:ring-2 focus:ring-black focus:ring-offset-1"
placeholder="Enter you password" placeholder="Password"
value={password} value={password}
onInput={(e) => setPassword(String((e.target as any).value))} onInput={(e) => setPassword(String((e.target as any).value))}
/> />
{message && ( {error && (
<div <p className="rounded-lg bg-red-100 p-2 text-red-700">{error}.</p>
className={`mt-2 rounded-lg p-2 ${
message.type === 'error'
? 'bg-red-100 text-red-700'
: message.type === 'success'
? 'bg-green-100 text-green-700'
: 'bg-blue-100 text-blue-700'
}`}
>
{message.message}
</div>
)} )}
<button <button
type="submit" type="submit"
disabled={ disabled={isLoading}
email.length === 0 || className="inline-flex w-full items-center justify-center rounded-lg bg-black p-2 py-3 text-sm font-medium text-white outline-none focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:bg-gray-400"
password.length === 0 ||
name.length === 0 ||
isLoading
}
className="mt-3 inline-flex h-10 w-full items-center justify-center rounded-lg border border-slate-300 bg-black p-2 text-sm font-medium text-white outline-none transition duration-150 ease-in-out focus:ring-2 focus:ring-black focus:ring-offset-1 disabled:opacity-60"
> >
{isLoading ? <Spinner className="text-white" /> : 'Continue'} {isLoading ? 'Please wait...' : 'Continue to Verify Email'}
</button> </button>
</form> </form>
); );

@ -73,7 +73,7 @@ export function GitHubButton(props: GitHubButtonProps) {
return ( return (
<> <>
<button <button
class="inline-flex h-10 w-full items-center justify-center gap-2 rounded border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-none transition duration-150 ease-in-out focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60" class="inline-flex h-10 w-full items-center justify-center gap-2 rounded border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-none focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60"
disabled={isLoading} disabled={isLoading}
onClick={handleClick} onClick={handleClick}
> >

@ -1,9 +1,8 @@
import { useEffect, useState } from 'preact/hooks'; import { useEffect, useState } from 'preact/hooks';
import Cookies from 'js-cookie';
import GoogleIcon from '../../icons/google.svg'; import GoogleIcon from '../../icons/google.svg';
import SpinnerIcon from '../../icons/spinner.svg'; import SpinnerIcon from '../../icons/spinner.svg';
import { TOKEN_COOKIE_NAME } from '../../lib/constants'; import { TOKEN_COOKIE_NAME } from '../../lib/constants';
import Cookies from 'js-cookie';
type GoogleButtonProps = {}; type GoogleButtonProps = {};
@ -73,7 +72,7 @@ export function GoogleButton(props: GoogleButtonProps) {
return ( return (
<> <>
<button <button
class="inline-flex h-10 w-full items-center justify-center gap-2 rounded border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-none transition duration-150 ease-in-out focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60" class="inline-flex h-10 w-full items-center justify-center gap-2 rounded border border-slate-300 bg-white p-2 text-sm font-medium text-black outline-none focus:ring-2 focus:ring-[#333] focus:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-60"
disabled={isLoading} disabled={isLoading}
onClick={handleClick} onClick={handleClick}
> >

Loading…
Cancel
Save