add login page with contained inputs
This commit is contained in:
parent
762d5c0fc0
commit
fd10dcfb15
2 changed files with 128 additions and 0 deletions
34
src/routes/auth/login/+page.server.ts
Normal file
34
src/routes/auth/login/+page.server.ts
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
import type { Actions, PageServerLoad } from './$types'
|
||||
import { fail, redirect } from '@sveltejs/kit'
|
||||
|
||||
export const load: PageServerLoad = async ({ locals, url }) => {
|
||||
if (locals.session.isAuthenticated) {
|
||||
redirect(302, url.searchParams.get('next') ?? '/me')
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
export const actions: Actions = {
|
||||
default: async ({ request, fetch, url }) => {
|
||||
const form = await request.formData()
|
||||
const email = String(form.get('email') ?? '')
|
||||
const password = String(form.get('password') ?? '')
|
||||
|
||||
if (!email || !password) {
|
||||
return fail(400, { error: 'Email and password are required', email })
|
||||
}
|
||||
|
||||
const res = await fetch('/auth/login', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ email, password, grant_type: 'password' })
|
||||
})
|
||||
|
||||
if (res.ok) {
|
||||
redirect(303, url.searchParams.get('next') ?? '/me')
|
||||
}
|
||||
|
||||
const j = await res.json().catch(() => ({}))
|
||||
return fail(res.status, { error: j.error ?? 'Login failed', email })
|
||||
}
|
||||
}
|
||||
94
src/routes/auth/login/+page.svelte
Normal file
94
src/routes/auth/login/+page.svelte
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
<script lang="ts">
|
||||
import { enhance } from '$app/forms'
|
||||
import AuthCard from '$lib/components/auth/AuthCard.svelte'
|
||||
import Input from '$lib/components/ui/Input.svelte'
|
||||
import Button from '$lib/components/ui/Button.svelte'
|
||||
import * as m from '$lib/paraglide/messages'
|
||||
|
||||
interface Props {
|
||||
form: { error?: string; email?: string } | null
|
||||
}
|
||||
|
||||
let { form }: Props = $props()
|
||||
|
||||
let email = $state(form?.email ?? '')
|
||||
let password = $state('')
|
||||
let isSubmitting = $state(false)
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>{m.auth_login_title()} | Granblue Party</title>
|
||||
</svelte:head>
|
||||
|
||||
<AuthCard title={m.auth_login_title()}>
|
||||
<form
|
||||
method="post"
|
||||
use:enhance={() => {
|
||||
isSubmitting = true
|
||||
return async ({ update }) => {
|
||||
isSubmitting = false
|
||||
await update()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<Input
|
||||
type="email"
|
||||
name="email"
|
||||
label={m.auth_login_email()}
|
||||
bind:value={email}
|
||||
autocomplete="email"
|
||||
required
|
||||
fullWidth
|
||||
contained
|
||||
/>
|
||||
|
||||
<Input
|
||||
type="password"
|
||||
name="password"
|
||||
label={m.auth_login_password()}
|
||||
bind:value={password}
|
||||
autocomplete="current-password"
|
||||
minlength={8}
|
||||
required
|
||||
fullWidth
|
||||
contained
|
||||
/>
|
||||
|
||||
{#if form?.error}
|
||||
<p class="error">{form.error}</p>
|
||||
{/if}
|
||||
|
||||
<Button type="submit" variant="primary" fullWidth disabled={isSubmitting}>
|
||||
{isSubmitting ? m.auth_login_submitting() : m.auth_login_submit()}
|
||||
</Button>
|
||||
</form>
|
||||
|
||||
{#snippet footer()}
|
||||
<p>
|
||||
{m.auth_login_noAccount()}
|
||||
<a href="/auth/register">{m.auth_login_register()}</a>
|
||||
</p>
|
||||
{/snippet}
|
||||
</AuthCard>
|
||||
|
||||
<style lang="scss">
|
||||
@use '$src/themes/spacing' as *;
|
||||
@use '$src/themes/colors' as *;
|
||||
@use '$src/themes/typography' as *;
|
||||
|
||||
form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: $unit-2x;
|
||||
}
|
||||
|
||||
.error {
|
||||
color: $error;
|
||||
font-size: $font-small;
|
||||
text-align: center;
|
||||
margin: 0;
|
||||
padding: $unit $unit-2x;
|
||||
background: var(--danger-bg);
|
||||
border-radius: $unit;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in a new issue