CLASSROOMIO-T-1: 1st logic for signup
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
export let supabase;
|
||||
export let handleSubmit;
|
||||
export let isLogin = true;
|
||||
export let showOnlyContent = false;
|
||||
|
||||
async function signInWithGoogle() {
|
||||
const { data, error } = await supabase.auth.signInWithOAuth({
|
||||
@@ -15,49 +16,57 @@
|
||||
</script>
|
||||
|
||||
<div class="w-full min-h-screen flex items-center justify-center mt-4">
|
||||
<div class="container border border-gray bg-white">
|
||||
<div
|
||||
class="container border border-gray bg-white {showOnlyContent && 'h-2/4'}"
|
||||
>
|
||||
<div class="flex items-center flex-col p-2 lg:px-8 lg:py-4">
|
||||
<div class="flex items-center w-full justify-center">
|
||||
<img
|
||||
src="/logo-192.png"
|
||||
alt="ClassroomIO logo"
|
||||
height="50"
|
||||
width="50"
|
||||
data-atf="1"
|
||||
/>
|
||||
<h4 class="text-xl">ClassroomIO</h4>
|
||||
</div>
|
||||
{#if !showOnlyContent}
|
||||
<div class="flex items-center w-full justify-center">
|
||||
<img
|
||||
src="/logo-192.png"
|
||||
alt="ClassroomIO logo"
|
||||
height="50"
|
||||
width="50"
|
||||
data-atf="1"
|
||||
/>
|
||||
<h4 class="text-xl">ClassroomIO</h4>
|
||||
</div>
|
||||
{/if}
|
||||
<form
|
||||
on:submit|preventDefault={handleSubmit}
|
||||
class="flex items-center flex-col w-10/12"
|
||||
>
|
||||
<slot />
|
||||
</form>
|
||||
<div class="w-10/12 mb-3">
|
||||
<p class="text-sm mb-5">or sign up with:</p>
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
onClick={signInWithGoogle}
|
||||
className="py-3 sm:w-full w-full"
|
||||
>
|
||||
<GoogleIconColored />
|
||||
<span class="ml-2">Sign up with Google</span>
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-full p-6 border-t border-grey text-center">
|
||||
{#if isLogin}
|
||||
Not registered yet? <a
|
||||
class="hover:underline text-blue-700"
|
||||
href="/signup">Sign up</a
|
||||
>
|
||||
{:else}
|
||||
Already have an account? <a
|
||||
class="hover:underline text-blue-700"
|
||||
href="/login">Log In</a
|
||||
>
|
||||
{#if !showOnlyContent}
|
||||
<div class="w-10/12 mb-3">
|
||||
<p class="text-sm mb-5">or sign up with:</p>
|
||||
<PrimaryButton
|
||||
variant={VARIANTS.OUTLINED}
|
||||
onClick={signInWithGoogle}
|
||||
className="py-3 sm:w-full w-full"
|
||||
>
|
||||
<GoogleIconColored />
|
||||
<span class="ml-2">Sign up with Google</span>
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{#if !showOnlyContent}
|
||||
<div class="w-full p-6 border-t border-grey text-center">
|
||||
{#if isLogin}
|
||||
Not registered yet? <a
|
||||
class="hover:underline text-blue-700"
|
||||
href="/signup">Sign up</a
|
||||
>
|
||||
{:else}
|
||||
Already have an account? <a
|
||||
class="hover:underline text-blue-700"
|
||||
href="/login">Log In</a
|
||||
>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<svg
|
||||
width="120"
|
||||
height="120"
|
||||
viewBox="0 0 120 120"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
clip-rule="evenodd"
|
||||
d="M85.3281 31H34.6719C33.4724 31 32.5 31.9724 32.5 33.1719V70.8281C32.5 72.0276 33.4724 73 34.6719 73H85.3281C86.5276 73 87.5 72.0276 87.5 70.8281V33.1719C87.5 31.9724 86.5276 31 85.3281 31ZM34.6719 27C31.2632 27 28.5 29.7632 28.5 33.1719V70.8281C28.5 74.2368 31.2632 77 34.6719 77H85.3281C88.7368 77 91.5 74.2368 91.5 70.8281V33.1719C91.5 29.7632 88.7368 27 85.3281 27H34.6719Z"
|
||||
fill="#0233BD"
|
||||
/>
|
||||
<rect
|
||||
x="40.9844"
|
||||
y="37.875"
|
||||
width="36.4141"
|
||||
height="3.08594"
|
||||
rx="1.54297"
|
||||
fill="#658DFE"
|
||||
/>
|
||||
<rect
|
||||
x="40.9844"
|
||||
y="44.0469"
|
||||
width="36.4141"
|
||||
height="3.08594"
|
||||
rx="1.54297"
|
||||
fill="#658DFE"
|
||||
/>
|
||||
<rect
|
||||
x="40.9844"
|
||||
y="50.2188"
|
||||
width="36.4141"
|
||||
height="3.08594"
|
||||
rx="1.54297"
|
||||
fill="#658DFE"
|
||||
/>
|
||||
<path
|
||||
d="M23 94.0391V62.5938H97V94.0391C97 96.067 95.356 97.7109 93.3281 97.7109H26.6719C24.644 97.7109 23 96.067 23 94.0391Z"
|
||||
fill="#658DFE"
|
||||
stroke="#0233BD"
|
||||
stroke-width="5"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -37,9 +37,9 @@
|
||||
});
|
||||
|
||||
async function getProfile() {
|
||||
console.log('Get user profile');
|
||||
// Get user profile
|
||||
const authUser = supabase.auth.user();
|
||||
console.log('Get user profile', authUser);
|
||||
|
||||
// Check if user has profile
|
||||
let {
|
||||
@@ -82,6 +82,7 @@
|
||||
goto('/dashboard');
|
||||
}
|
||||
}
|
||||
$user.fetchingUser = false;
|
||||
} else if (profileData) {
|
||||
// Profile exists, go to profile page
|
||||
$user.fetchingUser = false;
|
||||
|
||||
+54
-36
@@ -5,81 +5,92 @@
|
||||
</script>
|
||||
|
||||
<script>
|
||||
import { goto } from '@sapper/app';
|
||||
import { Chasing } from 'svelte-loading-spinners';
|
||||
import TextField from '../components/Form/TextField.svelte';
|
||||
import PrimaryButton from '../components/PrimaryButton/index.svelte';
|
||||
import { getSupabase } from '../utils/functions/supabase';
|
||||
import { user } from '../utils/store/user';
|
||||
import {
|
||||
signUpValidation,
|
||||
getConfirmPasswordError,
|
||||
getDisableSubmit,
|
||||
} from '../utils/functions/validator';
|
||||
import { SIGNUP_FIELDS } from '../utils/constants/authentication';
|
||||
import AuthUI from '../components/AuthUI/index.svelte';
|
||||
import EmailSentIcon from '../components/Icons/EmailSentIcon.svelte';
|
||||
|
||||
export let config;
|
||||
|
||||
let supabase = getSupabase(config);
|
||||
let email;
|
||||
let name;
|
||||
let password;
|
||||
let passwordAgain;
|
||||
let fields = Object.assign({}, SIGNUP_FIELDS);
|
||||
let loading = false;
|
||||
let success = false;
|
||||
let errors = {};
|
||||
let submitError;
|
||||
let disableSubmit = false;
|
||||
|
||||
async function handleSubmit() {
|
||||
if (!email) {
|
||||
errors = {
|
||||
email: 'Email is required',
|
||||
password: 'Password is required',
|
||||
};
|
||||
const validationRes = signUpValidation(fields);
|
||||
console.log('validationRes', validationRes);
|
||||
|
||||
if (Object.keys(validationRes).length) {
|
||||
errors = Object.assign(errors, validationRes);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
loading = true;
|
||||
const { data, error } = await supabase.auth.signIn(
|
||||
{ email },
|
||||
{
|
||||
redirectTo: window.location.origin + '/login',
|
||||
}
|
||||
);
|
||||
const { data, error } = await supabase.auth.signUp({
|
||||
email: fields.email,
|
||||
password: fields.password,
|
||||
options: {
|
||||
data: {
|
||||
fullname: fields.name,
|
||||
},
|
||||
},
|
||||
});
|
||||
if (error) throw error;
|
||||
|
||||
success = true;
|
||||
email = {};
|
||||
return goto('/login');
|
||||
// success = true;
|
||||
// fields = Object.assign({}, SIGNUP_FIELDS);
|
||||
} catch (error) {
|
||||
errors = {
|
||||
email: error.error_description || error.message,
|
||||
};
|
||||
submitError = error.error_description || error.message;
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
}
|
||||
|
||||
$: errors.confirmPassword = getConfirmPasswordError(fields);
|
||||
$: disableSubmit = getDisableSubmit(fields);
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Sign Up - ClassroomIO</title>
|
||||
</svelte:head>
|
||||
|
||||
<AuthUI {supabase} isLogin={false} {handleSubmit}>
|
||||
<AuthUI {supabase} isLogin={false} {handleSubmit} showOnlyContent={success}>
|
||||
<div class="mt-4 w-full">
|
||||
{#if $user.fetchingUser}
|
||||
<div class="h-40 text-md flex items-center justify-center">
|
||||
<Chasing size="60" color="#ff3e00" unit="px" duration="1s" />
|
||||
</div>
|
||||
{:else if success}
|
||||
<div class="h-40 text-md flex items-center justify-center flex-col">
|
||||
<p class="">
|
||||
A link has been sent to your email. Please check both your
|
||||
<div class="text-md flex items-center justify-center flex-col">
|
||||
<EmailSentIcon />
|
||||
<h2 class="text-xl">Email sent!</h2>
|
||||
<p class="mt-4 text-center">
|
||||
We have sent a confirmation email to {fields.email}. Please check both
|
||||
your
|
||||
<strong>spam </strong>and your<strong> inbox</strong>.
|
||||
</p>
|
||||
<p class="mt-2 underline">
|
||||
If our email is in your spam, do make sure you mark our email address
|
||||
as safe, then move it from your spam to your inbox.
|
||||
</p>
|
||||
</div>
|
||||
{:else}
|
||||
<p class="text-lg font-semibold mb-6">Create a free account</p>
|
||||
<TextField
|
||||
label="Full Name"
|
||||
bind:value={name}
|
||||
bind:value={fields.name}
|
||||
type="text"
|
||||
autoFocus={true}
|
||||
placeholder="e.g Joke Silva"
|
||||
@@ -87,37 +98,45 @@
|
||||
inputClassName="w-full"
|
||||
isDisabled={loading}
|
||||
errorMessage={errors.name}
|
||||
isRequired
|
||||
/>
|
||||
<TextField
|
||||
label="Your Email"
|
||||
bind:value={email}
|
||||
bind:value={fields.email}
|
||||
type="email"
|
||||
placeholder="you@domain.com"
|
||||
className="mb-6"
|
||||
inputClassName="w-full"
|
||||
isDisabled={loading}
|
||||
errorMessage={errors.email}
|
||||
isRequired
|
||||
/>
|
||||
<TextField
|
||||
label="Your Password"
|
||||
bind:value={password}
|
||||
bind:value={fields.password}
|
||||
type="password"
|
||||
placeholder="************"
|
||||
className="mb-6"
|
||||
inputClassName="w-full"
|
||||
isDisabled={loading}
|
||||
errorMessage={errors.password}
|
||||
helperMessage="Password must be more than 6 characters"
|
||||
isRequired
|
||||
/>
|
||||
<TextField
|
||||
label="Confirm Password"
|
||||
bind:value={passwordAgain}
|
||||
bind:value={fields.confirmPassword}
|
||||
type="password"
|
||||
placeholder="************"
|
||||
className="mb-6"
|
||||
inputClassName="w-full"
|
||||
isDisabled={loading}
|
||||
errorMessage={errors.passwordAgain}
|
||||
errorMessage={errors.confirmPassword}
|
||||
isRequired
|
||||
/>
|
||||
{#if submitError}
|
||||
<p class="text-sm text-red-500">{submitError}</p>
|
||||
{/if}
|
||||
<div class="w-full text-right">
|
||||
<a class="text-md text-blue-700" href="/forgot"> Forgot password? </a>
|
||||
</div>
|
||||
@@ -126,12 +145,11 @@
|
||||
|
||||
{#if !success}
|
||||
<div class="my-4 w-full flex justify-end items-center">
|
||||
<!-- <a href="/login" class="text-blue-700 text-sm">Create an account</a> -->
|
||||
<PrimaryButton
|
||||
label={loading ? 'Creating...' : 'Log In'}
|
||||
label={loading ? 'Creating...' : 'Create Account'}
|
||||
type="submit"
|
||||
className="py-3 sm:w-full w-full"
|
||||
isDisabled={loading}
|
||||
isDisabled={disableSubmit || loading}
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
export const SIGNUP_FIELDS = {
|
||||
name: '',
|
||||
email: '',
|
||||
password: '',
|
||||
confirmPassword: '',
|
||||
};
|
||||
@@ -0,0 +1,43 @@
|
||||
import z from 'zod';
|
||||
|
||||
const validationSchema = z.object({
|
||||
name: z.string().min(3, {
|
||||
message: 'Must be 3 or more characters long',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
email: z.string().email({
|
||||
message: 'Invalid email address',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
password: z.string().min(6, {
|
||||
message: 'Must be 6 or more characters long',
|
||||
invalid_type_error: 'Must not be empty',
|
||||
}),
|
||||
});
|
||||
|
||||
export const getConfirmPasswordError = ({ password, confirmPassword }) => {
|
||||
return password > 6 && confirmPassword > 6 && password !== confirmPassword
|
||||
? 'Does not match password'
|
||||
: null;
|
||||
};
|
||||
|
||||
export const signUpValidation = (fields = {}) => {
|
||||
const { error } = validationSchema.safeParse(fields);
|
||||
const errors = {};
|
||||
|
||||
if (Array.isArray(error?.issues)) {
|
||||
for (const issue of error.issues) {
|
||||
const { message, path } = issue;
|
||||
console.log(issue);
|
||||
if (path.length) {
|
||||
errors[path[0]] = message;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errors;
|
||||
};
|
||||
|
||||
export const getDisableSubmit = ({ password, confirmPassword }) => {
|
||||
return !!(password && confirmPassword && password !== confirmPassword);
|
||||
};
|
||||
Reference in New Issue
Block a user