enhance (auth): adjust component

This commit is contained in:
Abizrh
2025-08-10 15:48:49 +07:00
parent d4dc345d26
commit 53e9658424
3 changed files with 122 additions and 70 deletions
+74
View File
@@ -0,0 +1,74 @@
<script setup lang="ts">
import type { z } from 'zod'
import { toTypedSchema } from '@vee-validate/zod'
import { Loader2 } from 'lucide-vue-next'
import { useForm } from 'vee-validate'
interface Props {
schema: z.ZodSchema<any>
isLoading: boolean
}
const props = defineProps<Props>()
const emit = defineEmits<{
submit: [data: any]
}>()
const { handleSubmit, defineField, errors, meta } = useForm({
validationSchema: toTypedSchema(props.schema),
initialValues: {
name: '',
password: '',
},
})
const [name, nameAttrs] = defineField('name')
const [password, passwordAttrs] = defineField('password')
const onSubmit = handleSubmit(async (values) => {
try {
await emit('submit', values)
} catch (error) {
console.error('Submission failed:', error)
}
})
</script>
<template>
<form class="grid gap-6" @submit="onSubmit">
<div class="grid gap-2">
<Label for="name">Username</Label>
<Input
id="name"
v-model="name"
v-bind="nameAttrs"
:disabled="isLoading"
:class="{ 'border-red-500': errors.name }"
/>
<span v-if="errors.name" class="text-sm text-red-500">
{{ errors.name }}
</span>
</div>
<div class="grid gap-2">
<Label for="password">Password</Label>
<Input
id="password"
v-model="password"
v-bind="passwordAttrs"
type="password"
:disabled="isLoading"
:class="{ 'border-red-500': errors.password }"
/>
<span v-if="errors.password" class="text-sm text-red-500">
{{ errors.password }}
</span>
</div>
<Button type="submit" class="w-full" :disabled="isLoading || !meta.valid">
<Loader2 v-if="isLoading" class="mr-2 h-4 w-4 animate-spin" />
Login
</Button>
</form>
</template>
-70
View File
@@ -1,70 +0,0 @@
<script setup lang="ts">
import { Loader2 } from 'lucide-vue-next'
const email = ref('demo@gmail.com')
const password = ref('password')
const isLoading = ref(false)
async function onSubmit(event: Event) {
event.preventDefault()
if (!email.value || !password.value) return
isLoading.value = true
try {
const { data: respData } = await useFetch('/api/v1/authentication/login', {
method: 'POST',
body: JSON.stringify({
name: 'system',
password: 'the-SYSTEM-1234',
}),
})
const resp = respData.value
if (!resp) throw new Error('No response')
const { data: rawdata, meta } = resp
console.log('DATA', rawdata)
console.log('META', meta)
if (meta.status === 'verified') {
await nextTick()
navigateTo('/')
}
} catch (error) {
console.error('Login failed:', error)
} finally {
isLoading.value = false
}
}
</script>
<template>
<form class="grid gap-6" @submit="onSubmit">
<div class="grid gap-2">
<Label for="email"> Email </Label>
<Input
id="email"
v-model="email"
type="email"
placeholder="name@example.com"
:disabled="isLoading"
auto-capitalize="none"
auto-complete="email"
auto-correct="off"
/>
</div>
<div class="grid gap-2">
<div class="flex items-center">
<Label for="password"> Password </Label>
</div>
<Input id="password" v-model="password" type="password" :disabled="isLoading" />
</div>
<Button type="submit" class="w-full" :disabled="isLoading">
<Loader2 v-if="isLoading" class="mr-2 h-4 w-4 animate-spin" />
Login
</Button>
</form>
</template>
<style scoped></style>
+48
View File
@@ -0,0 +1,48 @@
<script setup lang="ts">
import { z } from 'zod'
const loginSchema = z.object({
name: z.string().min(6, 'Please enter a valid username'),
password: z.string().min(6, 'Password must be at least 6 characters'),
})
const { login } = useUserStore()
type LoginFormData = z.infer<typeof loginSchema>
const isLoading = ref(false)
const apiErrors = ref<Record<string, string>>({})
async function onSubmit(data: LoginFormData) {
isLoading.value = true
const result = await xfetch('/api/v1/authentication/login', 'POST', {
name: data.name,
password: data.password,
})
if (result.success) {
const { data: rawdata, meta } = result.body
if (meta.status === 'verified') {
await login(rawdata)
await navigateTo('/')
}
} else {
if (result.errors) {
Object.entries(result.errors).forEach(
([field, errorInfo]: [string, any]) => (apiErrors.value[field] = errorInfo.message),
)
} else {
apiErrors.value.general = result.error?.message || result.message || 'Login failed'
}
}
isLoading.value = false
}
</script>
<template>
<AppAuthLogin :schema="loginSchema" :is-loading="isLoading" @submit="onSubmit" />
</template>
<style scoped></style>