154 lines
5.0 KiB
Vue
154 lines
5.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 sr-only"
|
|
name="website"
|
|
:label="$t('pages.contact.form.labels.website')"
|
|
:ui="{ label: 'text-text text-lg text-bold' }"
|
|
tabindex="-1"
|
|
>
|
|
<div>
|
|
If you see this input, you may be using accessibility tools to access this website. This input is meant to
|
|
be hidden to human visitors, but not bots which do not necessarily render the website the way it is meant
|
|
to. Unfortunately, this also affects accessibility tools, such as the ones for visually-impared people. If
|
|
that is indeed, please ignore this input, as it is not meant to be filled by human beings. Filling this
|
|
input will result in a discarded contact form.
|
|
</div>
|
|
<UInput
|
|
v-model="state.website"
|
|
:ui="{ root: 'relative inline-flex items-center w-full', base: 'placeholder:text-300' }"
|
|
:placeholder="$t('pages.contact.form.placeholders.website')"
|
|
tabindex="-1"
|
|
/>
|
|
</UFormField>
|
|
<UFormField
|
|
: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"
|
|
:loading="loading"
|
|
>
|
|
{{ $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';
|
|
|
|
useMeta({
|
|
title: $t('pages.contact.name'),
|
|
description: $t('pages.contact.description'),
|
|
});
|
|
|
|
const toast = useToast();
|
|
|
|
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);
|
|
|
|
watch(contactResponse, async (response) => {
|
|
if (response) {
|
|
toast.add({
|
|
title: response.success ? $t('pages.contact.toast.success') : $t('pages.contact.toast.error'),
|
|
description: $t(response.message),
|
|
color: response.success ? 'info' : 'error',
|
|
});
|
|
}
|
|
});
|
|
watch(contactError, async (response) => {
|
|
if (response) {
|
|
toast.add({
|
|
title: $t('pages.contact.toast.error'),
|
|
description: $t(response.message),
|
|
color: 'error',
|
|
});
|
|
}
|
|
});
|
|
</script>
|