feat: working form
This commit is contained in:
+37
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -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
@@ -1,56 +1,41 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { toTypedSchema } from "@vee-validate/zod";
|
import { toTypedSchema } from '@vee-validate/zod'
|
||||||
import { useForm } from "vee-validate";
|
import { useForm } from 'vee-validate'
|
||||||
import z from "zod";
|
import { ref } from 'vue'
|
||||||
|
import FormField from './FormField.vue'
|
||||||
|
import { loginSchema, type LoginForm as LoginFormData } from '../schemas/login'
|
||||||
|
|
||||||
defineProps<{
|
const props = defineProps<{
|
||||||
email: string;
|
email: string
|
||||||
}>();
|
error?: string
|
||||||
|
}>()
|
||||||
|
|
||||||
interface Form {
|
const form = ref<HTMLFormElement>()
|
||||||
email: string;
|
|
||||||
password: string;
|
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>({
|
form.value?.submit()
|
||||||
initialValues: {
|
})
|
||||||
email: "",
|
|
||||||
password: "",
|
|
||||||
},
|
|
||||||
validationSchema: toTypedSchema(
|
|
||||||
z.object({
|
|
||||||
email: z.email(),
|
|
||||||
password: z.string().min(8),
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
const onSubmit = handleSubmit(async (data) => {
|
|
||||||
console.log(data);
|
|
||||||
});
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<form
|
<form ref="form" method="post" class="container mx-auto p-4 flex flex-col gap-4" @submit="onSubmit">
|
||||||
method="post"
|
<div v-if="error" class="alert alert-error">{{ error }}</div>
|
||||||
class="container mx-auto p-4 flex flex-col gap-4"
|
<FormField type="email" name="email" label="E-Mail" required />
|
||||||
@submit.prevent="onSubmit"
|
<FormField type="password" name="password" label="Password" required />
|
||||||
>
|
|
||||||
<input
|
|
||||||
type="email"
|
|
||||||
name="email"
|
|
||||||
class="input"
|
|
||||||
placeholder="E-Mail"
|
|
||||||
required
|
|
||||||
:value="email"
|
|
||||||
/>
|
|
||||||
<input
|
|
||||||
type="password"
|
|
||||||
name="password"
|
|
||||||
class="input"
|
|
||||||
placeholder="Password"
|
|
||||||
required
|
|
||||||
/>
|
|
||||||
<button type="submit" class="btn btn-primary self-start">Sign in</button>
|
<button type="submit" class="btn btn-primary self-start">Sign in</button>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
+20
-11
@@ -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 email = ''
|
||||||
let error = "";
|
let error = ''
|
||||||
|
|
||||||
if (Astro.request.method === "POST") {
|
if (Astro.request.method === 'POST') {
|
||||||
const formData = await Astro.request.formData();
|
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) {
|
if (!result.success) {
|
||||||
error = "E-Mail shouldn't be empty.";
|
error = result.error.issues[0]?.message ?? 'Invalid form data.'
|
||||||
|
} else {
|
||||||
|
email = result.data.email
|
||||||
|
console.log('POST DATA', result.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
---
|
---
|
||||||
|
|
||||||
<Layout>
|
<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>
|
</Layout>
|
||||||
|
|||||||
@@ -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>
|
||||||
Reference in New Issue
Block a user