630 lines
27 KiB
Vue
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> |