Merge branch 'baru' of https://git.abbauf.com/Magang-2025/Undangan into baru
This commit is contained in:
commit
8d84a54e79
@ -4,14 +4,14 @@
|
|||||||
<img
|
<img
|
||||||
src="/balloon2.png"
|
src="/balloon2.png"
|
||||||
alt="Balloons Left"
|
alt="Balloons Left"
|
||||||
class="fixed left-0 bottom-0 w-64 md:w-80 lg:w-96 opacity-90 animate-swing-left select-none pointer-events-none z-0 balloon-left -translate-x-[53%]"
|
class="fixed left-0 bottom-0 w-52 md:w-80 lg:w-96 opacity-90 animate-swing-left select-none pointer-events-none z-0 balloon-left -translate-x-[53%]"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Balon kanan - di ujung kanan -->
|
<!-- Balon kanan - di ujung kanan -->
|
||||||
<img
|
<img
|
||||||
src="/balloon2.png"
|
src="/balloon2.png"
|
||||||
alt="Balloons Right"
|
alt="Balloons Right"
|
||||||
class="fixed right-0 bottom-0 w-64 md:w-80 lg:w-96 opacity-90 animate-swing-right select-none pointer-events-none z-0 balloon-right translate-x-[54%]"
|
class="fixed right-0 bottom-0 w-52 md:w-80 lg:w-96 opacity-90 animate-swing-right select-none pointer-events-none z-0 balloon-right translate-x-[54%]"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- Judul -->
|
<!-- Judul -->
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="relative p-6 text-center max-w-4xl mx-auto">
|
<div class="relative p-6 text-center max-w-6xl mx-auto">
|
||||||
<!-- Gambar Happy Birthday di belakang -->
|
<!-- Gambar Happy Birthday di belakang -->
|
||||||
<img
|
<img
|
||||||
src="/happy1.png"
|
src="/happy1.png"
|
||||||
alt="Happy Birthday"
|
alt="Happy Birthday"
|
||||||
class="absolute top-[-59%] left-1/2 transform w-80 md:w-96 opacity-90 z-0 animate-happy-drop"
|
class="absolute top-[-59%] left-1/2 transform w-80 md:w-96 opacity-90 z-0 animate-happy-drop"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<h2
|
<h2
|
||||||
@ -13,22 +13,28 @@
|
|||||||
📸 Galeri Foto 📸
|
📸 Galeri Foto 📸
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
<!-- Grid galeri -->
|
||||||
<div
|
<div
|
||||||
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 relative z-10"
|
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 relative z-10"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(img, i) in images"
|
v-for="(img, i) in images"
|
||||||
:key="i"
|
:key="i"
|
||||||
class="group relative overflow-hidden rounded-2xl shadow-lg transform hover:scale-105 transition-all duration-500"
|
class="group relative overflow-hidden rounded-2xl shadow-lg transform hover:scale-105 transition-all duration-500"
|
||||||
>
|
>
|
||||||
|
<!-- Overlay saat hover -->
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-10"
|
class="absolute inset-0 bg-gradient-to-t from-black/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-10"
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
|
<!-- Gambar -->
|
||||||
<img
|
<img
|
||||||
:src="img"
|
:src="img"
|
||||||
alt="Galeri"
|
alt="Galeri"
|
||||||
class="w-full h-64 object-cover transform group-hover:scale-110 transition-transform duration-500"
|
class="w-full h-64 object-cover transform group-hover:scale-110 transition-transform duration-500"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<!-- Teks muncul saat hover -->
|
||||||
<div
|
<div
|
||||||
class="absolute bottom-0 left-0 right-0 p-4 text-white transform translate-y-full group-hover:translate-y-0 transition-transform duration-300 z-20"
|
class="absolute bottom-0 left-0 right-0 p-4 text-white transform translate-y-full group-hover:translate-y-0 transition-transform duration-300 z-20"
|
||||||
>
|
>
|
||||||
@ -37,6 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Pesan jika belum ada foto -->
|
||||||
<div
|
<div
|
||||||
v-if="images.length === 0"
|
v-if="images.length === 0"
|
||||||
class="bg-white/80 rounded-2xl p-8 shadow-lg relative z-10"
|
class="bg-white/80 rounded-2xl p-8 shadow-lg relative z-10"
|
||||||
@ -48,7 +55,10 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
defineProps({
|
defineProps({
|
||||||
images: Array
|
images: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,10 +1,29 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="p-6 text-center max-w-2xl mx-auto">
|
<div class="p-6 text-center max-w-2xl mx-auto relative">
|
||||||
<h2 class="text-4xl font-bold bg-gradient-to-r from-orange-600 to-yellow-600 bg-clip-text text-transparent mb-8">
|
<h2
|
||||||
|
class="text-4xl font-bold bg-gradient-to-r from-orange-600 to-yellow-600 bg-clip-text text-transparent mb-8"
|
||||||
|
>
|
||||||
💌 Buku Tamu 💌
|
💌 Buku Tamu 💌
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="bg-white/80 backdrop-blur-lg rounded-2xl p-8 shadow-xl border border-yellow-100 mb-8">
|
<!-- 🎈 Balon Kiri -->
|
||||||
|
<img
|
||||||
|
src="/balloon2.png"
|
||||||
|
alt="Balloons Left"
|
||||||
|
class="absolute w-32 md:w-40 -top-12 -left-7.5 animate-swing-top pointer-events-none select-none"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 🎈 Balon Kanan -->
|
||||||
|
<img
|
||||||
|
src="/balloon2.png"
|
||||||
|
alt="Balloons Right"
|
||||||
|
class="absolute w-32 md:w-40 -top-12 -right-10.5 animate-swing-top pointer-events-none select-none"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- 💌 Card Utama -->
|
||||||
|
<div
|
||||||
|
class="bg-white/80 backdrop-blur-lg rounded-2xl p-8 shadow-xl border border-yellow-100 mb-8 relative z-10"
|
||||||
|
>
|
||||||
<form @submit.prevent="submitMessage" class="space-y-4">
|
<form @submit.prevent="submitMessage" class="space-y-4">
|
||||||
<textarea
|
<textarea
|
||||||
v-model="newMessage"
|
v-model="newMessage"
|
||||||
@ -23,7 +42,8 @@
|
|||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="space-y-4 max-h-96 overflow-y-auto px-2">
|
<!-- 💬 Daftar Pesan -->
|
||||||
|
<div class="space-y-4 max-h-96 overflow-y-auto px-2 relative z-10">
|
||||||
<div
|
<div
|
||||||
v-for="(msg, i) in messages"
|
v-for="(msg, i) in messages"
|
||||||
:key="i"
|
:key="i"
|
||||||
@ -38,7 +58,9 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="messages.length === 0" class="bg-white/60 p-8 rounded-2xl">
|
<div v-if="messages.length === 0" class="bg-white/60 p-8 rounded-2xl">
|
||||||
<p class="text-gray-600">Belum ada ucapan. Jadilah yang pertama mengucapkan!</p>
|
<p class="text-gray-600">
|
||||||
|
Belum ada ucapan. Jadilah yang pertama mengucapkan!
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -60,4 +82,23 @@ function submitMessage() {
|
|||||||
emit('addMessage', newMessage.value)
|
emit('addMessage', newMessage.value)
|
||||||
newMessage.value = ''
|
newMessage.value = ''
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@keyframes swing-top {
|
||||||
|
0% {
|
||||||
|
transform: rotate(2deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: rotate(-2deg);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: rotate(2deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-swing-top {
|
||||||
|
animation: swing-top 4s ease-in-out infinite;
|
||||||
|
transform-origin: bottom center; /* ✅ Balon berayun dari bawah (tali diam) */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -1,33 +1,59 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col items-center text-center p-6 space-y-6 max-w-2xl mx-auto">
|
<div>
|
||||||
<!-- Photo frame with decoration -->
|
<!-- 🎈 Balon Background - Fixed di seluruh layar -->
|
||||||
<div class="relative">
|
<div class="fixed inset-0 w-full h-full overflow-hidden z-0 pointer-events-none">
|
||||||
<div class="absolute -inset-4 bg-gradient-to-r from-yellow-400 to-orange-400 rounded-full blur opacity-30"></div>
|
<!-- Balon Kiri -->
|
||||||
<img
|
<img src="/balon1.png" alt="Balon" class="absolute w-26 animate-fly-slow" style="left: 5%; bottom: -150px;" />
|
||||||
v-if="childPhoto"
|
<img src="/balon2.png" alt="Balon" class="absolute w-24 animate-fly-medium delay-[0.5s]" style="left: 10%; bottom: -200px;" />
|
||||||
:src="childPhoto"
|
<img src="/balon3.png" alt="Balon" class="absolute w-26 animate-fly-fast delay-[1s]" style="left: 2%; bottom: -250px;" />
|
||||||
alt="Foto Anak"
|
<img src="/balon1.png" alt="Balon" class="absolute w-24 animate-fly-slow delay-[1.5s]" style="left: 8%; bottom: -300px;" />
|
||||||
class="relative w-48 h-48 rounded-full object-cover border-4 border-white shadow-2xl z-10"
|
|
||||||
/>
|
<!-- Balon Kanan -->
|
||||||
<div v-else class="relative w-48 h-48 rounded-full bg-gradient-to-br from-yellow-200 to-orange-200 border-4 border-white shadow-2xl flex items-center justify-center z-10">
|
<img src="/balon2.png" alt="Balon" class="absolute w-26 animate-fly-medium" style="right: 5%; bottom: -150px;" />
|
||||||
<span class="text-4xl">👶</span>
|
<img src="/balon3.png" alt="Balon" class="absolute w-24 animate-fly-slow delay-[1s]" style="right: 10%; bottom: -200px;" />
|
||||||
</div>
|
<img src="/balon1.png" alt="Balon" class="absolute w-26 animate-fly-fast delay-[2s]" style="right: 2%; bottom: -250px;" />
|
||||||
|
<img src="/balon2.png" alt="Balon" class="absolute w-24 animate-fly-slow delay-[2.5s]" style="right: 8%; bottom: -300px;" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-white/80 backdrop-blur-md rounded-2xl p-8 shadow-xl border border-yellow-100">
|
<!-- Container Konten Utama -->
|
||||||
<h2 class="text-4xl font-bold bg-gradient-to-r from-orange-600 to-yellow-600 bg-clip-text text-transparent mb-4">
|
<div class="relative flex flex-col items-center text-center p-6 space-y-6 max-w-2xl mx-auto">
|
||||||
Halo, Aku {{ childName }}
|
<!-- Foto Anak -->
|
||||||
</h2>
|
<div class="relative z-10 mb-6 group transition-transform duration-500 hover:scale-105">
|
||||||
<div class="space-y-3 text-gray-700">
|
<div class="absolute -inset-4 bg-gradient-to-r from-yellow-400 to-orange-400 rounded-full blur opacity-30 transition-all duration-500 group-hover:opacity-60 group-hover:blur-lg"></div>
|
||||||
<p class="text-xl font-semibold">Usiaku kini <span class="text-orange-500">{{ age }}</span> tahun 🎉</p>
|
<img
|
||||||
<p class="text-gray-600">Putra/Putri dari</p>
|
v-if="childPhoto"
|
||||||
<p class="text-xl font-bold text-gray-800 bg-gradient-to-r from-orange-400 to-yellow-400 bg-clip-text text-transparent">
|
:src="childPhoto"
|
||||||
{{ parentsName }}
|
alt="Foto Anak"
|
||||||
|
class="relative w-48 h-48 rounded-full object-cover border-4 border-white shadow-2xl z-10 transition-all duration-500 group-hover:shadow-[0_0_25px_rgba(255,165,0,0.6)]"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="relative w-48 h-48 rounded-full bg-gradient-to-br from-yellow-200 to-orange-200 border-4 border-white shadow-2xl flex items-center justify-center z-10 transition-all duration-500 group-hover:shadow-[0_0_25px_rgba(255,165,0,0.6)]"
|
||||||
|
>
|
||||||
|
<span class="text-4xl">👶</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Kartu Ucapan -->
|
||||||
|
<div
|
||||||
|
class="bg-white/80 backdrop-blur-md rounded-2xl p-8 shadow-xl border border-yellow-100 z-10 transition-all duration-500 hover:scale-105 hover:shadow-[0_0_30px_rgba(255,200,0,0.4)]"
|
||||||
|
>
|
||||||
|
<h2 class="text-4xl font-bold bg-gradient-to-r from-orange-600 to-yellow-600 bg-clip-text text-transparent mb-4">
|
||||||
|
Halo, Aku {{ childName }}
|
||||||
|
</h2>
|
||||||
|
<div class="space-y-3 text-gray-700">
|
||||||
|
<p class="text-xl font-semibold">
|
||||||
|
Usiaku kini <span class="text-orange-500">{{ age }}</span> tahun 🎉
|
||||||
|
</p>
|
||||||
|
<p class="text-gray-600">Putra/Putri dari</p>
|
||||||
|
<p class="text-xl font-bold text-gray-800 bg-gradient-to-r from-orange-400 to-yellow-400 bg-clip-text text-transparent">
|
||||||
|
{{ parentsName }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p class="mt-6 text-lg text-gray-600 italic">
|
||||||
|
Aku sangat senang jika kamu bisa hadir di pesta ulang tahunku!
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-6 text-lg text-gray-600 italic">
|
|
||||||
Aku sangat senang jika kamu bisa hadir di pesta ulang tahunku!
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -39,4 +65,40 @@ defineProps({
|
|||||||
age: [String, Number],
|
age: [String, Number],
|
||||||
childPhoto: String
|
childPhoto: String
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@keyframes flyUp {
|
||||||
|
0% {
|
||||||
|
transform: translateY(100vh) scale(0.9) rotate(0deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
70% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(-110vh) scale(1.05) rotate(10deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 💨 Durasi lebih cepat agar terasa ramai */
|
||||||
|
.animate-fly-slow {
|
||||||
|
animation: flyUp 8s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fly-medium {
|
||||||
|
animation: flyUp 6s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-fly-fast {
|
||||||
|
animation: flyUp 4s linear infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ⏱️ Delay singkat agar balon muncul hampir bersamaan */
|
||||||
|
.delay-\[0\.5s\] { animation-delay: 0.5s; }
|
||||||
|
.delay-\[1s\] { animation-delay: 1s; }
|
||||||
|
.delay-\[1\.5s\] { animation-delay: 1.5s; }
|
||||||
|
.delay-\[2s\] { animation-delay: 2s; }
|
||||||
|
.delay-\[2\.5s\] { animation-delay: 2.5s; }
|
||||||
|
</style>
|
||||||
|
|||||||
@ -1,14 +1,34 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col items-center justify-center text-center p-6 space-y-8 max-w-2xl mx-auto">
|
<div class="flex flex-col items-center justify-center text-center p-6 space-y-8 max-w-2xl mx-auto relative overflow-hidden min-h-screen">
|
||||||
<h2 class="text-4xl font-bold bg-gradient-to-r from-orange-600 to-yellow-600 bg-clip-text text-transparent">
|
<!-- 🎈 BALLOON BACKGROUND -->
|
||||||
|
<div class="balloon-container">
|
||||||
|
<div class="balloon balloon-left-1">
|
||||||
|
<img src="/balloon1.png" alt="Balloon" class="w-32 h-auto" />
|
||||||
|
</div>
|
||||||
|
<div class="balloon balloon-left-2">
|
||||||
|
<img src="/balloon1.png" alt="Balloon" class="w-32 h-auto" />
|
||||||
|
</div>
|
||||||
|
<div class="balloon balloon-right-1">
|
||||||
|
<img src="/balloon1.png" alt="Balloon" class="w-32 h-auto" />
|
||||||
|
</div>
|
||||||
|
<div class="balloon balloon-right-2">
|
||||||
|
<img src="/balloon1.png" alt="Balloon" class="w-32 h-auto" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 🎀 THANK YOU CARD -->
|
||||||
|
<h2 class="text-4xl font-bold bg-gradient-to-r from-orange-600 to-yellow-600 bg-clip-text text-transparent z-10">
|
||||||
Terima Kasih! 🙏
|
Terima Kasih! 🙏
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div class="bg-white/80 backdrop-blur-lg rounded-2xl p-8 shadow-xl border border-yellow-100 space-y-6">
|
<div class="bg-white/80 backdrop-blur-lg rounded-2xl p-8 shadow-xl border border-yellow-100 space-y-6 z-10">
|
||||||
<p class="text-lg text-gray-700">Sudah meluangkan waktu untuk melihat undangan ulang tahunku 💛</p>
|
<p class="text-lg text-gray-700">Sudah meluangkan waktu untuk melihat undangan ulang tahunku 💛</p>
|
||||||
|
|
||||||
<p class="text-xl font-semibold text-gray-800">
|
<p class="text-xl font-semibold text-gray-800">
|
||||||
Salam hangat dari <span class="bg-gradient-to-r from-orange-500 to-yellow-500 bg-clip-text text-transparent font-bold">{{ childName }}</span>
|
Salam hangat dari
|
||||||
|
<span class="bg-gradient-to-r from-orange-500 to-yellow-500 bg-clip-text text-transparent font-bold">
|
||||||
|
{{ childName }}
|
||||||
|
</span>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div v-if="jsonData?.pesan_terimakasih" class="bg-gradient-to-r from-yellow-100 to-orange-100 p-6 rounded-xl border-l-4 border-orange-400">
|
<div v-if="jsonData?.pesan_terimakasih" class="bg-gradient-to-r from-yellow-100 to-orange-100 p-6 rounded-xl border-l-4 border-orange-400">
|
||||||
@ -21,7 +41,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex space-x-4 mt-6">
|
<!-- EMOJI ANIMATION -->
|
||||||
|
<div class="flex space-x-4 mt-6 z-10">
|
||||||
<div class="animate-bounce">🎈</div>
|
<div class="animate-bounce">🎈</div>
|
||||||
<div class="animate-bounce delay-100">🎁</div>
|
<div class="animate-bounce delay-100">🎁</div>
|
||||||
<div class="animate-bounce delay-200">🍰</div>
|
<div class="animate-bounce delay-200">🍰</div>
|
||||||
@ -35,4 +56,67 @@ defineProps({
|
|||||||
childName: String,
|
childName: String,
|
||||||
jsonData: Object
|
jsonData: Object
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.balloon-container {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* BALLOON ANIMATION */
|
||||||
|
.balloon {
|
||||||
|
position: absolute;
|
||||||
|
bottom: -150px;
|
||||||
|
opacity: 0;
|
||||||
|
animation: floatUp 12s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balloon-left-1 {
|
||||||
|
left: 8%;
|
||||||
|
animation-delay: 0s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balloon-left-2 {
|
||||||
|
left: 20%;
|
||||||
|
animation-delay: 4s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balloon-right-1 {
|
||||||
|
right: 8%;
|
||||||
|
animation-delay: 2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.balloon-right-2 {
|
||||||
|
right: 22%;
|
||||||
|
animation-delay: 6s;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes floatUp {
|
||||||
|
0% {
|
||||||
|
transform: translateY(0) scale(0.8) rotate(0deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
60% {
|
||||||
|
transform: translateY(-60vh) scale(1) rotate(10deg);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
80% {
|
||||||
|
transform: translateY(-80vh) scale(1.1) rotate(-10deg);
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(-100vh) scale(1.2) rotate(15deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -1,35 +1,138 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen flex flex-col items-center justify-center text-center bg-orange-100 py-10 px-6">
|
<section
|
||||||
<h2 class="text-3xl font-bold text-orange-700 mb-4">📅 Detail Acara</h2>
|
class="relative w-full h-screen flex flex-col justify-center items-center overflow-hidden text-center bg-gradient-to-b from-purple-900 via-red-900 to-black text-white px-6"
|
||||||
|
>
|
||||||
|
<!-- Judul -->
|
||||||
|
<h1 class="text-4xl md:text-5xl font-extrabold text-yellow-400 drop-shadow-lg mb-6">
|
||||||
|
Detail Petualangan
|
||||||
|
</h1>
|
||||||
|
|
||||||
<div class="bg-white rounded-2xl shadow-md p-6 w-full max-w-md text-gray-700">
|
<!-- Kotak konten utama -->
|
||||||
<p class="mb-2"><strong>Hari & Tanggal:</strong> {{ formatDate(hari_tanggal_acara) }}</p>
|
<div
|
||||||
<p class="mb-2"><strong>Waktu:</strong> {{ waktu }}</p>
|
class="bg-black/60 rounded-2xl p-6 md:p-8 w-full max-w-2xl shadow-[0_0_25px_rgba(255,255,255,0.1)] flex flex-col gap-4"
|
||||||
<p class="mb-2"><strong>Alamat:</strong> {{ alamat }}</p>
|
>
|
||||||
|
<!-- Hari & Tanggal -->
|
||||||
|
<div class="flex items-center gap-4 border border-red-600 rounded-lg p-4 bg-gradient-to-r from-red-800/40 to-red-900/30">
|
||||||
|
<div class="text-3xl">📅</div>
|
||||||
|
<div class="text-left">
|
||||||
|
<h2 class="font-semibold text-red-400">Hari & Tanggal</h2>
|
||||||
|
<p class="text-white font-medium">Rabu, 22 Oktober 2025</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<a
|
<!-- Waktu -->
|
||||||
v-if="link_gmaps"
|
<div class="flex items-center gap-4 border border-blue-600 rounded-lg p-4 bg-gradient-to-r from-blue-800/40 to-blue-900/30">
|
||||||
:href="link_gmaps"
|
<div class="text-3xl">⏰</div>
|
||||||
target="_blank"
|
<div class="text-left">
|
||||||
class="inline-block mt-4 bg-orange-600 text-white py-2 px-6 rounded-full hover:bg-orange-700 transition"
|
<h2 class="font-semibold text-blue-400">Waktu Acara</h2>
|
||||||
|
<p class="text-white font-medium">18.00</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Lokasi -->
|
||||||
|
<div class="flex items-center gap-4 border border-yellow-600 rounded-lg p-4 bg-gradient-to-r from-yellow-800/40 to-yellow-900/30">
|
||||||
|
<div class="text-3xl">📍</div>
|
||||||
|
<div class="text-left">
|
||||||
|
<h2 class="font-semibold text-yellow-400">Lokasi Petualangan</h2>
|
||||||
|
<p class="text-white font-medium">jkbjkb</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tombol Maps -->
|
||||||
|
<button
|
||||||
|
class="mt-4 bg-gray-800 text-white px-6 py-3 rounded-full font-semibold hover:bg-gray-700 transition-all duration-300 mx-auto flex items-center gap-2"
|
||||||
>
|
>
|
||||||
📍 Lihat di Google Maps
|
🗺️ Link Maps Menyusul
|
||||||
</a>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<!-- Catatan -->
|
||||||
|
<p
|
||||||
|
class="mt-6 text-sm md:text-base italic text-yellow-300 max-w-2xl text-center leading-relaxed"
|
||||||
|
>
|
||||||
|
“Bersiaplah untuk berayun-ayun dalam keseruan! Kostum Spider-Man opsional tapi sangat disarankan!
|
||||||
|
Jangan lupa bawa kekuatan super dan senyuman! 🕷️✨”
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
hari_tanggal_acara: String,
|
hari_tanggal_acara: String,
|
||||||
waktu: String,
|
waktu: String,
|
||||||
alamat: String,
|
alamat: String,
|
||||||
link_gmaps: String
|
link_gmaps: String,
|
||||||
})
|
});
|
||||||
|
|
||||||
|
const showSpider = ref(false);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
showSpider.value = true;
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
|
||||||
const formatDate = (dateStr) => {
|
const formatDate = (dateStr) => {
|
||||||
if (!dateStr) return '-'
|
if (!dateStr) return "Akan diumumkan";
|
||||||
const d = new Date(dateStr)
|
try {
|
||||||
return d.toLocaleDateString('id-ID', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' })
|
const d = new Date(dateStr);
|
||||||
}
|
return d.toLocaleDateString("id-ID", {
|
||||||
|
weekday: "long",
|
||||||
|
day: "numeric",
|
||||||
|
month: "long",
|
||||||
|
year: "numeric",
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
return dateStr;
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 🕸️ Animasi Spider-Man */
|
||||||
|
@keyframes float-slow {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0px) scaleX(-1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-25px) scaleX(-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-float-slow {
|
||||||
|
animation: float-slow 6s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 🕷️ Transisi Spider muncul */
|
||||||
|
.fade-slide-enter-active {
|
||||||
|
transition: all 1s ease;
|
||||||
|
}
|
||||||
|
.fade-slide-enter-from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-40px);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 🕷️ Bounce kecil */
|
||||||
|
@keyframes bounce {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-12px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-bounce {
|
||||||
|
animation: bounce 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 📱 Responsif untuk HP */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
img[alt="Spider-Man"] {
|
||||||
|
width: 6rem !important;
|
||||||
|
bottom: 3%;
|
||||||
|
left: 4%;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -1,17 +1,70 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-yellow-100 py-10 px-4">
|
<section
|
||||||
<h2 class="text-3xl font-bold text-orange-700 text-center mb-8">📸 Galeri Foto</h2>
|
class="relative w-full min-h-screen bg-gradient-to-b from-blue-900 via-red-800 to-black text-white flex flex-col justify-center items-center overflow-hidden py-16 px-6"
|
||||||
|
>
|
||||||
|
<!-- Efek jaring latar -->
|
||||||
|
<div class="absolute inset-0 opacity-10 pointer-events-none">
|
||||||
|
<div class="absolute top-0 left-1/3 w-0.5 h-full bg-gradient-to-b from-blue-200 to-red-200"></div>
|
||||||
|
<div class="absolute top-0 left-2/3 w-0.5 h-full bg-gradient-to-b from-blue-200 to-red-200"></div>
|
||||||
|
<div class="absolute inset-0 bg-[radial-gradient(circle_at_center,rgba(255,255,255,0.15),transparent_70%)]"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6 max-w-5xl mx-auto">
|
<!-- Judul -->
|
||||||
|
<div class="relative z-10 text-center mb-12">
|
||||||
|
<h2
|
||||||
|
class="text-5xl md:text-6xl font-extrabold text-yellow-300 drop-shadow-[0_0_10px_rgba(255,255,0,0.4)] tracking-tight"
|
||||||
|
>
|
||||||
|
🕸️ Galeri Petualangan 🕷️
|
||||||
|
</h2>
|
||||||
|
<p class="mt-3 text-base md:text-lg text-gray-200 italic tracking-wide">
|
||||||
|
Momen seru para Spider-Hero yang tertangkap kamera!
|
||||||
|
</p>
|
||||||
|
<div class="w-32 h-1 bg-gradient-to-r from-red-500 to-blue-500 mx-auto mt-4 rounded-full"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Grid Foto -->
|
||||||
|
<div
|
||||||
|
class="relative z-10 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8 max-w-6xl mx-auto"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
v-for="(img, index) in images"
|
v-for="(img, index) in images"
|
||||||
:key="index"
|
:key="index"
|
||||||
class="relative group overflow-hidden rounded-2xl shadow-md"
|
class="relative group rounded-2xl overflow-hidden shadow-[0_0_25px_rgba(255,255,255,0.15)] border border-white/10 bg-black/40 backdrop-blur-sm hover:shadow-[0_0_35px_rgba(255,0,0,0.4)] transition-all duration-500"
|
||||||
>
|
>
|
||||||
<img :src="img" alt="Foto" class="w-full h-64 object-cover transition-transform duration-300 group-hover:scale-110" />
|
<!-- Gambar -->
|
||||||
|
<img
|
||||||
|
:src="img"
|
||||||
|
alt="Foto"
|
||||||
|
class="w-full h-72 object-cover transform group-hover:scale-110 transition-transform duration-700 ease-out"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Overlay hover -->
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gradient-to-t from-black/80 via-black/30 to-transparent opacity-0 group-hover:opacity-100 transition-all duration-500 flex flex-col items-center justify-end pb-5"
|
||||||
|
>
|
||||||
|
<span class="text-yellow-300 font-semibold text-lg mb-1 drop-shadow-md">Photo {{ index + 1 }}</span>
|
||||||
|
<span class="text-sm text-gray-200">🕷️ Klik untuk zoom</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Icon Spider -->
|
||||||
|
<div
|
||||||
|
class="absolute top-3 right-3 bg-gradient-to-r from-red-600 to-red-800 text-white px-3 py-1 rounded-full text-sm font-bold shadow-lg"
|
||||||
|
>
|
||||||
|
🕷️
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<!-- Empty State -->
|
||||||
|
<div
|
||||||
|
v-if="images.length === 0"
|
||||||
|
class="relative z-10 text-center mt-16 animate-pulse"
|
||||||
|
>
|
||||||
|
<div class="text-6xl mb-3">🕸️</div>
|
||||||
|
<p class="text-xl font-semibold">Foto-foto sedang dalam petualangan...</p>
|
||||||
|
<p class="text-yellow-300 mt-2">Mereka akan segera muncul!</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@ -21,4 +74,31 @@ defineProps({
|
|||||||
default: () => []
|
default: () => []
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* Efek muncul halus untuk tiap foto */
|
||||||
|
.group {
|
||||||
|
animation: fadeInUp 0.8s ease both;
|
||||||
|
}
|
||||||
|
@keyframes fadeInUp {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(30px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsif tambahan */
|
||||||
|
@media (max-width: 640px) {
|
||||||
|
h2 {
|
||||||
|
font-size: 2.25rem;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
height: 12rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -1,28 +1,236 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col items-center text-center min-h-screen bg-yellow-200 py-12 px-6">
|
<section
|
||||||
<img
|
class="relative w-full min-h-screen flex flex-col items-center justify-center overflow-hidden text-center bg-gradient-to-b from-blue-900 via-red-800 to-black text-white animate-fade-in"
|
||||||
v-if="childPhoto"
|
>
|
||||||
:src="childPhoto"
|
<!-- 🕸️ Background grid lembut -->
|
||||||
alt="Foto Anak"
|
<div class="absolute inset-0 opacity-10 pointer-events-none">
|
||||||
class="w-40 h-40 rounded-full shadow-lg mb-6 object-cover border-4 border-yellow-500"
|
<div class="absolute top-0 left-1/4 w-0.5 h-full bg-white/30"></div>
|
||||||
/>
|
<div class="absolute top-0 left-2/4 w-0.5 h-full bg-white/30"></div>
|
||||||
|
<div class="absolute top-0 left-3/4 w-0.5 h-full bg-white/30"></div>
|
||||||
|
<div class="absolute top-1/4 left-0 w-full h-0.5 bg-white/30"></div>
|
||||||
|
<div class="absolute top-2/4 left-0 w-full h-0.5 bg-white/30"></div>
|
||||||
|
<div class="absolute top-3/4 left-0 w-full h-0.5 bg-white/30"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<h2 class="text-3xl font-bold text-orange-700 mb-2">{{ childName }}</h2>
|
<!-- 🕷️ Laba-laba animasi turun dari atas -->
|
||||||
<p class="text-lg text-gray-700 mb-4">Berusia {{ age }} tahun 🎂</p>
|
<div
|
||||||
<p class="text-md text-gray-600 mb-6">Putra/Putri dari {{ parentsName }}</p>
|
v-for="(spider, index) in spiders"
|
||||||
|
:key="index"
|
||||||
|
class="absolute text-3xl animate-spider-move"
|
||||||
|
:style="{
|
||||||
|
left: spider.left,
|
||||||
|
animationDelay: spider.delay,
|
||||||
|
fontSize: spider.size,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
🕷️
|
||||||
|
</div>
|
||||||
|
|
||||||
<p class="max-w-md text-gray-700 leading-relaxed">
|
|
||||||
Dengan penuh sukacita, kami mengundang teman-teman dan keluarga untuk hadir dalam acara ulang tahun kami yang
|
<!-- ✨ Konten utama -->
|
||||||
ke-{{ age }}!
|
<div class="relative z-10 w-full px-6 max-w-2xl mt-16 md:mt-0 animate-slide-up">
|
||||||
</p>
|
<!-- Foto Anak -->
|
||||||
</div>
|
<div class="relative mb-8 flex justify-center">
|
||||||
|
<!-- Cahaya latar -->
|
||||||
|
<div
|
||||||
|
class="absolute w-72 h-72 md:w-80 md:h-80 rounded-full bg-gradient-to-br from-red-500 via-yellow-500 to-blue-600 blur-3xl opacity-60 animate-pulse-slow"
|
||||||
|
></div>
|
||||||
|
|
||||||
|
<!-- Foto anak -->
|
||||||
|
<img
|
||||||
|
v-if="childPhoto"
|
||||||
|
:src="childPhoto"
|
||||||
|
alt="Foto Anak"
|
||||||
|
class="relative w-56 h-56 md:w-64 md:h-64 rounded-full shadow-2xl object-cover border-4 border-white mx-auto transform hover:scale-105 transition duration-500 z-10"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!-- Placeholder jika foto belum ada -->
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
class="relative w-56 h-56 md:w-64 md:h-64 rounded-full shadow-2xl bg-gradient-to-br from-red-600 to-blue-600 flex items-center justify-center mx-auto border-4 border-white z-10"
|
||||||
|
>
|
||||||
|
<span class="text-7xl">🕷️</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Nama & Informasi -->
|
||||||
|
<h2 class="text-5xl md:text-6xl font-extrabold text-yellow-300 drop-shadow-lg mb-4 tracking-tight">
|
||||||
|
{{ childName || 'Spider Kid' }}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<p class="text-xl md:text-2xl text-blue-200 mb-3 font-semibold">
|
||||||
|
Berusia {{ age || '?' }} tahun 🎂
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p class="text-lg md:text-xl text-gray-200 mb-8">
|
||||||
|
Putra/Putri dari {{ parentsName || 'Peter Parker & Mary Jane' }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Deskripsi -->
|
||||||
|
<div class="bg-black/70 backdrop-blur-lg rounded-2xl p-6 border border-red-500/60 shadow-xl mb-8">
|
||||||
|
<p class="text-white leading-relaxed text-lg md:text-xl">
|
||||||
|
Dengan kekuatan
|
||||||
|
<span class="text-red-400 font-bold">Spider-Sense</span>
|
||||||
|
yang bergetar, kami mengundang Anda untuk bergabung dalam perayaan ulang tahun ke-
|
||||||
|
{{ age || '?' }} petualangan kami!
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Info tambahan -->
|
||||||
|
<div class="flex flex-wrap gap-4 justify-center animate-bounce-slow">
|
||||||
|
<div
|
||||||
|
class="bg-red-600/90 text-white px-5 py-3 rounded-full text-base font-medium shadow-lg flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<span>🕸️</span>
|
||||||
|
<span>Anak ke-{{ childOrder || '?' }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="bg-blue-600/90 text-white px-5 py-3 rounded-full text-base font-medium shadow-lg flex items-center gap-2"
|
||||||
|
>
|
||||||
|
<span>🎭</span>
|
||||||
|
<span>{{ age || '?' }} Tahun</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref, onMounted } from 'vue'
|
||||||
|
|
||||||
|
const spiders = ref([])
|
||||||
|
|
||||||
|
// 🕷️ Generate posisi dan delay acak
|
||||||
|
onMounted(() => {
|
||||||
|
for (let i = 0; i < 8; i++) {
|
||||||
|
spiders.value.push({
|
||||||
|
left: `${Math.random() * 90}%`,
|
||||||
|
delay: `${i * 1.8}s`,
|
||||||
|
size: `${Math.floor(Math.random() * 16) + 20}px`,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
age: [String, Number],
|
age: [String, Number],
|
||||||
childName: String,
|
childName: String,
|
||||||
|
childOrder: [String, Number],
|
||||||
parentsName: String,
|
parentsName: String,
|
||||||
childPhoto: String
|
childPhoto: String,
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* ✨ Animasi masuk */
|
||||||
|
@keyframes fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fade-in 1.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ✨ Konten naik perlahan */
|
||||||
|
@keyframes slide-up {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(40px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-slide-up {
|
||||||
|
animation: slide-up 1.5s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 🕷️ Laba-laba turun dari atas ke bawah */
|
||||||
|
@keyframes spider-move {
|
||||||
|
0% {
|
||||||
|
transform: translateY(-100px) rotate(0deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
90% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(100vh) rotate(30deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-spider-move {
|
||||||
|
animation: spider-move 8s linear infinite;
|
||||||
|
top: -50px; /* Mulai dari atas layar */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 🕸️ Spider-Man melayang */
|
||||||
|
@keyframes float-slow {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translateY(0px) rotate(0deg);
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
transform: translateY(-15px) rotate(2deg);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-10px) rotate(0deg);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
transform: translateY(-15px) rotate(-2deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-float-slow {
|
||||||
|
animation: float-slow 8s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 🔥 Efek cahaya berdenyut */
|
||||||
|
@keyframes pulse-slow {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 0.6;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.9;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-pulse-slow {
|
||||||
|
animation: pulse-slow 5s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 🩵 Info tambahan bergerak lembut */
|
||||||
|
@keyframes bounce-slow {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
transform: translateY(-6px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.animate-bounce-slow {
|
||||||
|
animation: bounce-slow 3s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 📱 Responsif */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
img[alt='Spider-Man'] {
|
||||||
|
width: 16rem !important;
|
||||||
|
right: 0;
|
||||||
|
top: 15%;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@ -1,21 +1,65 @@
|
|||||||
|
<!-- components/templates/UltahStarter/Landing.vue -->
|
||||||
<template>
|
<template>
|
||||||
<div
|
<section
|
||||||
class="flex flex-col items-center justify-center text-center min-h-screen px-6 py-10 text-white bg-gradient-to-b from-yellow-400 to-orange-500"
|
class="relative flex flex-col items-center justify-center text-center h-screen w-screen text-white bg-gradient-to-b from-red-800 via-blue-900 to-black overflow-hidden"
|
||||||
>
|
>
|
||||||
<h1 class="text-4xl font-bold mb-4 animate-bounce">
|
<!-- 🕸️ BACKGROUND SPIDER WEB -->
|
||||||
🎉 Selamat Datang di Undangan Ulang Tahun 🎉
|
<div class="absolute inset-0 opacity-15 animate-spin-slow">
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 500 500"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
class="w-full h-full"
|
||||||
|
>
|
||||||
|
<g stroke="white" stroke-width="0.4" fill="none">
|
||||||
|
<circle cx="250" cy="250" r="60" />
|
||||||
|
<circle cx="250" cy="250" r="120" />
|
||||||
|
<circle cx="250" cy="250" r="180" />
|
||||||
|
<circle cx="250" cy="250" r="240" />
|
||||||
|
<circle cx="250" cy="250" r="300" />
|
||||||
|
<line x1="250" y1="0" x2="250" y2="500" />
|
||||||
|
<line x1="0" y1="250" x2="500" y2="250" />
|
||||||
|
<line x1="125" y1="0" x2="375" y2="500" />
|
||||||
|
<line x1="375" y1="0" x2="125" y2="500" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 🕷️ SPIDER ICON -->
|
||||||
|
<div class="text-8xl mb-6 animate-pulse-slow drop-shadow-lg">🕷️</div>
|
||||||
|
|
||||||
|
<!-- 🎉 TITLE -->
|
||||||
|
<h1
|
||||||
|
class="text-5xl md:text-6xl font-extrabold mb-6 text-red-400 drop-shadow-[0_0_12px_rgba(255,0,0,0.7)] animate-fade-down"
|
||||||
|
>
|
||||||
|
🕸️ Spider-Man Birthday Invitation 🕸️
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
<p class="text-lg mb-2">Halo, <span class="font-semibold">{{ guestName || 'Tamu Spesial' }}</span>!</p>
|
<!-- 👋 GREETING -->
|
||||||
<p class="text-xl font-semibold mb-8">Kami mengundangmu ke pesta ulang tahun {{ childName }} 🎂</p>
|
<p class="text-xl mb-4 font-semibold animate-fade-up">
|
||||||
|
Halo,
|
||||||
|
<span class="text-red-300 font-bold">
|
||||||
|
{{ guestName || 'Friendly Neighborhood Guest' }}
|
||||||
|
</span>!
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- 🕶️ EVENT INTRO -->
|
||||||
|
<p
|
||||||
|
class="text-2xl font-bold mb-10 text-yellow-100 drop-shadow-md animate-fade-up-delay"
|
||||||
|
>
|
||||||
|
Bergabunglah dalam petualangan ulang tahun {{ childName }}! 🎭
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- 🔘 BUTTON -->
|
||||||
<button
|
<button
|
||||||
@click="$emit('open-invitation')"
|
@click="$emit('open-invitation')"
|
||||||
class="bg-white text-orange-700 font-bold py-3 px-8 rounded-full shadow-lg hover:bg-yellow-100 transition"
|
class="relative bg-gradient-to-r from-red-600 to-blue-600 text-white font-bold py-4 px-10 rounded-full shadow-2xl border-2 border-white/40 overflow-hidden group transition-all duration-300 hover:scale-110"
|
||||||
>
|
>
|
||||||
Buka Undangan
|
<span class="relative z-10">🕷️ Buka Undangan 🕸️</span>
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-white/25 transform -skew-x-12 -translate-x-full group-hover:translate-x-full transition-transform duration-700"
|
||||||
|
></div>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@ -24,3 +68,39 @@ defineProps({
|
|||||||
childName: String
|
childName: String
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* ───────────── Animations ───────────── */
|
||||||
|
@keyframes spin-slow {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
@keyframes pulse-slow {
|
||||||
|
0%,100% { transform: scale(1); }
|
||||||
|
50% { transform: scale(1.15); }
|
||||||
|
}
|
||||||
|
@keyframes fade-down {
|
||||||
|
0% { opacity: 0; transform: translateY(-20px); }
|
||||||
|
100% { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
@keyframes fade-up {
|
||||||
|
0% { opacity: 0; transform: translateY(20px); }
|
||||||
|
100% { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Utility classes */
|
||||||
|
.animate-spin-slow { animation: spin-slow 40s linear infinite; }
|
||||||
|
.animate-pulse-slow { animation: pulse-slow 3s ease-in-out infinite; }
|
||||||
|
.animate-fade-down { animation: fade-down 1s ease-out; }
|
||||||
|
.animate-fade-up { animation: fade-up 1.2s ease-out; }
|
||||||
|
.animate-fade-up-delay { animation: fade-up 1.8s ease-out; }
|
||||||
|
|
||||||
|
/* Pastikan layar penuh */
|
||||||
|
:host, html, body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -1,31 +1,135 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen flex flex-col items-center justify-center bg-gradient-to-br from-orange-300 to-yellow-400 text-white text-center p-8">
|
<section
|
||||||
<h2 class="text-4xl font-bold mb-4">Terima Kasih! 💖</h2>
|
class="relative w-full min-h-screen bg-gradient-to-b from-blue-900 via-red-800 to-black text-white flex flex-col lg:flex-row items-center justify-between overflow-hidden"
|
||||||
<p class="text-lg mb-2">Atas kehadiran dan doa untuk {{ childName }}</p>
|
>
|
||||||
<p class="text-md mb-6">Semoga kebahagiaan selalu menyertai kita semua 🎉</p>
|
<!-- 🌐 Efek jaring latar -->
|
||||||
|
<div class="absolute inset-0 opacity-10 pointer-events-none">
|
||||||
<div class="bg-white/20 rounded-2xl p-4 shadow-md max-w-md">
|
<div class="absolute top-0 left-1/3 w-0.5 h-full bg-gradient-to-b from-blue-200 to-red-200"></div>
|
||||||
<p><strong>Nama Pemesan:</strong> {{ jsonData.nama_pemesan }}</p>
|
<div class="absolute top-0 left-2/3 w-0.5 h-full bg-gradient-to-b from-blue-200 to-red-200"></div>
|
||||||
<p><strong>Email:</strong> {{ jsonData.email }}</p>
|
<div
|
||||||
<p><strong>No Telepon:</strong> {{ jsonData.no_telepon }}</p>
|
class="absolute inset-0 bg-[radial-gradient(circle_at_center,rgba(255,255,255,0.15),transparent_70%)]"
|
||||||
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<!-- 🕷️ Laba-laba animasi -->
|
||||||
@click="reloadPage"
|
<div v-if="showSpider" class="absolute top-10 left-10 text-4xl animate-bounce hidden sm:block">🕷️</div>
|
||||||
class="mt-8 bg-white text-orange-700 py-3 px-6 rounded-full font-semibold shadow hover:bg-yellow-100 transition"
|
<div
|
||||||
|
v-if="showSpider"
|
||||||
|
class="absolute top-20 right-1/4 text-3xl animate-bounce hidden sm:block"
|
||||||
|
style="animation-delay: 0.5s;"
|
||||||
|
>🕸️</div>
|
||||||
|
<div
|
||||||
|
v-if="showSpider"
|
||||||
|
class="absolute bottom-20 left-1/3 text-4xl animate-bounce hidden sm:block"
|
||||||
|
style="animation-delay: 1s;"
|
||||||
|
>🕷️</div>
|
||||||
|
|
||||||
|
<!-- ================= FOTO SPIDERMAN (BACKGROUND UNTUK MOBILE) ================= -->
|
||||||
|
<div class="absolute inset-0 lg:hidden pointer-events-none">
|
||||||
|
<img
|
||||||
|
src="/spiderman.png"
|
||||||
|
alt="Spider-Man"
|
||||||
|
class="absolute inset-0 w-full h-full object-cover object-center opacity-40"
|
||||||
|
@error="onImageError"
|
||||||
|
/>
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-t from-black/70 to-transparent"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= KONTEN TEKS (KIRI) ================= -->
|
||||||
|
<div
|
||||||
|
class="relative z-10 w-full lg:w-1/2 min-h-[50vh] flex flex-col justify-center items-center lg:items-start text-center lg:text-left px-6 lg:px-20 py-12 lg:py-0 space-y-8"
|
||||||
>
|
>
|
||||||
💌 Kembali ke Awal
|
<div class="text-5xl sm:text-6xl animate-bounce">🕷️</div>
|
||||||
</button>
|
|
||||||
</div>
|
<h1
|
||||||
|
class="text-3xl sm:text-5xl lg:text-6xl font-extrabold text-yellow-300 drop-shadow-[0_0_10px_rgba(255,255,0,0.4)]"
|
||||||
|
>
|
||||||
|
Terima Kasih! 💙❤️
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<p class="text-lg sm:text-2xl text-blue-200">
|
||||||
|
Atas kehadiran dan doa <span class="text-yellow-300 font-semibold">spider-power</span> untuk
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p
|
||||||
|
class="text-2xl sm:text-4xl font-bold text-yellow-300 bg-black/40 py-3 sm:py-4 px-6 sm:px-8 rounded-2xl border border-yellow-500/50"
|
||||||
|
>
|
||||||
|
{{ childName || 'Spider-Kid' }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="bg-black/50 backdrop-blur-lg rounded-2xl p-6 border border-red-500/50">
|
||||||
|
<p class="text-base sm:text-lg italic leading-relaxed">
|
||||||
|
"With great age comes great responsibility!
|
||||||
|
Semoga kebahagiaan selalu menyertai kita semua 🕸️"
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Tombol Kembali -->
|
||||||
|
<button
|
||||||
|
@click="reloadPage"
|
||||||
|
class="w-full bg-gradient-to-r from-red-600 to-blue-600 text-white py-4 px-8 rounded-full font-bold shadow-2xl hover:from-red-700 hover:to-blue-700 transition-all duration-300 transform hover:scale-105 border-2 border-white/30 text-lg flex items-center justify-center gap-3"
|
||||||
|
>
|
||||||
|
<span class="text-2xl">🕸️</span>
|
||||||
|
Kembali ke Awal
|
||||||
|
<span class="text-2xl">🕷️</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================= FOTO SPIDERMAN (KANAN UNTUK DESKTOP) ================= -->
|
||||||
|
<div
|
||||||
|
class="hidden lg:flex absolute top-0 right-0 h-full w-1/2 justify-end items-center overflow-hidden"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
src="/spiderman.png"
|
||||||
|
alt="Spider-Man"
|
||||||
|
class="h-full w-auto object-cover object-right transform translate-x-10"
|
||||||
|
@error="onImageError"
|
||||||
|
/>
|
||||||
|
<!-- Efek gradasi ke kiri -->
|
||||||
|
<div class="absolute inset-0 bg-gradient-to-l from-black/80 via-black/50 to-transparent"></div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import { ref, onMounted } from "vue";
|
||||||
|
|
||||||
defineProps({
|
defineProps({
|
||||||
childName: String,
|
childName: String,
|
||||||
jsonData: Object
|
jsonData: {
|
||||||
})
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const reloadPage = () => {
|
const showSpider = ref(false);
|
||||||
window.location.reload()
|
|
||||||
}
|
const reloadPage = () => window.location.reload();
|
||||||
|
|
||||||
|
const onImageError = (e) => {
|
||||||
|
e.target.src =
|
||||||
|
"https://images.unsplash.com/photo-1635805737707-575885ab0820?w=800&h=1000&fit=crop&auto=format";
|
||||||
|
e.target.alt = "Spider-Man Character";
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
setTimeout(() => (showSpider.value = true), 1500);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
@keyframes bounce {
|
||||||
|
0%, 100% { transform: translateY(0); }
|
||||||
|
50% { transform: translateY(-15px); }
|
||||||
|
}
|
||||||
|
.animate-bounce {
|
||||||
|
animation: bounce 2s ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Responsif tambahan agar spiderman selalu kanan dan proporsional */
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
img[alt="Spider-Man"] {
|
||||||
|
object-position: center right;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -85,12 +85,7 @@
|
|||||||
/>
|
/>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
|
||||||
<footer
|
|
||||||
class="relative z-10 bg-white/50 backdrop-blur-md text-center py-4 text-gray-700 font-medium border-t border-yellow-300/50"
|
|
||||||
>
|
|
||||||
<p>© {{ new Date().getFullYear() }}</p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@ -1,180 +1,202 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="min-h-screen bg-gradient-to-br from-yellow-200 via-yellow-300 to-yellow-400 relative overflow-hidden">
|
<div
|
||||||
<!-- Background decorations -->
|
class="relative min-h-screen w-full bg-gradient-to-br from-red-900 via-red-800 to-blue-900 overflow-hidden text-white"
|
||||||
<div class="absolute inset-0 overflow-hidden pointer-events-none">
|
>
|
||||||
<div class="absolute top-10 left-10 w-20 h-20 bg-yellow-500/20 rounded-full blur-xl"></div>
|
<!-- 🕸️ ANIMATED SPIDER-WEB BACKGROUND -->
|
||||||
<div class="absolute top-1/4 right-16 w-16 h-16 bg-orange-500/20 rounded-full blur-lg"></div>
|
<div class="absolute inset-0 opacity-15 animate-spin-slow">
|
||||||
<div class="absolute bottom-20 left-1/4 w-24 h-24 bg-pink-500/15 rounded-full blur-xl"></div>
|
<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" class="w-full h-full">
|
||||||
<div class="absolute bottom-10 right-10 w-20 h-20 bg-red-500/15 rounded-full blur-lg"></div>
|
<g stroke="white" stroke-width="0.4" fill="none">
|
||||||
</div>
|
<circle cx="250" cy="250" r="60" />
|
||||||
|
<circle cx="250" cy="250" r="120" />
|
||||||
<!-- Navigation -->
|
<circle cx="250" cy="250" r="180" />
|
||||||
<nav
|
<circle cx="250" cy="250" r="240" />
|
||||||
v-if="currentSection !== 'landing'"
|
<circle cx="250" cy="250" r="300" />
|
||||||
class="fixed top-6 left-1/2 transform -translate-x-1/2 z-20 animate-fade-in"
|
<line x1="250" y1="0" x2="250" y2="500" />
|
||||||
|
<line x1="0" y1="250" x2="500" y2="250" />
|
||||||
|
<line x1="125" y1="0" x2="375" y2="500" />
|
||||||
|
<line x1="375" y1="0" x2="125" y2="500" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 💫 LIGHT ORBS -->
|
||||||
|
<div class="absolute top-10 left-10 w-32 h-32 bg-red-500/30 rounded-full blur-2xl"></div>
|
||||||
|
<div class="absolute bottom-20 right-10 w-24 h-24 bg-blue-500/25 rounded-full blur-xl"></div>
|
||||||
|
|
||||||
|
<!-- 🕷️ FLOATING ICONS -->
|
||||||
|
<div class="absolute top-16 right-16 text-6xl opacity-20 animate-bounce-slow">🕷️</div>
|
||||||
|
<div class="absolute bottom-20 left-16 text-6xl opacity-20 animate-bounce-slow delay-700">🕸️</div>
|
||||||
|
|
||||||
|
<!-- 🔻 NAVIGATION -->
|
||||||
|
<nav
|
||||||
|
v-if="currentSection !== 'landing'"
|
||||||
|
class="fixed top-6 left-1/2 transform -translate-x-1/2 z-30 animate-fade-in"
|
||||||
|
>
|
||||||
|
<ul
|
||||||
|
class="flex space-x-2 bg-black/70 backdrop-blur-lg px-6 py-3 rounded-full shadow-lg text-sm font-semibold text-white border border-red-500/60"
|
||||||
>
|
>
|
||||||
<ul
|
<li v-for="section in sections" :key="section.key">
|
||||||
class="flex space-x-2 bg-white/70 backdrop-blur-lg px-6 py-3 rounded-full shadow-lg text-sm font-semibold text-gray-800 border border-yellow-200"
|
<button
|
||||||
>
|
@click="switchSection(section.key)"
|
||||||
<li><button @click="switchSection('introduction')" :class="navClass('introduction')" class="px-3 py-1 rounded-full transition-all duration-300">Intro</button></li>
|
:class="navClass(section.key)"
|
||||||
<li><button @click="switchSection('event')" :class="navClass('event')" class="px-3 py-1 rounded-full transition-all duration-300">Event</button></li>
|
class="px-3 py-1 rounded-full transition-all duration-300"
|
||||||
<li><button @click="switchSection('gallery')" :class="navClass('gallery')" class="px-3 py-1 rounded-full transition-all duration-300">Gallery</button></li>
|
>
|
||||||
<li><button @click="switchSection('guestbook')" :class="navClass('guestbook')" class="px-3 py-1 rounded-full transition-all duration-300">Guest Book</button></li>
|
{{ section.label }}
|
||||||
<li><button @click="switchSection('thanks')" :class="navClass('thanks')" class="px-3 py-1 rounded-full transition-all duration-300">Thanks</button></li>
|
</button>
|
||||||
</ul>
|
</li>
|
||||||
</nav>
|
</ul>
|
||||||
|
</nav>
|
||||||
<!-- Tombol Musik -->
|
|
||||||
<div class="fixed bottom-6 left-6 z-30" v-if="currentSection !== 'landing'">
|
<!-- 🎵 MUSIC BUTTON -->
|
||||||
<button
|
<div class="fixed bottom-6 left-6 z-40" v-if="currentSection !== 'landing'">
|
||||||
@click="toggleMusic"
|
<button
|
||||||
class="bg-gradient-to-r from-yellow-500 to-orange-500 hover:from-yellow-600 hover:to-orange-600 p-4 rounded-full text-white shadow-xl transition-all duration-300 hover:scale-110 hover:shadow-2xl"
|
@click="toggleMusic"
|
||||||
>
|
class="bg-gradient-to-r from-red-600 to-blue-600 hover:from-red-700 hover:to-blue-700 p-4 rounded-full shadow-2xl transition-all duration-300 hover:scale-110 animate-pulse-slow"
|
||||||
<span class="text-lg">{{ isPlaying ? '⏸️' : '▶️' }}</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Main Section -->
|
|
||||||
<main
|
|
||||||
class="relative z-10 min-h-screen flex items-center justify-center p-4 transition-all duration-700 ease-in-out"
|
|
||||||
>
|
>
|
||||||
<!-- Landing -->
|
<span class="text-lg">{{ isPlaying ? '⏸️' : '▶️' }}</span>
|
||||||
<Landing
|
</button>
|
||||||
v-if="currentSection === 'landing'"
|
</div>
|
||||||
:childName="formData.nama_panggilan"
|
|
||||||
:guestName="data.nama_tamu"
|
<!-- 🌆 MAIN CONTENT -->
|
||||||
|
<main
|
||||||
|
class="relative z-20 h-screen w-screen flex items-center justify-center transition-all duration-700 ease-in-out overflow-hidden"
|
||||||
|
>
|
||||||
|
<transition name="fade" mode="out-in">
|
||||||
|
<component
|
||||||
|
:is="currentComponent"
|
||||||
|
:key="currentSection"
|
||||||
|
v-bind="componentProps"
|
||||||
@open-invitation="switchSection('introduction')"
|
@open-invitation="switchSection('introduction')"
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Introduction -->
|
|
||||||
<Introduction
|
|
||||||
v-if="currentSection === 'introduction'"
|
|
||||||
:age="formData.umur_yang_dirayakan"
|
|
||||||
:childName="formData.nama_lengkap"
|
|
||||||
:childOrder="formData.anak_ke"
|
|
||||||
:parentsName="`${formData.nama_bapak} & ${formData.nama_ibu}`"
|
|
||||||
:childPhoto="formData.foto && formData.foto.length ? `${backendUrl}/storage/${formData.foto[0]}` : null"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Event -->
|
|
||||||
<Event
|
|
||||||
v-if="currentSection === 'event'"
|
|
||||||
:hari_tanggal_acara="formData.hari_tanggal_acara"
|
|
||||||
:waktu="formData.waktu"
|
|
||||||
:alamat="formData.alamat"
|
|
||||||
:link_gmaps="formData.link_gmaps"
|
|
||||||
:hitung_mundur="formData.hitung_mundur"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- Gallery -->
|
|
||||||
<Gallery v-if="currentSection === 'gallery'" :images="galleryImages" />
|
|
||||||
|
|
||||||
<!-- Guest Book -->
|
|
||||||
<GuestBook
|
|
||||||
v-if="currentSection === 'guestbook'"
|
|
||||||
:guestName="data.nama_tamu"
|
|
||||||
:messages="messages"
|
|
||||||
@addMessage="addMessage"
|
@addMessage="addMessage"
|
||||||
/>
|
/>
|
||||||
|
</transition>
|
||||||
<!-- Thank You -->
|
</main>
|
||||||
<ThankYou
|
</div>
|
||||||
v-if="currentSection === 'thanks'"
|
</template>
|
||||||
:childName="formData.nama_panggilan"
|
|
||||||
:jsonData="formData"
|
<script setup>
|
||||||
/>
|
import { ref, computed } from 'vue'
|
||||||
</main>
|
import { useRuntimeConfig } from '#app'
|
||||||
|
|
||||||
<!-- Footer -->
|
// 🧩 Import Semua Komponen
|
||||||
<footer
|
import Landing from '~/components/templates/UltahStarter/Landing.vue'
|
||||||
class="relative z-10 bg-white/50 backdrop-blur-md text-center py-4 text-gray-700 font-medium border-t border-yellow-300/50"
|
|
||||||
>
|
|
||||||
<p>© {{ new Date().getFullYear() }}</p>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, computed, watchEffect } from 'vue'
|
|
||||||
import { useRuntimeConfig } from '#app'
|
|
||||||
|
|
||||||
// Import Komponen
|
|
||||||
import Landing from '~/components/templates/UltahStarter/Landing.vue'
|
|
||||||
import Introduction from '~/components/templates/UltahStarter/Introduction.vue'
|
import Introduction from '~/components/templates/UltahStarter/Introduction.vue'
|
||||||
import Event from '~/components/templates/UltahStarter/Event.vue'
|
import Event from '~/components/templates/UltahStarter/Event.vue'
|
||||||
import Gallery from '~/components/templates/UltahStarter/Gallery.vue'
|
import Gallery from '~/components/templates/UltahStarter/Gallery.vue'
|
||||||
import ThankYou from '~/components/templates/UltahStarter/ThankYou.vue'
|
import ThankYou from '~/components/templates/UltahStarter/ThankYou.vue'
|
||||||
|
|
||||||
|
// Props dari induk
|
||||||
// Props dari halaman induk
|
const props = defineProps({ data: Object })
|
||||||
const props = defineProps({
|
|
||||||
data: { type: Object, required: true }
|
// URL backend
|
||||||
})
|
const config = useRuntimeConfig()
|
||||||
|
const backendUrl = config.public.apiBaseUrl
|
||||||
// Runtime config (untuk backend URL)
|
|
||||||
const config = useRuntimeConfig()
|
// Data backend
|
||||||
const backendUrl = config.public.apiBaseUrl
|
const formData = computed(() => props.data.form || {})
|
||||||
|
|
||||||
// Data dari backend
|
// ✅ Gambar galeri
|
||||||
const formData = computed(() => props.data.form || {})
|
const galleryImages = computed(() => {
|
||||||
|
const f = formData.value
|
||||||
// ✅ FIX: Galeri gambar (hapus prefix public/, tambahkan /storage/)
|
return [f.foto_1, f.foto_2, f.foto_3, f.foto_4, f.foto_5]
|
||||||
const galleryImages = computed(() => {
|
.filter(Boolean)
|
||||||
const f = formData.value
|
.map(img => `${backendUrl}/storage/${img.replace(/^public\//, '')}`)
|
||||||
const imageList = [
|
})
|
||||||
f.foto_1,
|
|
||||||
f.foto_2,
|
// 🌍 Navigasi section
|
||||||
f.foto_3,
|
const currentSection = ref('landing')
|
||||||
f.foto_4,
|
const sections = [
|
||||||
f.foto_5
|
{ key: 'introduction', label: 'Intro' },
|
||||||
].filter(Boolean)
|
{ key: 'event', label: 'Event' },
|
||||||
|
{ key: 'gallery', label: 'Gallery' },
|
||||||
return imageList.map(img => {
|
{ key: 'thanks', label: 'Thanks' }
|
||||||
const cleanPath = img.replace(/^public\//, '')
|
]
|
||||||
return `${backendUrl}/storage/${cleanPath}`
|
|
||||||
})
|
const switchSection = (section) => (currentSection.value = section)
|
||||||
})
|
|
||||||
|
// 🔊 Musik
|
||||||
watchEffect(() => {
|
const isPlaying = ref(false)
|
||||||
console.log("🧾 formData:", formData.value)
|
const toggleMusic = () => (isPlaying.value = !isPlaying.value)
|
||||||
console.log("🖼️ galleryImages:", galleryImages.value)
|
|
||||||
})
|
// 💬 Buku tamu
|
||||||
|
const messages = ref([])
|
||||||
// Navigasi antar bagian
|
const addMessage = (msg) => messages.value.push(msg)
|
||||||
const currentSection = ref('landing')
|
|
||||||
const switchSection = (s) => (currentSection.value = s)
|
// 🎭 Komponen dinamis berdasarkan section
|
||||||
|
const currentComponent = computed(() => {
|
||||||
// Musik toggle
|
switch (currentSection.value) {
|
||||||
const isPlaying = ref(false)
|
case 'landing': return Landing
|
||||||
const toggleMusic = () => (isPlaying.value = !isPlaying.value)
|
case 'introduction': return Introduction
|
||||||
|
case 'event': return Event
|
||||||
// Buku tamu
|
case 'gallery': return Gallery
|
||||||
const messages = ref([])
|
case 'guestbook': return GuestBook
|
||||||
const addMessage = (msg) => messages.value.push(msg)
|
case 'thanks': return ThankYou
|
||||||
|
default: return Landing
|
||||||
// Style untuk navigasi aktif
|
|
||||||
const navClass = (s) =>
|
|
||||||
currentSection.value === s
|
|
||||||
? 'text-white bg-gradient-to-r from-orange-500 to-yellow-500 shadow-md'
|
|
||||||
: 'hover:text-orange-600 hover:bg-white/50'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
html {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
button {
|
|
||||||
transition: all 0.3s ease;
|
// 🎁 Props untuk tiap komponen
|
||||||
}
|
const componentProps = computed(() => ({
|
||||||
|
childName: formData.value.nama_panggilan,
|
||||||
@keyframes fade-in {
|
guestName: props.data.nama_tamu,
|
||||||
from { opacity: 0; transform: translateY(-10px); }
|
age: formData.value.umur_yang_dirayakan,
|
||||||
to { opacity: 1; transform: translateY(0); }
|
childOrder: formData.value.anak_ke,
|
||||||
}
|
parentsName: `${formData.value.nama_bapak} & ${formData.value.nama_ibu}`,
|
||||||
|
childPhoto: formData.value.foto?.length
|
||||||
.animate-fade-in {
|
? `${backendUrl}/storage/${formData.value.foto[0]}`
|
||||||
animation: fade-in 0.5s ease-out;
|
: null,
|
||||||
}
|
hari_tanggal_acara: formData.value.hari_tanggal_acara,
|
||||||
</style>
|
waktu: formData.value.waktu,
|
||||||
|
alamat: formData.value.alamat,
|
||||||
|
link_gmaps: formData.value.link_gmaps,
|
||||||
|
hitung_mundur: formData.value.hitung_mundur,
|
||||||
|
images: galleryImages.value,
|
||||||
|
messages: messages.value,
|
||||||
|
jsonData: formData.value
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Style aktif navigasi
|
||||||
|
const navClass = (key) =>
|
||||||
|
currentSection.value === key
|
||||||
|
? 'bg-gradient-to-r from-red-600 to-blue-600 text-white shadow-lg'
|
||||||
|
: 'hover:text-red-400 hover:bg-black/40'
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 🌟 Animations */
|
||||||
|
@keyframes spin-slow {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes bounce-slow {
|
||||||
|
0%, 100% { transform: translateY(0); }
|
||||||
|
50% { transform: translateY(-10px); }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-slow {
|
||||||
|
0%, 100% { transform: scale(1); }
|
||||||
|
50% { transform: scale(1.1); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ✨ Fade transition between sections */
|
||||||
|
.fade-enter-active, .fade-leave-active {
|
||||||
|
transition: opacity 0.8s ease, transform 0.8s ease;
|
||||||
|
}
|
||||||
|
.fade-enter-from, .fade-leave-to {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.animate-spin-slow { animation: spin-slow 40s linear infinite; }
|
||||||
|
.animate-bounce-slow { animation: bounce-slow 4s ease-in-out infinite; }
|
||||||
|
.animate-pulse-slow { animation: pulse-slow 3s ease-in-out infinite; }
|
||||||
|
|
||||||
|
.animate-fade-in {
|
||||||
|
animation: fade-in 0.6s ease-out;
|
||||||
|
}
|
||||||
|
@keyframes fade-in {
|
||||||
|
from { opacity: 0; transform: translateY(-10px); }
|
||||||
|
to { opacity: 1; transform: translateY(0); }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
BIN
proyek-frontend/public/balon1.png
Normal file
BIN
proyek-frontend/public/balon1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 MiB |
BIN
proyek-frontend/public/balon2.png
Normal file
BIN
proyek-frontend/public/balon2.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 846 KiB |
BIN
proyek-frontend/public/balon3.png
Normal file
BIN
proyek-frontend/public/balon3.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 MiB |
BIN
proyek-frontend/public/man.png
Normal file
BIN
proyek-frontend/public/man.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 115 KiB |
BIN
proyek-frontend/public/spiderman.png
Normal file
BIN
proyek-frontend/public/spiderman.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 300 KiB |
Loading…
Reference in New Issue
Block a user