Update contact form
All checks were successful
Build and deploy updated apps / Build & deploy (push) Successful in 1m49s

This commit is contained in:
Dominik Milacher 2025-10-15 10:04:43 +02:00
parent cbfab733b7
commit f6e88469b3
4 changed files with 84 additions and 47 deletions

View File

@ -22,6 +22,7 @@ const matrix: ContentMatrix = {
}
const business: BusinessInfo = {
uid: 'panoramablick-saalbach.at',
name: {
de: 'Landhaus Panoramablick',
en: 'Guesthouse Panoramablick'
@ -485,7 +486,6 @@ export default defineAppConfig({
contact: {
title: {
de: 'Kontakt aufnehmen',
'de@winter': 'Winterkontakt',
en: 'Contact us'
},
description: {
@ -508,24 +508,68 @@ export default defineAppConfig({
},
form: {
name: {
prompt: {
de: 'Ihr Name',
en: 'Your name'
},
invalid: {
de: 'Name zu kurz',
en: 'Name too short'
}
},
email: {
prompt: {
de: 'Ihre E-Mail',
en: 'Your email address'
},
invalid: {
de: 'E-Mail Adresse nicht gültig',
en: 'Email address not valid'
}
},
subject: {
prompt: {
de: 'Betreff',
en: 'Subject'
},
invalid: {
de: 'Betreff zu kurz',
en: 'Subject too short'
}
},
message: {
prompt: {
de: 'Ihre Anfrage',
en: 'Your inquiry'
},
invalid: {
de: 'Nachricht zu kurz',
en: 'Message too short'
}
},
send: {
de: 'Senden',
en: 'Send'
},
sent: {
title: {
de: 'Nachricht gesendet',
en: 'Message sent'
},
description: {
de: 'Vielen Dank - wir melden uns bald.',
en: 'Thank you - we\'ll be in touch soon.'
}
},
error: {
title: {
de: 'Fehler',
en: 'Error'
},
description: {
de: 'Die Nachricht konnte nicht versendet werden - bitte versuchen Sie es erneut.',
en: 'The message could not be sent - please try again.'
}
}
},
heroes: {
@ -545,7 +589,7 @@ export default defineAppConfig({
},
image: '/family/sabrina-daniel.webp'
}
}
},
},
apartments: {
'highlight': {

View File

@ -10,7 +10,6 @@ const { add } = useToast()
const shown = useCookie('cookie-toast-shown', { maxAge: 60 * 60 * 24 * 7 })
onMounted(() => {
console.log("MIAU", c.value)
if (!shown.value) {
add({
title: c.value.cookies.title,

View File

@ -45,23 +45,23 @@
</p>
<!-- Form -->
<UForm :state="state" class="space-y-4" @submit="onSubmit">
<UForm :state="state" :schema="schema" class="space-y-4" @submit="onSubmit">
<UFormField name="name" label="Name" :ui="{ label: 'sr-only' }">
<UInput v-model="state.name" class="w-full" :placeholder="c.contact.form.name"/>
<UInput v-model="state.name" class="w-full" :placeholder="c.contact.form.name.prompt"/>
</UFormField>
<UFormField name="email" label="E-Mail" :ui="{ label: 'sr-only' }">
<UInput v-model="state.email" type="email" class="w-full"
:placeholder="c.contact.form.email"/>
:placeholder="c.contact.form.email.prompt"/>
</UFormField>
<UFormField name="subject" label="Betreff" :ui="{ label: 'sr-only' }">
<UInput v-model="state.subject" class="w-full" :placeholder="c.contact.form.subject"/>
<UInput v-model="state.subject" class="w-full" :placeholder="c.contact.form.subject.prompt"/>
</UFormField>
<UFormField name="message" label="Nachricht" :ui="{ label: 'sr-only' }">
<UTextarea v-model="state.message" :rows="6" class="w-full"
:placeholder="c.contact.form.message"/>
:placeholder="c.contact.form.message.prompt"/>
</UFormField>
<UButton type="submit" color="primary" size="lg" class="w-full sm:w-auto" trailing-icon="i-heroicons-paper-airplane">
@ -103,16 +103,16 @@ import * as v from 'valibot'
import type {FormSubmitEvent} from '@nuxt/ui'
/* ───── validation schema ───── */
const schema = v.object({
name: v.pipe(v.string(), v.minLength(2, 'Bitte Namen eingeben')),
email: v.pipe(v.string(), v.email('Ungültige E-Mail')),
subject: v.pipe(v.string(), v.minLength(3, 'Betreff fehlt')),
message: v.pipe(v.string(), v.minLength(10, 'Nachricht ist zu kurz'))
})
type Schema = v.InferOutput<typeof schema>
const schema = computed(() => v.object({
name: v.pipe(v.string(), v.minLength(2, c.value.contact.form.name.invalid)),
email: v.pipe(v.string(), v.email(c.value.contact.form.email.invalid)),
subject: v.pipe(v.string(), v.minLength(3, c.value.contact.form.subject.invalid)),
message: v.pipe(v.string(), v.minLength(10, c.value.contact.form.message.invalid))
}))
//type Schema = v.InferOutput<typeof schema>
/* ───── reactive form state ───── */
const state = reactive<Schema>({
const state = reactive({
name: '', email: '', subject: '', message: ''
})
@ -120,17 +120,8 @@ const toast = useToast()
/* ───── submit handler ───── */
async function onSubmit(event: FormSubmitEvent<Schema>) {
const config = useRuntimeConfig()
const hotelId = config.public.hotelId
if (!hotelId) {
toast.add({
title: 'Fehler',
description: 'Hotel-ID ist nicht konfiguriert!',
color: 'primary'
})
throw new Error('Hotel ID not configured')
}
const config = useAppConfig()
const hotelId = config.content.business.uid ?? ''
try {
await $fetch('https://api.dominikmilacher.com/contact', {
@ -143,17 +134,19 @@ async function onSubmit(event: FormSubmitEvent<Schema>) {
})
toast.add({
title: 'Nachricht gesendet',
description: 'Vielen Dank wir melden uns bald.',
title: c.value.contact.form.sent.title,
description: c.value.contact.form.sent.description,
color: 'primary'
})
/* reset fields */
Object.assign(state, {name: '', email: '', subject: '', message: ''})
} catch (err: any) {
//console.log(err?.data?.detail)
//console.log(err?.message)
toast.add({
title: 'Fehler',
description: err?.data?.detail ?? err?.message ?? 'Nachricht konnte nicht gesendet werden.',
title: c.value.contact.form.error.title,
description: c.value.contact.form.error.description,
color: 'primary'
})
}

View File

@ -30,13 +30,14 @@ export interface ContentMatrix {
}
export interface BusinessInfo {
name: Translations,
operator: Translations,
address: Translations,
phone: Translations,
email: Translations,
vat: Translations,
authority: Translations,
membership: Translations,
uid: string
name: Translations
operator: Translations
address: Translations
phone: Translations
email: Translations
vat: Translations
authority: Translations
membership: Translations
regulation: Translations
}