feat(landing): Add newsletter double-opt-in
This commit is contained in:
170
landing/app/pages/newsletter-bestaetigt.vue
Normal file
170
landing/app/pages/newsletter-bestaetigt.vue
Normal file
@@ -0,0 +1,170 @@
|
||||
<template>
|
||||
<div class="min-h-screen pt-24 pb-16 flex items-center">
|
||||
<!-- Background with gradient -->
|
||||
<div class="fixed inset-0 -z-10">
|
||||
<div
|
||||
class="absolute inset-0 bg-linear-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"
|
||||
/>
|
||||
<!-- Gradient orbs -->
|
||||
<div class="absolute top-20 left-1/4 w-96 h-96 bg-primary-400/20 rounded-full blur-3xl animate-orb-float" />
|
||||
<div
|
||||
class="absolute bottom-20 right-1/4 w-80 h-80 bg-accent-400/20 rounded-full blur-3xl animate-orb-float"
|
||||
style="animation-delay: 3s"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="relative max-w-2xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<!-- Success card -->
|
||||
<div class="glass rounded-3xl p-10 sm:p-14 shadow-2xl animate-fade-in-up">
|
||||
<!-- Checkmark icon with animation -->
|
||||
<div class="relative mb-8">
|
||||
<div
|
||||
class="w-24 h-24 mx-auto rounded-full bg-success-100 dark:bg-success-900/30 flex items-center justify-center animate-scale-in"
|
||||
>
|
||||
<UIcon name="i-lucide-check-circle" class="w-14 h-14 text-success-600 dark:text-success-400" />
|
||||
</div>
|
||||
<!-- Decorative rings -->
|
||||
<div
|
||||
class="absolute inset-0 w-24 h-24 mx-auto rounded-full border-2 border-success-400/30 animate-ping-slow"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Title -->
|
||||
<h1
|
||||
class="font-heading text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white mb-4 animate-fade-in-up"
|
||||
style="animation-delay: 200ms"
|
||||
>
|
||||
{{ $t('newsletterConfirmed.title') }}
|
||||
</h1>
|
||||
|
||||
<!-- Description -->
|
||||
<p
|
||||
class="text-lg text-gray-600 dark:text-gray-300 mb-8 animate-fade-in-up"
|
||||
style="animation-delay: 300ms"
|
||||
>
|
||||
{{ $t('newsletterConfirmed.description') }}
|
||||
</p>
|
||||
|
||||
<!-- CTA Button -->
|
||||
<div class="animate-fade-in-up" style="animation-delay: 400ms">
|
||||
<UButton
|
||||
to="/"
|
||||
size="xl"
|
||||
class="btn-gradient rounded-xl font-semibold shadow-lg shadow-primary-500/25 hover:shadow-primary-500/40 transition-shadow"
|
||||
>
|
||||
<UIcon name="i-lucide-home" class="w-5 h-5 mr-2" />
|
||||
{{ $t('newsletterConfirmed.backToHome') }}
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Trust indicators -->
|
||||
<div class="mt-8 flex flex-wrap justify-center gap-6 animate-fade-in-up" style="animation-delay: 500ms">
|
||||
<div class="flex items-center gap-2 text-sm 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-sm 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-bell-off" 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>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
const { t, locale } = useI18n()
|
||||
|
||||
// SEO Meta
|
||||
useSeoMeta({
|
||||
title: () => t('newsletterConfirmed.meta.title'),
|
||||
description: () => t('newsletterConfirmed.meta.description'),
|
||||
ogTitle: () => t('newsletterConfirmed.meta.title'),
|
||||
ogDescription: () => t('newsletterConfirmed.meta.description'),
|
||||
ogImage: '/og-image.png',
|
||||
ogType: 'website',
|
||||
twitterCard: 'summary_large_image',
|
||||
robots: 'noindex, nofollow'
|
||||
})
|
||||
|
||||
// Set language
|
||||
useHead({
|
||||
htmlAttrs: {
|
||||
lang: () => locale.value
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* Orb float animation */
|
||||
@keyframes orb-float {
|
||||
0%,
|
||||
100% {
|
||||
transform: translateY(0) scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: translateY(-20px) scale(1.05);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-orb-float {
|
||||
animation: orb-float 8s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* Fade in up animation */
|
||||
@keyframes fade-in-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in-up {
|
||||
animation: fade-in-up 0.6s ease-out forwards;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
/* Scale in animation for checkmark */
|
||||
@keyframes scale-in {
|
||||
0% {
|
||||
transform: scale(0);
|
||||
opacity: 0;
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-scale-in {
|
||||
animation: scale-in 0.5s ease-out forwards;
|
||||
}
|
||||
|
||||
/* Slow ping animation for decorative ring */
|
||||
@keyframes ping-slow {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
opacity: 0.5;
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.5);
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.animate-ping-slow {
|
||||
animation: ping-slow 2s ease-out infinite;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user