feat: working form

This commit is contained in:
2026-09-15 00:40:54 +02:00
parent f6ba8f46d6
commit 2f9cfd3f1a
5 changed files with 110 additions and 54 deletions
+37
View File
@@ -0,0 +1,37 @@
{
"arrowParens": "always",
"bracketSpacing": true,
"endOfLine": "lf",
"htmlWhitespaceSensitivity": "css",
"insertPragma": false,
"singleAttributePerLine": false,
"bracketSameLine": false,
"jsxBracketSameLine": false,
"jsxSingleQuote": true,
"printWidth": 120,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"requirePragma": false,
"semi": false,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "es5",
"useTabs": false,
"embeddedLanguageFormatting": "auto",
"vueIndentScriptAndStyle": false,
"experimentalTernaries": false,
"overrides": [
{
"files": "*.ts",
"options": {
"parser": "typescript"
}
},
{
"files": "*.vue",
"options": {
"parser": "vue"
}
}
]
}
+17
View File
@@ -0,0 +1,17 @@
<script setup lang="ts">
import { ErrorMessage, Field } from 'vee-validate'
defineProps<{
type: 'text' | 'email' | 'password'
name: string
label: string
required?: boolean
}>()
</script>
<template>
<div class="flex flex-col gap-1">
<Field :type="type" :name="name" class="input" :placeholder="label" :required="required" />
<ErrorMessage :name="name" as="span" class="text-error" />
</div>
</template>
+30 -45
View File
@@ -1,56 +1,41 @@
<script setup lang="ts">
import { toTypedSchema } from "@vee-validate/zod";
import { useForm } from "vee-validate";
import z from "zod";
import { toTypedSchema } from '@vee-validate/zod'
import { useForm } from 'vee-validate'
import { ref } from 'vue'
import FormField from './FormField.vue'
import { loginSchema, type LoginForm as LoginFormData } from '../schemas/login'
defineProps<{
email: string;
}>();
const props = defineProps<{
email: string
error?: string
}>()
interface Form {
email: string;
password: string;
const form = ref<HTMLFormElement>()
const { handleSubmit } = useForm<LoginFormData>({
initialValues: {
email: props.email,
password: '',
},
validationSchema: toTypedSchema(loginSchema),
})
const onSubmit = handleSubmit((data) => {
const emailInput = form.value?.elements.namedItem('email')
if (emailInput instanceof HTMLInputElement) {
emailInput.value = data.email
}
const { handleSubmit } = useForm<Form>({
initialValues: {
email: "",
password: "",
},
validationSchema: toTypedSchema(
z.object({
email: z.email(),
password: z.string().min(8),
}),
),
});
const onSubmit = handleSubmit(async (data) => {
console.log(data);
});
form.value?.submit()
})
</script>
<template>
<form
method="post"
class="container mx-auto p-4 flex flex-col gap-4"
@submit.prevent="onSubmit"
>
<input
type="email"
name="email"
class="input"
placeholder="E-Mail"
required
:value="email"
/>
<input
type="password"
name="password"
class="input"
placeholder="Password"
required
/>
<form ref="form" method="post" class="container mx-auto p-4 flex flex-col gap-4" @submit="onSubmit">
<div v-if="error" class="alert alert-error">{{ error }}</div>
<FormField type="email" name="email" label="E-Mail" required />
<FormField type="password" name="password" label="Password" required />
<button type="submit" class="btn btn-primary self-start">Sign in</button>
</form>
</template>
+20 -11
View File
@@ -1,23 +1,32 @@
---
import Layout from "../layouts/layout.astro";
import LoginForm from "../islands/LoginForm.vue";
import LoginForm from '../islands/LoginForm.vue'
import Layout from '../layouts/layout.astro'
import { loginSchema } from '../schemas/login'
let email = "";
let error = "";
let email = ''
let error = ''
if (Astro.request.method === "POST") {
const formData = await Astro.request.formData();
if (Astro.request.method === 'POST') {
const formData = await Astro.request.formData()
const input = {
email: formData.get('email'),
password: formData.get('password'),
}
const result = loginSchema.safeParse(input)
email = formData.get("email")?.toString() ?? "";
email = typeof input.email === 'string' ? input.email : ''
if (!email) {
error = "E-Mail shouldn't be empty.";
if (!result.success) {
error = result.error.issues[0]?.message ?? 'Invalid form data.'
} else {
email = result.data.email
console.log('POST DATA', result.data)
}
}
---
<Layout>
<h1 class="text-2xl font-bold">Sign in</h1>
<h1 class='text-2xl font-bold'>Sign in</h1>
<LoginForm client:load email={email} />
<LoginForm client:load email={email} error={error} />
</Layout>
+8
View File
@@ -0,0 +1,8 @@
import z from 'zod'
export const loginSchema = z.object({
email: z.string().trim().pipe(z.email()),
password: z.string().min(8),
})
export type LoginForm = z.infer<typeof loginSchema>