feat(contact): add toast notifications for form feedback

- Add toast notifications for contact form success/error responses
- Add toast notifications for backend errors in AppFooter
- Add accessibility explanation for honeypot field
- Add loading state to contact form submit button
- Add i18n translations for toast messages (en/fr)
- Fix honeypot input missing v-model binding
This commit is contained in:
2026-02-04 15:19:08 +01:00
parent 10e51b5da4
commit 37972aa660
6 changed files with 57 additions and 17 deletions

View File

@@ -43,18 +43,27 @@
</UFormField>
</div>
<UFormField
class="w-full"
class="w-full sr-only"
name="website"
:label="$t('pages.contact.form.honeypot')"
: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.honeypot')"
:placeholder="$t('pages.contact.form.placeholders.website')"
tabindex="-1"
/>
</UFormField>
<UFormField
v-model="state.website"
:label="$t('pages.contact.form.labels.message')"
name="message"
:ui="{ label: 'text-text text-lg text-bold' }"
@@ -74,6 +83,7 @@
type="submit"
class="w-full text-center text-lg justify-center-safe"
size="lg"
:loading="loading"
>
{{ $t('pages.contact.form.sendButton') }}
</UButton>
@@ -86,6 +96,7 @@
<script setup lang="ts">
import type { FormSubmitEvent } from '@nuxt/ui';
import { z } from 'zod';
const toast = useToast();
const { postContact } = useBackend();
@@ -115,9 +126,22 @@ const { data: contactResponse, error: contactError, loading, run: sendRequest }
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);
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>