Files
gremiumhub/landing/app/components/landing/NewsletterSignup.vue

188 lines
7.5 KiB
Vue

<template>
<section id="newsletter" class="relative py-16 lg:py-20 overflow-hidden scroll-mt-20">
<!-- Background with gradient and particles -->
<div
class="absolute inset-0 bg-gradient-to-br from-primary-50 via-cyan-50 to-accent-50 dark:from-gray-950 dark:via-primary-950/30 dark:to-accent-950/30"
/>
<!-- Animated particles -->
<div class="absolute inset-0 overflow-hidden pointer-events-none">
<div class="particle" />
<div class="particle" />
<div class="particle" />
<div class="particle" />
<div class="particle" />
<div class="particle" />
<div class="particle" />
<div class="particle" />
</div>
<!-- Gradient orbs -->
<div class="absolute top-0 left-1/4 w-96 h-96 bg-primary-400/20 rounded-full blur-3xl animate-orb-float" />
<div
class="absolute bottom-0 right-1/4 w-80 h-80 bg-accent-400/20 rounded-full blur-3xl animate-orb-float"
style="animation-delay: 3s"
/>
<div class="relative z-10 max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<!-- Glass card -->
<div class="max-w-2xl mx-auto">
<div class="glass rounded-3xl p-8 sm:p-12 shadow-2xl">
<!-- Icon -->
<div class="flex justify-center mb-6">
<div
class="w-16 h-16 rounded-2xl bg-gradient-to-br from-primary-500 to-cyan-500 flex items-center justify-center animate-float-slow shadow-lg shadow-primary-500/25"
>
<UIcon name="i-lucide-mail" class="w-8 h-8 text-white" />
</div>
</div>
<!-- Title -->
<h2
class="font-heading text-3xl sm:text-4xl font-bold text-center text-gray-900 dark:text-white mb-4 animate-fade-in-up"
>
{{ $t('newsletter.title', { highlight: '' })
}}<span class="gradient-text">{{ $t('newsletter.titleHighlight') }}</span>
</h2>
<!-- Description -->
<p
class="text-center text-lg text-gray-600 dark:text-gray-300 mb-8 animate-fade-in-up"
style="animation-delay: 100ms"
>
{{ $t('newsletter.description') }}
</p>
<!-- Form -->
<UForm
:state="formState"
:schema="schema"
class="animate-fade-in-up"
style="animation-delay: 200ms"
@submit="onSubmit"
>
<div class="flex flex-col sm:flex-row gap-3">
<UFormField name="email" class="flex-1">
<UInput
v-model="formState.email"
type="email"
:placeholder="$t('newsletter.placeholder')"
size="xl"
:disabled="isLoading || isSuccess"
:ui="{
root: 'w-full',
base: 'rounded-xl bg-white dark:bg-gray-900 border-gray-200 dark:border-gray-700 focus:ring-2 focus:ring-primary-500 focus:border-transparent'
}"
>
<template #leading>
<UIcon name="i-lucide-mail" class="w-5 h-5 text-gray-400" />
</template>
</UInput>
</UFormField>
<UButton
type="submit"
size="xl"
:loading="isLoading"
:disabled="isSuccess"
class="btn-gradient px-8 rounded-xl font-semibold shadow-lg shadow-primary-500/25 whitespace-nowrap"
>
<template v-if="isSuccess">
<UIcon name="i-lucide-check" class="w-5 h-5 mr-2" />
<span>{{ $t('newsletter.submitted') }}</span>
</template>
<template v-else>
<span>{{ $t('newsletter.submit') }}</span>
</template>
</UButton>
</div>
</UForm>
<!-- Success message with animation -->
<Transition
enter-active-class="transition-all duration-500 ease-out"
enter-from-class="opacity-0 scale-95 translate-y-4"
enter-to-class="opacity-100 scale-100 translate-y-0"
leave-active-class="transition-all duration-300 ease-in"
leave-from-class="opacity-100 scale-100 translate-y-0"
leave-to-class="opacity-0 scale-95 translate-y-4"
>
<div
v-if="isSuccess"
class="mt-6 p-4 rounded-xl bg-success-100 dark:bg-success-900/30 border border-success-200 dark:border-success-800"
>
<div class="flex items-center justify-center gap-3 text-success-700 dark:text-success-300">
<div class="w-8 h-8 rounded-full bg-success-500 flex items-center justify-center">
<UIcon name="i-lucide-check" class="w-5 h-5 text-white" />
</div>
<span class="font-medium">{{ $t('newsletter.success') }}</span>
</div>
</div>
</Transition>
<!-- Privacy note -->
<p
class="mt-6 text-sm text-center text-gray-500 dark:text-gray-400 animate-fade-in-up"
style="animation-delay: 300ms"
>
<i18n-t keypath="newsletter.privacyNote" tag="span">
<template #link>
<NuxtLink to="/datenschutz" class="text-primary-600 dark:text-primary-400 hover:underline font-medium">
{{ $t('newsletter.privacyLink') }}
</NuxtLink>
</template>
</i18n-t>
</p>
<!-- Trust indicators -->
<div
class="mt-8 flex flex-wrap justify-center gap-6 text-sm animate-fade-in-up"
style="animation-delay: 400ms"
>
<div class="flex items-center gap-2 text-gray-600 dark:text-gray-300">
<div class="w-6 h-6 rounded-full bg-success-100 dark:bg-success-900/30 flex items-center justify-center">
<UIcon name="i-lucide-shield-check" class="w-3.5 h-3.5 text-success-600 dark:text-success-400" />
</div>
<span>{{ $t('newsletter.trust.gdpr') }}</span>
</div>
<div class="flex items-center gap-2 text-gray-600 dark:text-gray-300">
<div class="w-6 h-6 rounded-full bg-success-100 dark:bg-success-900/30 flex items-center justify-center">
<UIcon name="i-lucide-lock" class="w-3.5 h-3.5 text-success-600 dark:text-success-400" />
</div>
<span>{{ $t('newsletter.trust.encrypted') }}</span>
</div>
<div class="flex items-center gap-2 text-gray-600 dark:text-gray-300">
<div class="w-6 h-6 rounded-full bg-success-100 dark:bg-success-900/30 flex items-center justify-center">
<UIcon name="i-lucide-x-circle" class="w-3.5 h-3.5 text-success-600 dark:text-success-400" />
</div>
<span>{{ $t('newsletter.trust.noSpam') }}</span>
</div>
</div>
</div>
</div>
</div>
</section>
</template>
<script setup lang="ts">
import { z } from 'zod'
import type { FormSubmitEvent } from '@nuxt/ui'
const { t } = useI18n()
const { isLoading, isSuccess, submitEmail } = useNewsletterSignup()
const schema = computed(() =>
z.object({
email: z.string().min(1, t('newsletter.validation.required')).email(t('newsletter.validation.invalid'))
})
)
const formState = reactive<{ email: string }>({
email: ''
})
async function onSubmit(event: FormSubmitEvent<{ email: string }>) {
await submitEmail(event.data.email)
}
</script>