Undangan/proyek-frontend/app/components/templates/wedding/WeddingA.vue
2025-10-07 10:36:44 +07:00

630 lines
27 KiB
Vue

<!-- components/invitation/templates/wedding/WeddingA.vue -->
<template>
<div class="wedding-template-a min-h-screen bg-gradient-to-b from-rose-50 to-white">
<!-- Opening Cover -->
<section v-if="!isOpened" class="fixed inset-0 z-50 flex items-center justify-center bg-cover bg-center"
:style="{ backgroundImage: `url(${data.coverImage || '/wedding1.png'})` }">
<div class="absolute inset-0 bg-black/40"></div>
<div class="relative text-center text-white p-8">
<p class="text-sm uppercase tracking-widest mb-4 animate-fade-in">The Wedding of</p>
<h1 class="text-5xl md:text-7xl font-serif mb-6 animate-slide-up">
{{ data.bride.nickname }} & {{ data.groom.nickname }}
</h1>
<p class="text-lg mb-8 animate-fade-in-delay">{{ formatDate(data.eventDate) }}</p>
<button @click="openInvitation"
class="px-8 py-3 bg-white text-rose-600 rounded-full font-semibold hover:bg-rose-50 transition-all duration-300 animate-pulse-slow">
<Icon name="mdi:envelope-open-outline" class="mr-2" />
Buka Undangan
</button>
</div>
</section>
<!-- Main Content -->
<div v-show="isOpened" class="animate-fade-in">
<!-- Hero Section -->
<section class="relative h-screen flex items-center justify-center overflow-hidden">
<div class="absolute inset-0 bg-cover bg-center"
:style="{ backgroundImage: `url(${data.heroImage || '/wedding1.png'})` }">
<div class="absolute inset-0 bg-gradient-to-b from-transparent via-black/20 to-black/40"></div>
</div>
<div class="relative text-center text-white px-4 z-10">
<p class="text-sm uppercase tracking-widest mb-4" data-aos="fade-down">
{{ data.greeting || 'Dengan Memohon Rahmat dan Ridho Allah SWT' }}
</p>
<h2 class="text-4xl md:text-6xl font-serif mb-4" data-aos="zoom-in">
{{ data.bride.nickname }} & {{ data.groom.nickname }}
</h2>
<div class="w-24 h-0.5 bg-white mx-auto mb-4" data-aos="zoom-in" data-aos-delay="200"></div>
<p class="text-lg" data-aos="fade-up" data-aos-delay="300">
{{ formatDate(data.eventDate) }}
</p>
</div>
<!-- Scroll Indicator -->
<div class="absolute bottom-8 left-1/2 transform -translate-x-1/2 animate-bounce">
<Icon name="mdi:chevron-double-down" class="text-white text-3xl" />
</div>
</section>
<!-- Couple Section -->
<section class="py-20 bg-white rounded-2xl shadow-lg max-w-5xl mx-auto px-6">
<div class="text-center mb-12" data-aos="fade-up">
<h2 class="text-3xl md:text-4xl font-bold text-yellow-600 mb-4">Meet The Happy Couple</h2>
<p class="text-gray-600 max-w-2xl mx-auto">
Glory be to Allah SWT who has created creatures in pairs. Ya Allah,
please accept and bless us
</p>
</div>
<div class="grid md:grid-cols-2 gap-12 items-center">
<!-- Groom -->
<div class="text-center" data-aos="fade-right">
<div class="relative inline-block mb-6">
<div
class="w-40 h-40 md:w-48 md:h-48 rounded-full border-4 border-yellow-400 mx-auto flex items-center justify-center overflow-hidden">
<img :src="data.groom.photo || '/pria.jpg'" :alt="data.groom.fullname"
class="w-full h-full object-cover" />
</div>
<!-- Ornament -->
<div class="absolute bottom-0 left-1/2 -translate-x-1/2 translate-y-4">
<Icon name="mdi:flower" class="text-yellow-500 text-5xl" />
</div>
</div>
<h3 class="text-2xl font-[GreatVibes] text-yellow-600 mb-2">{{ data.groom.fullname }}</h3>
<p class="text-gray-600">Son of</p>
<p class="text-gray-700 font-medium">
{{ data.groom.fatherName }} & {{ data.groom.motherName }}
</p>
<div class="flex justify-center mt-4 space-x-4">
<a v-if="data.groom.instagram" :href="`https://instagram.com/${data.groom.instagram}`"
target="_blank">
<Icon name="mdi:instagram"
class="text-yellow-600 text-2xl hover:text-yellow-700 transition-colors" />
</a>
<a v-if="data.groom.twitter" :href="`https://twitter.com/${data.groom.twitter}`"
target="_blank">
<Icon name="mdi:twitter"
class="text-yellow-600 text-2xl hover:text-yellow-700 transition-colors" />
</a>
<a v-if="data.groom.facebook" :href="`https://facebook.com/${data.groom.facebook}`"
target="_blank">
<Icon name="mdi:facebook"
class="text-yellow-600 text-2xl hover:text-yellow-700 transition-colors" />
</a>
</div>
</div>
<!-- Bride -->
<div class="text-center" data-aos="fade-left">
<div class="relative inline-block mb-6">
<div
class="w-40 h-40 md:w-48 md:h-48 rounded-full border-4 border-yellow-400 mx-auto flex items-center justify-center overflow-hidden">
<img :src="data.bride.photo || '/wanita.jpg'" :alt="data.bride.fullname"
class="w-full h-full object-cover" />
</div>
<!-- Ornament -->
<div class="absolute bottom-0 left-1/2 -translate-x-1/2 translate-y-4">
<Icon name="mdi:flower" class="text-yellow-500 text-5xl" />
</div>
</div>
<h3 class="text-2xl font-[GreatVibes] text-yellow-600 mb-2">{{ data.bride.fullname }}</h3>
<p class="text-gray-600">Daughter of</p>
<p class="text-gray-700 font-medium">
{{ data.bride.fatherName }} & {{ data.bride.motherName }}
</p>
<div class="flex justify-center mt-4 space-x-4">
<a v-if="data.bride.instagram" :href="`https://instagram.com/${data.bride.instagram}`"
target="_blank">
<Icon name="mdi:instagram"
class="text-yellow-600 text-2xl hover:text-yellow-700 transition-colors" />
</a>
<a v-if="data.bride.twitter" :href="`https://twitter.com/${data.bride.twitter}`"
target="_blank">
<Icon name="mdi:twitter"
class="text-yellow-600 text-2xl hover:text-yellow-700 transition-colors" />
</a>
<a v-if="data.bride.facebook" :href="`https://facebook.com/${data.bride.facebook}`"
target="_blank">
<Icon name="mdi:facebook"
class="text-yellow-600 text-2xl hover:text-yellow-700 transition-colors" />
</a>
</div>
</div>
</div>
<!-- Our Story Button -->
<div class="text-center mt-12">
<button
class="bg-yellow-500 hover:bg-yellow-600 text-white px-6 py-3 rounded-md font-medium transition-colors">
Our Story
</button>
</div>
</section>
<!-- Event Details -->
<section class="py-20 bg-rose-50">
<div class="max-w-4xl mx-auto px-4">
<div class="text-center mb-12" data-aos="fade-up">
<h2 class="text-3xl md:text-4xl font-serif text-rose-800 mb-4">Waktu & Tempat</h2>
<p class="text-gray-600">Merupakan suatu kehormatan dan kebahagiaan bagi kami apabila
Bapak/Ibu/Saudara/i berkenan hadir</p>
</div>
<!-- Akad Nikah -->
<div class="bg-white rounded-2xl shadow-lg p-8 mb-6" data-aos="fade-up">
<div class="text-center">
<div
class="inline-flex items-center justify-center w-16 h-16 bg-rose-100 rounded-full mb-4">
<Icon name="mdi:mosque" class="text-rose-600 text-2xl" />
</div>
<h3 class="text-2xl font-serif text-gray-800 mb-4">Akad Nikah</h3>
<div class="space-y-2 text-gray-600">
<p class="flex items-center justify-center">
<Icon name="mdi:calendar" class="mr-2" />
{{ formatDate(data.akad.date) }}
</p>
<p class="flex items-center justify-center">
<Icon name="mdi:clock-outline" class="mr-2" />
{{ data.akad.time }} - Selesai
</p>
<p class="flex items-center justify-center">
<Icon name="mdi:map-marker" class="mr-2" />
{{ data.akad.place }}
</p>
<p class="text-sm">{{ data.akad.address }}</p>
</div>
</div>
</div>
<!-- Resepsi -->
<div class="bg-white rounded-2xl shadow-lg p-8" data-aos="fade-up" data-aos-delay="200">
<div class="text-center">
<div
class="inline-flex items-center justify-center w-16 h-16 bg-blue-100 rounded-full mb-4">
<Icon name="mdi:party-popper" class="text-blue-600 text-2xl" />
</div>
<h3 class="text-2xl font-serif text-gray-800 mb-4">Resepsi</h3>
<div class="space-y-2 text-gray-600">
<p class="flex items-center justify-center">
<Icon name="mdi:calendar" class="mr-2" />
{{ formatDate(data.resepsi.date) }}
</p>
<p class="flex items-center justify-center">
<Icon name="mdi:clock-outline" class="mr-2" />
{{ data.resepsi.time }} - Selesai
</p>
<p class="flex items-center justify-center">
<Icon name="mdi:map-marker" class="mr-2" />
{{ data.resepsi.place }}
</p>
<p class="text-sm">{{ data.resepsi.address }}</p>
</div>
</div>
</div>
<!-- Countdown Timer -->
<div class="mt-12" data-aos="zoom-in">
<CountdownTimer :targetDate="data.eventDate" />
</div>
</div>
</section>
<!-- Gallery -->
<section class="py-20">
<div class="max-w-6xl mx-auto px-4">
<Gallery :images="data.gallery" />
</div>
</section>
<!-- Maps -->
<section class="bg-[#FFF8EC] py-12 text-center">
<div class="max-w-5xl mx-auto px-4 text-center">
<!-- Judul -->
<div class="mb-8">
<div class="flex items-center justify-center gap-2 mb-2">
<span class="h-[1px] w-12 bg-yellow-400"></span>
<span class="text-yellow-600 text-2xl">🌸</span>
<span class="h-[1px] w-12 bg-yellow-400"></span>
</div>
<h2 class="text-3xl md:text-4xl font-serif text-rose-800 mb-4">Lokasi Acara</h2>
</div>
<div class="grid md:grid-cols-2 gap-6">
<div data-aos="fade-right">
<h3 class="font-semibold text-gray-800 mb-3">Akad Nikah</h3>
<Maps :location="data.akad.mapUrl" />
<a :href="data.akad.mapUrl" target="_blank"
class="inline-block mt-4 px-6 py-2 bg-rose-600 text-white rounded-lg hover:bg-rose-700 transition-colors">
<Icon name="mdi:map" class="mr-2" />
Buka di Google Maps
</a>
</div>
<div data-aos="fade-left">
<h3 class="font-semibold text-gray-800 mb-3">Resepsi</h3>
<Maps :location="data.resepsi.mapUrl" />
<a :href="data.resepsi.mapUrl" target="_blank"
class="inline-block mt-4 px-6 py-2 bg-rose-600 text-white rounded-lg hover:bg-rose-700 transition-colors">
<Icon name="mdi:map" class="mr-2" />
Buka di Google Maps
</a>
</div>
</div>
</div>
</section>
<!-- Ucapan -->
<section class="py-20">
<div class="max-w-2xl mx-auto px-4">
<!-- RSVP Form -->
<RSVP :invitationId="data.id" @submitted="handleRSVPSubmit" />
</div>
</section>
<section>
<!-- Gift Section -->
<section class="py-20 bg-[#FFF8F0]">
<div class="max-w-5xl mx-auto px-4 text-center">
<!-- Judul -->
<div class="mb-10">
<div class="flex items-center justify-center mb-4">
<span class="w-20 h-px bg-orange-300"></span>
<span class="mx-2 text-orange-400 text-2xl">🌸</span>
<span class="w-20 h-px bg-orange-300"></span>
</div>
<h2 class="text-3xl md:text-4xl font-bold text-orange-500">Give a Gift</h2>
<p class="text-gray-600 mt-4 max-w-2xl mx-auto">
Bagi keluarga dan sahabat yang ingin berbagi tanda kasih, kami dengan senang hati
menerimanya sebagai bagian dari doa dan restu yang tulus. Terima kasih telah menjadi
bagian dari hari istimewa kami.
</p>
</div>
<!-- Card Container -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Digital Wallet -->
<div class="bg-white rounded-2xl shadow-md p-6 text-left">
<h3 class="text-xl font-semibold text-gray-700 mb-4">Digital Wallet</h3>
<p class="text-sm text-gray-400 mb-6">Note: Tap to copy bank number</p>
<!-- Akun 1 -->
<div class="mb-6">
<p class="font-semibold text-orange-500 flex items-center space-x-2">
<span>Asep Irawan</span>
<img src="/logo1.png" alt="BNI" class="h-5" />
</p>
<div class="flex items-center mt-2 bg-white shadow-md rounded-xl p-3">
<input class="flex-1 text-gray-700 font-mono outline-none"
value="009 - 0222 2444 21" readonly />
<button @click="copyToClipboard('009 - 0222 2444 21')">
<Icon name="mdi:content-copy" class="text-gray-500" />
</button>
</div>
</div>
<!-- Akun 2 -->
<div>
<p class="font-semibold text-orange-500 flex items-center space-x-2">
<span>Putri Amanda</span>
<img src="/logo2.png" alt="BNI" class="h-5" />
</p>
<div class="flex items-center mt-2 bg-white shadow-md rounded-xl p-3">
<input class="flex-1 text-gray-700 font-mono outline-none"
value="009 - 0222 2444 21" readonly />
<button @click="copyToClipboard('009 - 0222 2444 21')">
<Icon name="mdi:content-copy" class="text-gray-500" />
</button>
</div>
</div>
</div>
<!-- Offline Gift -->
<div class="bg-white rounded-2xl shadow-md p-6 text-left">
<h3 class="text-xl font-semibold text-gray-700 mb-4">Offline Gift</h3>
<p class="text-gray-600 mb-6">
Jl. Terusan Jakarta No.53, Cicaheum, Kec. Kiaracondong, Kota Bandung, Jawa Barat
40291
</p>
<div class="flex items-center space-x-4">
<Icon name="mdi:map-marker" class="text-orange-500 text-2xl" />
<a href="https://maps.google.com/?q=Jl.+Terusan+Jakarta+No.53,+Cicaheum"
target="_blank"
class="bg-orange-400 hover:bg-orange-500 text-white px-6 py-2 rounded-xl shadow transition">
Open Map
</a>
</div>
</div>
</div>
<!-- Garis Dekorasi Bawah -->
<div class="flex items-center justify-center mt-10">
<span class="w-20 h-px bg-orange-300"></span>
<span class="mx-2 text-orange-400 text-2xl">🌸</span>
<span class="w-20 h-px bg-orange-300"></span>
</div>
</div>
</section>
</section>
<!-- Closing -->
<section class="py-20 text-center px-4">
<div class="max-w-2xl mx-auto" data-aos="fade-up">
<p class="text-gray-600 mb-4">
Merupakan suatu kehormatan dan kebahagiaan bagi kami apabila Bapak/Ibu/Saudara/i
berkenan hadir untuk memberikan doa restu kepada kedua mempelai.
</p>
<p class="text-gray-600 mb-8">
Atas kehadiran serta doa restu Bapak/Ibu/Saudara/i, kami ucapkan terima kasih.
</p>
<p class="font-serif text-2xl text-rose-800 mb-2">Wassalamu'alaikum Wr. Wb.</p>
<p class="text-gray-700 font-semibold mt-8">
{{ data.bride.nickname }} & {{ data.groom.nickname }}
</p>
</div>
</section>
<!-- Footer -->
<footer class="relative text-center bg-cover bg-center bg-no-repeat"
style="background-image: url('/wedding1.png');">
<!-- Overlay gelap biar teks lebih kontras -->
<div class="absolute inset-0 bg-black/40"></div>
<!-- Konten footer -->
<div class="relative z-10">
<!-- Kotak Nama Mempelai -->
<div class="flex items-center justify-center space-x-4 -mt-12">
<div class="px-8 py-3 border border-white rounded-lg bg-white/20 backdrop-blur-sm shadow">
<p class="font-semibold italic text-2xl text-white">{{ data.groom.nickname }}</p>
</div>
<span class="text-3xl font-bold text-white">-</span>
<div class="px-8 py-3 border border-white rounded-lg bg-white/20 backdrop-blur-sm shadow">
<p class="font-semibold italic text-2xl text-white">{{ data.bride.nickname }}</p>
</div>
</div>
<!-- Ikon bunga -->
<div class="flex justify-center mt-6">
<span class="text-white text-3xl">✿</span>
</div>
<!-- Logo -->
<div class="flex justify-center mt-4">
<img src="/ABBAUF.png" alt="Logo" class="h-12 object-contain" />
</div>
<!-- Copyright -->
<p class="text-xs mt-4 text-white/80">
© 2024 All rights reserved
</p>
</div>
</footer>
<!-- Music Player -->
<MusicPlayer v-if="data.musicUrl" :url="data.musicUrl" :autoplay="true" />
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import AOS from 'aos'
import 'aos/dist/aos.css'
// Import shared components
import CountdownTimer from '~/components/shared/CountdownTimer.vue'
import Gallery from '~/components/shared/Gallery.vue'
import Maps from '~/components/shared/Maps.vue'
import RSVP from '~/components/shared/RSVP.vue'
import GuestBook from '~/components/shared/GuestBook.vue'
import MusicPlayer from '~/components/shared/MusicPlayer.vue'
// Props untuk menerima data dari parent/API
const props = defineProps({
data: {
type: Object,
required: true,
default: () => ({
id: '',
coverImage: '',
heroImage: '',
greeting: '',
eventDate: new Date(),
bride: {
fullname: '',
nickname: '',
photo: '',
orderChild: '',
fatherName: '',
motherName: '',
instagram: ''
},
groom: {
fullname: '',
nickname: '',
photo: '',
orderChild: '',
fatherName: '',
motherName: '',
instagram: ''
},
akad: {
date: new Date(),
time: '',
place: '',
address: '',
mapUrl: ''
},
resepsi: {
date: new Date(),
time: '',
place: '',
address: '',
mapUrl: ''
},
gallery: [],
gift: {
bankName: '',
accountNumber: '',
accountName: ''
},
musicUrl: ''
})
}
})
// State
const isOpened = ref(false)
const guestMessages = ref([])
// Methods
const openInvitation = () => {
isOpened.value = true
// Play music if available
if (props.data.musicUrl) {
// Music will autoplay through MusicPlayer component
}
}
const formatDate = (date) => {
if (!date) return ''
const options = {
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric'
}
return new Date(date).toLocaleDateString('id-ID', options)
}
const copyToClipboard = async (text) => {
try {
await navigator.clipboard.writeText(text)
// Show toast notification
alert('Nomor rekening berhasil disalin!')
} catch (err) {
console.error('Failed to copy:', err)
}
}
const handleRSVPSubmit = (data) => {
// Handle RSVP submission
console.log('RSVP submitted:', data)
// Add to guest messages
if (data.message) {
guestMessages.value.unshift({
name: data.name,
message: data.message,
attendance: data.attendance,
createdAt: new Date()
})
}
}
// Load guest messages from API
const loadGuestMessages = async () => {
try {
// Fetch from your Laravel API
// const response = await $fetch(`/api/invitations/${props.data.id}/messages`)
// guestMessages.value = response.data
} catch (error) {
console.error('Error loading guest messages:', error)
}
}
// Lifecycle
onMounted(() => {
// Initialize AOS
AOS.init({
duration: 1000,
once: true,
offset: 100
})
// Load guest messages
loadGuestMessages()
})
</script>
<style scoped>
/* Custom animations */
@keyframes fade-in {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes slide-up {
from {
transform: translateY(30px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
@keyframes pulse-slow {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
.animate-fade-in {
animation: fade-in 1s ease-out;
}
.animate-fade-in-delay {
animation: fade-in 1s ease-out 0.5s both;
}
.animate-slide-up {
animation: slide-up 1s ease-out;
}
.animate-pulse-slow {
animation: pulse-slow 2s ease-in-out infinite;
}
/* Custom scrollbar */
::-webkit-scrollbar {
width: 8px;
}
::-webkit-scrollbar-track {
background: #f1f1f1;
}
::-webkit-scrollbar-thumb {
background: #f43f5e;
border-radius: 4px;
}
::-webkit-scrollbar-thumb:hover {
background: #e11d48;
}
</style>