update signup page to use superform

pull/3/head
TZGyn 2 years ago
parent ea8ff70aa2
commit 68af735f09
Signed by: TZGyn
GPG Key ID: 122EAF77AE81FD4A

@ -0,0 +1,69 @@
<script lang="ts">
import * as Form from '$lib/components/ui/form'
import { Input } from '$lib/components/ui/input'
import { formSchema, type FormSchema } from '../schema'
import {
type SuperValidated,
type Infer,
superForm,
} from 'sveltekit-superforms'
import { zodClient } from 'sveltekit-superforms/adapters'
import { toast } from 'svelte-sonner'
export let data: SuperValidated<Infer<FormSchema>>
const form = superForm(data, {
validators: zodClient(formSchema),
invalidateAll: 'force',
resetForm: true,
onResult: ({ result }) => {
if (result.status === 200) {
toast.success('Signup success')
}
},
onError: ({ result }) => {
toast.error('Error signing up')
},
})
const { form: formData, enhance } = form
</script>
<form method="POST" use:enhance class="flex flex-col gap-4">
<Form.Field {form} name="email" class="flex flex-col gap-2">
<Form.Control let:attrs>
<Form.Label>Email</Form.Label>
<Input
{...attrs}
bind:value={$formData.email}
placeholder="name@example.com" />
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Form.Field {form} name="password" class="flex flex-col gap-2">
<Form.Control let:attrs>
<Form.Label>Password</Form.Label>
<Input
{...attrs}
type="password"
bind:value={$formData.password}
placeholder="••••••••" />
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Form.Field
{form}
name="password_confirm"
class="flex flex-col gap-2">
<Form.Control let:attrs>
<Form.Label>Password Confirm</Form.Label>
<Input
{...attrs}
type="password"
bind:value={$formData.password_confirm}
placeholder="••••••••" />
</Form.Control>
<Form.FieldErrors />
</Form.Field>
<Form.Button>Sign Up</Form.Button>
</form>

@ -1,67 +0,0 @@
<script lang="ts">
import Button from '$lib/components/ui/button/button.svelte'
import Input from '$lib/components/ui/input/input.svelte'
import Label from '$lib/components/ui/label/label.svelte'
import { Loader2 } from 'lucide-svelte'
import { goto } from '$app/navigation'
let isLoading = false
let email = ''
let password = ''
let password_confirm = ''
const userSignUp = async () => {
isLoading = true
const response = await fetch('/api/signup', {
method: 'post',
body: JSON.stringify({
email,
password,
password_confirm,
}),
})
const data = await response.json()
isLoading = false
if (data.success) {
goto('/')
}
}
</script>
<div class="flex flex-col gap-4">
<div class="flex w-full max-w-sm flex-col gap-2">
<Label for="email">Email</Label>
<Input
type="email"
id="email"
placeholder="name@example.com"
bind:value={email} />
</div>
<div class="flex w-full max-w-sm flex-col gap-2">
<Label for="password">Password</Label>
<Input
type="password"
id="password"
placeholder="••••••••"
bind:value={password} />
</div>
<div class="flex w-full max-w-sm flex-col gap-2">
<Label for="password_confirm">Password Confirm</Label>
<Input
type="password"
id="password_confirm"
placeholder="••••••••"
bind:value={password_confirm} />
</div>
<Button
disabled={isLoading}
on:click={userSignUp}
class="flex items-center gap-2">
{#if isLoading}
<Loader2 class="animate-spin" />
{/if}
Sign Up
</Button>
</div>

@ -0,0 +1,63 @@
import type { PageServerLoad, Actions } from './$types'
import { fail } from '@sveltejs/kit'
import { setError, superValidate } from 'sveltekit-superforms'
import { formSchema } from './schema'
import { zod } from 'sveltekit-superforms/adapters'
import { db } from '$lib/db'
import { user as userSchema } from '$lib/db/schema'
import { eq } from 'drizzle-orm'
import { lucia } from '$lib/server/auth'
export const load = (async (event) => {
return {
form: await superValidate(zod(formSchema)),
}
}) satisfies PageServerLoad
export const actions: Actions = {
default: async (event) => {
const form = await superValidate(event, zod(formSchema))
if (!form.valid) {
return fail(400, {
form,
})
}
if (form.data.password !== form.data.password_confirm) {
return setError(form, 'password_confirm', 'Password Not Match')
}
const users = await db
.select()
.from(userSchema)
.where(eq(userSchema.email, form.data.email))
const user = users[0]
if (user) {
return setError(form, 'email', 'Email Already Exist')
}
const hashedPassword = await Bun.password.hash(form.data.password)
const returnUsers = await db
.insert(userSchema)
.values({
email: form.data.email,
password: hashedPassword,
})
.returning()
const session = await lucia.createSession(returnUsers[0].id, {})
const sessionCookie = lucia.createSessionCookie(session.id)
event.cookies.set(sessionCookie.name, sessionCookie.value, {
...sessionCookie.attributes,
path: '/',
secure: Bun.env.APP_ENV === 'prod',
})
return {
form,
}
},
}

@ -1,37 +1,40 @@
<script lang="ts">
import ThemeToggle from '$lib/components/theme-toggle.svelte'
import UserAuthForm from './(components)/user-auth-form.svelte'
import Form from './(components)/form.svelte'
import type { PageData } from './$types'
export let data: PageData
</script>
<div
class="container relative h-screen flex-col items-center justify-center md:grid lg:max-w-none lg:grid-cols-2 lg:px-0">
<div class="absolute right-4 top-4 md:right-8 md:top-8">
class="container relative flex-col justify-center items-center h-screen md:grid lg:grid-cols-2 lg:px-0 lg:max-w-none">
<div class="absolute top-4 right-4 md:top-8 md:right-8">
<ThemeToggle />
</div>
<div
class="bg-primary-foreground relative hidden h-full flex-col p-10 text-white dark:border-r lg:flex">
class="hidden relative flex-col p-10 h-full text-white lg:flex dark:border-r bg-primary-foreground">
<div
class="text-primary relative z-20 flex items-center text-lg font-medium">
class="flex relative z-20 items-center text-lg font-medium text-primary">
Shortener
</div>
</div>
<div class="p-8">
<div
class="mx-auto flex w-full flex-col justify-center space-y-6 sm:w-[350px]">
class="flex flex-col justify-center mx-auto space-y-6 w-full sm:w-[350px]">
<div class="flex flex-col space-y-2 text-center">
<h1 class="text-2xl font-semibold tracking-tight">
Create an account
</h1>
<p class="text-muted-foreground text-sm">
<p class="text-sm text-muted-foreground">
Enter your email below to create your account
</p>
</div>
<UserAuthForm />
<p class="text-muted-foreground px-8 text-center text-sm">
<Form data={data.form} />
<p class="px-8 text-sm text-center text-muted-foreground">
Already Have An Account? Login{' '}
<a
href="/login"
class="hover:text-primary underline underline-offset-4">
class="underline underline-offset-4 hover:text-primary">
Here
</a>{' '}
</p>

@ -2,8 +2,16 @@ import { z } from 'zod'
export const formSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
password_confirm: z.string().min(8),
password: z
.string()
.min(8, {
message: 'Password must be at least 8 characters long',
}),
password_confirm: z
.string()
.min(8, {
message: 'Password must be at least 8 characters long',
}),
})
export type FormSchema = typeof formSchema

@ -1,76 +0,0 @@
import type { RequestHandler } from './$types'
import { user as userSchema } from '$lib/db/schema'
import { eq } from 'drizzle-orm'
import { userCreateSchema } from '$lib/server/types'
import { db } from '$lib/db'
import { lucia } from '$lib/server/auth'
export const GET: RequestHandler = async () => {
return new Response()
}
export const POST: RequestHandler = async (event) => {
const body = await event.request.json()
const userCreate = userCreateSchema.safeParse(body)
if (!userCreate.success) {
return new Response(
JSON.stringify({
success: false,
}),
)
}
if (userCreate.data.password !== userCreate.data.password_confirm) {
return new Response(
JSON.stringify({
success: false,
message: 'password doesnt match',
}),
)
}
const users = await db
.select()
.from(userSchema)
.where(eq(userSchema.email, userCreate.data.email))
const user = users[0]
if (!user) {
const hashedPassword = await Bun.password.hash(
userCreate.data.password,
)
const returnUsers = await db
.insert(userSchema)
.values({
email: userCreate.data.email,
password: hashedPassword,
})
.returning()
const user = returnUsers[0]
const session = await lucia.createSession(user.id, {})
const sessionCookie = lucia.createSessionCookie(session.id)
event.cookies.set(sessionCookie.name, sessionCookie.value, {
...sessionCookie.attributes,
path: '/',
secure: Bun.env.APP_ENV === 'prod',
})
return new Response(
JSON.stringify({
success: true,
}),
)
} else {
return new Response(
JSON.stringify({
success: false,
}),
)
}
}
Loading…
Cancel
Save