112 lines
2.9 KiB
Vue
112 lines
2.9 KiB
Vue
<script setup lang="ts">
|
|
import type { AuthFormField, FormSubmitEvent } from '@nuxt/ui'
|
|
import { useForm } from '@inertiajs/vue3'
|
|
import * as v from 'valibot'
|
|
import { computed, ref } from 'vue'
|
|
import { useAuth } from '@/composables/useAuth'
|
|
import AuthLayout from '@/layouts/AuthLayout.vue'
|
|
|
|
const { config, flash } = useAuth()
|
|
|
|
const form = useForm('LoginForm', {
|
|
login: '',
|
|
password: '',
|
|
remember: false,
|
|
})
|
|
|
|
const rememberMe = ref(false)
|
|
|
|
const fields: AuthFormField[] = [
|
|
{
|
|
name: 'login',
|
|
type: 'text',
|
|
label: 'Email or Username',
|
|
placeholder: 'Enter your email or username',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'password',
|
|
type: 'password',
|
|
label: 'Password',
|
|
placeholder: 'Enter your password',
|
|
required: true,
|
|
},
|
|
]
|
|
|
|
const providers = computed(() =>
|
|
config.value.providers.map(provider => ({
|
|
label: provider.label,
|
|
icon: provider.icon,
|
|
to: `/auth/${provider.key}`,
|
|
})),
|
|
)
|
|
|
|
const schema = v.object({
|
|
login: v.pipe(v.string('Email or username is required'), v.nonEmpty('Email or username is required')),
|
|
password: v.pipe(v.string('Password is required'), v.nonEmpty('Password is required')),
|
|
remember: v.optional(v.boolean()),
|
|
})
|
|
|
|
type Schema = v.InferOutput<typeof schema>
|
|
|
|
function onSubmit(event: FormSubmitEvent<Schema>) {
|
|
form.login = event.data.login
|
|
form.password = event.data.password
|
|
form.remember = rememberMe.value
|
|
|
|
form.post('/login')
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<AuthLayout>
|
|
<UAuthForm
|
|
:schema="schema"
|
|
:fields="fields"
|
|
:providers="providers"
|
|
:submit="{ label: config.login.submit_label, loading: form.processing }"
|
|
:disabled="form.processing"
|
|
:ui="{ header: 'hidden' }"
|
|
@submit="onSubmit"
|
|
>
|
|
<template v-if="config.features.password_reset" #password-hint>
|
|
<ULink to="/forgot-password" class="text-primary font-medium" tabindex="-1">
|
|
Forgot password?
|
|
</ULink>
|
|
</template>
|
|
|
|
<template v-if="form.errors.login || flash.status" #validation>
|
|
<UAlert
|
|
v-if="form.errors.login"
|
|
color="error"
|
|
icon="i-lucide-alert-circle"
|
|
:title="form.errors.login"
|
|
/>
|
|
<UAlert
|
|
v-if="flash.status"
|
|
color="success"
|
|
icon="i-lucide-check-circle"
|
|
:title="flash.status"
|
|
/>
|
|
</template>
|
|
|
|
<template #footer>
|
|
<div class="flex items-center justify-between">
|
|
<UCheckbox
|
|
v-if="config.features.remember_me"
|
|
v-model="rememberMe"
|
|
label="Remember me"
|
|
/>
|
|
<span v-else />
|
|
<span v-if="config.features.registration" class="text-sm text-muted">
|
|
Don't have an account?
|
|
<ULink to="/register" class="text-primary font-medium">
|
|
Sign up
|
|
</ULink>
|
|
</span>
|
|
</div>
|
|
</template>
|
|
</UAuthForm>
|
|
</AuthLayout>
|
|
</template>
|