Files
framit/app/pages/contact.vue

124 lines
4.0 KiB
Vue

<template>
<NuxtLayout name="default">
<UPage>
<h1 class="text-4xl text-highlighted font-bold mb-8">
{{ $t('pages.contact.name') }}
</h1>
<UPageCard class="bg-background-100">
<UForm :schema="schema" :state="state" class="space-y-4" @submit="submitContactForm">
<div class="flex flex-row w-full gap-5">
<UFormField
:label="$t('pages.contact.form.labels.name')"
name="name"
class="w-full"
:ui="{ label: 'text-text text-lg text-bold' }"
>
<UInput
v-model="state.name"
autofocus
:ui="{
root: 'relative inline-flex items-center w-full',
base: 'placeholder:text-300',
}"
required
:placeholder="$t('pages.contact.form.placeholders.name')"
/>
</UFormField>
<UFormField
:label="$t('pages.contact.form.labels.email')"
name="email"
class="w-full"
:ui="{ label: 'text-text text-lg text-bold' }"
>
<UInput
v-model="state.email"
type="email"
:ui="{
root: 'relative inline-flex items-center w-full',
base: 'placeholder:text-300',
}"
required
:placeholder="$t('pages.contact.form.placeholders.email')"
/>
</UFormField>
</div>
<UFormField
class="w-full"
name="website"
:label="$t('pages.contact.form.honeypot')"
:ui="{ label: 'text-text text-lg text-bold' }"
>
<UInput
:ui="{ root: 'relative inline-flex items-center w-full', base: 'placeholder:text-300' }"
:placeholder="$t('pages.contact.form.placeholders.honeypot')"
/>
</UFormField>
<UFormField
v-model="state.website"
:label="$t('pages.contact.form.labels.message')"
name="message"
:ui="{ label: 'text-text text-lg text-bold' }"
>
<UTextarea
v-model="state.message"
:ui="{
root: 'relative inline-flex items-center w-full',
base: 'placeholder:text-300',
}"
:placeholder="$t('pages.contact.form.placeholders.message')"
/>
</UFormField>
<UButton
icon="mdi:send-outline"
color="primary"
type="submit"
class="w-full text-center text-lg justify-center-safe"
size="lg"
>
{{ $t('pages.contact.form.sendButton') }}
</UButton>
</UForm>
</UPageCard>
</UPage>
</NuxtLayout>
</template>
<script setup lang="ts">
import type { FormSubmitEvent } from '@nuxt/ui';
import { z } from 'zod';
const { postContact } = useBackend();
const schema = z.object({
email: z.email($t('pages.contact.form.validation.invalidEmail')),
name: z
.string()
.min(1, $t('pages.contact.form.validation.shortName'))
.max(100, $t('pages.contact.form.validation.longName')),
message: z
.string()
.min(10, $t('pages.contact.form.validation.shortMessage'))
.max(5000, $t('pages.contact.form.validation.longMessage')),
website: z.string().optional(),
});
type Schema = z.output<typeof schema>;
const state = reactive<Partial<Schema>>({
name: undefined,
email: undefined,
message: undefined,
website: undefined,
});
const { data: contactResponse, error: contactError, loading, run: sendRequest } = postContact();
const submitContactForm = async (event: FormSubmitEvent<Schema>) => await sendRequest!(event.data);
watchEffect(() => {
if (loading.value) console.log('loading');
if (contactResponse.value) console.log('Response:', contactResponse.value.message);
if (contactError.value) console.error('Error', contactError.value);
});
</script>