|
|
@ -1,27 +1,32 @@ |
|
|
|
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; |
|
|
|
|
|
|
|
} | null>(null); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
const handleRegisterResponse = async (res: Response) => { |
|
|
|
<form |
|
|
|
const json = await res.json(); |
|
|
|
className="w-full" |
|
|
|
|
|
|
|
onSubmit={(e) => { |
|
|
|
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(); |
|
|
|
e.preventDefault(); |
|
|
|
|
|
|
|
|
|
|
|
setIsLoading(true); |
|
|
|
setIsLoading(true); |
|
|
|
fetch('http://localhost:8080/v1-register', { |
|
|
|
fetch(`${import.meta.env.PUBLIC_API_URL}/v1-register`, { |
|
|
|
method: 'POST', |
|
|
|
method: 'POST', |
|
|
|
headers: { |
|
|
|
headers: { |
|
|
|
'Content-Type': 'application/json', |
|
|
|
'Content-Type': 'application/json', |
|
|
@ -32,45 +37,27 @@ const EmailSignupForm: FunctionComponent<{}> = () => { |
|
|
|
name, |
|
|
|
name, |
|
|
|
}), |
|
|
|
}), |
|
|
|
}) |
|
|
|
}) |
|
|
|
.then(async (res) => { |
|
|
|
.then(handleRegisterResponse) |
|
|
|
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) => { |
|
|
|
.catch((err) => { |
|
|
|
setIsLoading(false); |
|
|
|
setIsLoading(false); |
|
|
|
setMessage({ |
|
|
|
setError('Something went wrong. Please try again later.'); |
|
|
|
type: 'error', |
|
|
|
|
|
|
|
message: err.message, |
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
}} |
|
|
|
}; |
|
|
|
> |
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
|
|
|
|
<form className="flex w-full flex-col gap-2" onSubmit={onSubmit}> |
|
|
|
<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> |
|
|
|
); |
|
|
|
); |
|
|
|