Undangan/proyek-frontend/app/components/undangan/undangan-minimalis.vue
2025-10-09 14:17:57 +07:00

210 lines
7.9 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="min-h-screen bg-gradient-to-br from-rose-50 via-pink-50 to-purple-50 flex items-center justify-center p-4">
<!-- Main Card -->
<div class="max-w-lg w-full">
<!-- Floating Animation Container -->
<div class="animate-float">
<div class="relative bg-white rounded-3xl shadow-2xl overflow-hidden">
<!-- Decorative Top Wave -->
<div class="absolute top-0 left-0 right-0 h-32 bg-gradient-to-r from-rose-400 to-pink-400 opacity-10">
<svg class="absolute bottom-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320">
<path fill="#ffffff" fill-opacity="1" d="M0,96L48,112C96,128,192,160,288,160C384,160,480,128,576,112C672,96,768,96,864,112C960,128,1056,160,1152,160C1248,160,1344,128,1392,112L1440,96L1440,320L1392,320C1344,320,1248,320,1152,320C1056,320,960,320,864,320C768,320,672,320,576,320C480,320,384,320,288,320C192,320,96,320,48,320L0,320Z"></path>
</svg>
</div>
<!-- Header Image Section -->
<div class="relative h-64 overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-b from-transparent to-white z-10"></div>
<img
:src="imageUrl"
alt="Wedding Template"
class="w-full h-full object-cover transform hover:scale-110 transition-transform duration-700"
/>
<!-- Ornamental Corner -->
<div class="absolute top-4 left-4 w-16 h-16 border-l-4 border-t-4 border-rose-300 rounded-tl-2xl"></div>
<div class="absolute top-4 right-4 w-16 h-16 border-r-4 border-t-4 border-rose-300 rounded-tr-2xl"></div>
</div>
<!-- Content Section -->
<div class="relative px-8 py-10 space-y-8">
<!-- Divider Line -->
<div class="flex items-center justify-center mb-8">
<div class="h-px w-12 bg-gradient-to-r from-transparent to-rose-300"></div>
<div class="mx-4">
<svg class="w-8 h-8 text-rose-400" fill="currentColor" viewBox="0 0 20 20">
<path fill-rule="evenodd" d="M3.172 5.172a4 4 0 015.656 0L10 6.343l1.172-1.171a4 4 0 115.656 5.656L10 17.657l-6.828-6.829a4 4 0 010-5.656z" clip-rule="evenodd"/>
</svg>
</div>
<div class="h-px w-12 bg-gradient-to-l from-transparent to-rose-300"></div>
</div>
<!-- Names -->
<div class="text-center space-y-2">
<h1 class="text-4xl md:text-5xl font-serif font-bold bg-gradient-to-r from-rose-600 to-pink-600 bg-clip-text text-transparent animate-fade-in">
{{ formData.nama_pengantin || 'Undangan Pernikahan' }}
</h1>
<p class="text-gray-500 text-sm tracking-widest uppercase">The Wedding Of</p>
</div>
<!-- Date Section -->
<div class="bg-gradient-to-r from-rose-50 to-pink-50 rounded-2xl p-6 shadow-inner transform hover:scale-105 transition-transform duration-300">
<div class="flex items-center justify-center space-x-3 mb-2">
<svg class="w-6 h-6 text-rose-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
</svg>
<h2 class="text-lg font-semibold text-gray-700">Save The Date</h2>
</div>
<p class="text-center text-2xl font-serif text-gray-800">
{{ formatDate(formData.tanggal_acara) || 'Tanggal belum ditentukan' }}
</p>
</div>
<!-- Location Section -->
<div class="bg-gradient-to-r from-purple-50 to-pink-50 rounded-2xl p-6 shadow-inner transform hover:scale-105 transition-transform duration-300">
<div class="flex items-center justify-center space-x-3 mb-2">
<svg class="w-6 h-6 text-purple-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
<h2 class="text-lg font-semibold text-gray-700">Lokasi Acara</h2>
</div>
<p class="text-center text-xl text-gray-800 font-medium">
{{ formData.lokasi || 'Lokasi belum ditentukan' }}
</p>
</div>
<!-- Decorative Quote -->
<div class="text-center py-4">
<p class="text-sm text-gray-400 italic font-serif">
"Cinta adalah persahabatan yang telah terbakar"
</p>
</div>
<!-- Footer Badge -->
<div class="flex items-center justify-center pt-4">
<div class="bg-gradient-to-r from-rose-100 to-pink-100 px-6 py-2 rounded-full">
<p class="text-xs text-gray-600 font-medium">
{{ data.template?.nama_template }}
<span class="uppercase">{{ data.template?.paket }}</span>
</p>
</div>
</div>
</div>
<!-- Decorative Bottom Corners -->
<div class="absolute bottom-4 left-4 w-16 h-16 border-l-4 border-b-4 border-rose-300 rounded-bl-2xl"></div>
<div class="absolute bottom-4 right-4 w-16 h-16 border-r-4 border-b-4 border-rose-300 rounded-br-2xl"></div>
</div>
</div>
<!-- Floating Hearts Animation -->
<div class="fixed inset-0 pointer-events-none overflow-hidden -z-10">
<div class="heart-float" style="left: 10%; animation-delay: 0s;"></div>
<div class="heart-float" style="left: 30%; animation-delay: 2s;">💕</div>
<div class="heart-float" style="left: 50%; animation-delay: 4s;">💖</div>
<div class="heart-float" style="left: 70%; animation-delay: 1s;">💗</div>
<div class="heart-float" style="left: 90%; animation-delay: 3s;">💝</div>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { useRuntimeConfig } from '#app'
const props = defineProps({
data: {
type: Object,
required: true,
validator: (data) => {
return data && typeof data === 'object' && 'template' in data
},
},
})
const config = useRuntimeConfig()
const backendUrl = config.public.apiBaseUrl
const formData = computed(() => props.data.form || {})
const imageUrl = computed(() => {
const foto = props.data.template?.foto
return foto
? `${backendUrl}/storage/${foto}`
: 'https://images.unsplash.com/photo-1519741497674-611481863552?w=800&h=600&fit=crop'
})
const formatDate = (dateString) => {
if (!dateString) return null
try {
const date = new Date(dateString)
if (isNaN(date.getTime())) return null
return date.toLocaleDateString('id-ID', {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
})
} catch (error) {
console.error('Error formatting date:', error)
return null
}
}
</script>
<style scoped>
@keyframes float {
0%, 100% {
transform: translateY(0px);
}
50% {
transform: translateY(-20px);
}
}
@keyframes fade-in {
from {
opacity: 0;
transform: translateY(-10px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes heart-float {
0% {
transform: translateY(100vh) rotate(0deg);
opacity: 0;
}
10% {
opacity: 1;
}
90% {
opacity: 1;
}
100% {
transform: translateY(-100vh) rotate(360deg);
opacity: 0;
}
}
.animate-float {
animation: float 6s ease-in-out infinite;
}
.animate-fade-in {
animation: fade-in 1s ease-out;
}
.heart-float {
position: absolute;
font-size: 1.5rem;
animation: heart-float 15s linear infinite;
bottom: -50px;
}
</style>