Skip to content

Commit

Permalink
login improvments
Browse files Browse the repository at this point in the history
  • Loading branch information
andre-brandao committed Nov 5, 2024
1 parent f453fff commit b5f7f41
Show file tree
Hide file tree
Showing 13 changed files with 275 additions and 291 deletions.
2 changes: 1 addition & 1 deletion components.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"aliases": {
"components": "$lib/client/components",
"utils": "$lib/utils",
"utils": "$lib/utils.ts",
"ui": "$lib/client/components/ui",
"hooks": "$lib/hooks"
},
Expand Down
144 changes: 111 additions & 33 deletions src/lib/client/components/login-form.svelte
Original file line number Diff line number Diff line change
@@ -1,48 +1,126 @@
<script lang="ts">
import { enhance } from '$app/forms'
import { Button } from '$lib/client/components/ui/button/index.js'
import * as Card from '$lib/client/components/ui/card/index.js'
import { Input } from '$lib/client/components/ui/input/index.js'
import { Label } from '$lib/client/components/ui/label/index.js'
import { page } from '$app/stores'
import * as Tabs from '$lib/client/components/ui/tabs/index.js'
import type { Snippet } from 'svelte'
let {
children,
}: {
children?: Snippet
} = $props()
const defaultForm = $page.url.searchParams.get('tab') ?? 'login'
</script>

<Card.Root class="mx-auto max-w-sm">
<Card.Header>
<Card.Title class="text-2xl">Login</Card.Title>
<Card.Description>
Enter your email below to login to your account
</Card.Description>
</Card.Header>
<Card.Content>
<form class="grid gap-4" method="post" action="/login/password?/login">
<div class="grid gap-2">
<Label for="email">Email</Label>
<Input id="email" type="email" placeholder="[email protected]" required />
</div>
<div class="grid gap-2">
<div class="flex items-center">
<Label for="password">Password</Label>
<a href="##" class="ml-auto inline-block text-sm underline">
Forgot your password?
</a>
<Tabs.Root value={defaultForm} class="w-[400px]">
<Tabs.List class="grid w-full grid-cols-2">
<Tabs.Trigger value="login">Login</Tabs.Trigger>
<Tabs.Trigger value="signup">Signup</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="login">
<Card.Root>
<Card.Header>
<Card.Title class="text-2xl">Login</Card.Title>
<Card.Description>
Enter your email below to login to your account
</Card.Description>
</Card.Header>
<Card.Content>
<form
class="grid gap-4"
method="post"
action="/login?/password"
use:enhance
>
<div class="grid gap-2">
<Label for="email">Email</Label>
<Input
id="email"
type="email"
placeholder="[email protected]"
required
/>
</div>
<div class="grid gap-2">
<div class="flex items-center">
<Label for="password">Password</Label>
<a
href="/reset-password"
class="ml-auto inline-block text-sm underline"
>
Forgot your password?
</a>
</div>
<Input id="password" type="password" required />
</div>

{@render children?.()}
<Button type="submit" class="w-full">Login</Button>
<Button href="/login/google" variant="outline" class="w-full">
Login with Google
</Button>
</form>
<div class="mt-4 text-center text-sm">
Don't have an account?
<Tabs.Trigger value="signup">Signup</Tabs.Trigger>
</div>
<Input id="password" type="password" required />
</div>
</Card.Content>
</Card.Root>
</Tabs.Content>
<Tabs.Content value="signup">
<Card.Root>
<Card.Header>
<Card.Title class="text-2xl">Singup</Card.Title>
<Card.Description>
Enter your email below to create an account
</Card.Description>
</Card.Header>
<Card.Content>
<form
class="grid gap-4"
method="post"
action="/login?/signup"
use:enhance
>
<div class="grid gap-2">
<Label for="username">Username</Label>
<Input
id="username"
name="username"
type="text"
placeholder="username"
required
/>
</div>
<div class="grid gap-2">
<Label for="email">Email</Label>
<Input
id="email"
type="email"
name="email"
placeholder="[email protected]"
required
/>
</div>
<div class="grid gap-2">
<div class="flex items-center">
<Label for="password">Password</Label>
</div>
<Input id="password" type="password" name='password' required />
</div>

{@render children?.()}
<Button type="submit" class="w-full">Login</Button>
<Button href="/login/google" variant="outline" class="w-full">
Login with Google
</Button>
</form>
<div class="mt-4 text-center text-sm">
Don't have an account?
<a href="##" class="underline">Sign up</a>
</div>
</Card.Content>
</Card.Root>
{@render children?.()}
<Button type="submit" class="w-full">Sign up</Button>
<Button href="/login/google" variant="outline" class="w-full">
Login with Google
</Button>
</form>
</Card.Content>
</Card.Root>
</Tabs.Content>
</Tabs.Root>
18 changes: 18 additions & 0 deletions src/lib/client/components/ui/tabs/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Tabs as TabsPrimitive } from "bits-ui";
import Content from "./tabs-content.svelte";
import List from "./tabs-list.svelte";
import Trigger from "./tabs-trigger.svelte";

const Root = TabsPrimitive.Root;

export {
Root,
Content,
List,
Trigger,
//
Root as Tabs,
Content as TabsContent,
List as TabsList,
Trigger as TabsTrigger,
};
19 changes: 19 additions & 0 deletions src/lib/client/components/ui/tabs/tabs-content.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import { Tabs as TabsPrimitive } from "bits-ui";
import { cn } from "$lib/utils";
let {
ref = $bindable(null),
class: className,
...restProps
}: TabsPrimitive.ContentProps = $props();
</script>

<TabsPrimitive.Content
bind:ref
class={cn(
"ring-offset-background focus-visible:ring-ring mt-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2",
className
)}
{...restProps}
/>
19 changes: 19 additions & 0 deletions src/lib/client/components/ui/tabs/tabs-list.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import { Tabs as TabsPrimitive } from "bits-ui";
import { cn } from "$lib/utils";
let {
ref = $bindable(null),
class: className,
...restProps
}: TabsPrimitive.ListProps = $props();
</script>

<TabsPrimitive.List
bind:ref
class={cn(
"bg-muted text-muted-foreground inline-flex h-10 items-center justify-center rounded-md p-1",
className
)}
{...restProps}
/>
19 changes: 19 additions & 0 deletions src/lib/client/components/ui/tabs/tabs-trigger.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts">
import { Tabs as TabsPrimitive } from "bits-ui";
import { cn } from "$lib/utils";
let {
ref = $bindable(null),
class: className,
...restProps
}: TabsPrimitive.TriggerProps = $props();
</script>

<TabsPrimitive.Trigger
bind:ref
class={cn(
"ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm",
className
)}
{...restProps}
/>
84 changes: 76 additions & 8 deletions src/routes/(auth)/login/+page.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { fail, redirect } from '@sveltejs/kit'
import type { Actions, PageServerLoad } from './$types'

import { user } from '$db/controller'
import { sessionsC } from '$lib/server/auth/sessions'
import {
sessionsC,
} from '$lib/server/auth/sessions'
import { deleteSessionTokenCookie } from '$lib/server/auth/cookies'
deleteSessionTokenCookie,
setSessionTokenCookie,
} from '$lib/server/auth/cookies'
import { emailTemplate, sendMail } from '$lib/server/services/email'
// import { emailTemplate, sendMail } from '$lib/server/email'

export const load: PageServerLoad = async event => {
Expand All @@ -17,10 +19,11 @@ export const load: PageServerLoad = async event => {
}

export const actions: Actions = {
login: async ({ request, url }) => {
magic_link: async ({ request, url }) => {
const formData = await request.formData()

const email = formData.get('email')
console.log('(auth)/login?/magic_link', email)

const { error } = await user.auth.login.magicLink.send({
email,
Expand All @@ -40,15 +43,80 @@ export const actions: Actions = {
}
},
logout: async event => {
console.log('logout')

console.log('(auth)/login?/logout', event.locals.user)
const { session } = event.locals

if (!session) {
return redirect(302, '/login')
}
await sessionsC.invalidateSession(session.id)
await sessionsC.invalidateSession(session.id)
deleteSessionTokenCookie(event)
return redirect(302, '/login')
},

password: async event => {
const formData = await event.request.formData()
// const username = formData.get('username')
const password = formData.get('password')
const email = formData.get('email')
console.log('(auth)/login?/password', email, password)

const { data, error } = await user.auth.login.password(email, password)

if (error) {
return fail(404, {
succes: false,
message: error.message,
})
}
const existingUser = data.user

const token = sessionsC.generateSessionToken()
const session = await sessionsC.createSession(token, existingUser.id)
setSessionTokenCookie(event, token, session.expiresAt)
if (!existingUser.emailVerified) {
return redirect(302, '/verify-email')
}

return redirect(302, '/')
},

signup: async event => {
const formData = await event.request.formData()
const username = formData.get('username')
const password = formData.get('password')
const email = formData.get('email')
console.log('(auth)/login?/signup', username, email, password)

const { data, error } = await user.auth.register.withPassword(
username,
email,
password,
)

if (error) {
return fail(400, {
success: false,
message: error.message,
username,
email,
})
}

const userId = data.user.id
const ueserEmail = data.user.email

const token = sessionsC.generateSessionToken()
const session = await sessionsC.createSession(token, userId)
setSessionTokenCookie(event, token, session.expiresAt)

// const verificationCode = await user.verificationCode.generate(
// userId,
// ueserEmail,
// )

// await sendMail(ueserEmail, emailTemplate.verificationCode(verificationCode))

return redirect(302, '/admin')
},
}
8 changes: 8 additions & 0 deletions src/routes/(auth)/login/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,21 @@
</main> -->

<script lang="ts">
import * as m from '$lib/i18n/paraglide/messages'
import SEO, { getSEOProps } from '$components/SEO/index.svelte'
import type { ActionData } from './$types'
import Info from '$components/Info.svelte'
export let form: ActionData
import LoginForm from '$lib/client/components/login-form.svelte'
</script>

<SEO
{...getSEOProps({
title: m.title_sign_in(),
description: 'Sign in to your account',
})}
/>
<div class="flex h-screen w-full items-center justify-center px-4">
<LoginForm>
{#if form}
Expand Down
Loading

0 comments on commit b5f7f41

Please sign in to comment.