[Update] Starter ultah
This commit is contained in:
parent
c4b482b514
commit
566f3c0df8
@ -1,35 +1,138 @@
|
||||
<template>
|
||||
<div class="min-h-screen flex flex-col items-center justify-center text-center bg-orange-100 py-10 px-6">
|
||||
<h2 class="text-3xl font-bold text-orange-700 mb-4">📅 Detail Acara</h2>
|
||||
<section
|
||||
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">
|
||||
<p class="mb-2"><strong>Hari & Tanggal:</strong> {{ formatDate(hari_tanggal_acara) }}</p>
|
||||
<p class="mb-2"><strong>Waktu:</strong> {{ waktu }}</p>
|
||||
<p class="mb-2"><strong>Alamat:</strong> {{ alamat }}</p>
|
||||
<!-- Kotak konten utama -->
|
||||
<div
|
||||
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"
|
||||
>
|
||||
<!-- 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
|
||||
v-if="link_gmaps"
|
||||
:href="link_gmaps"
|
||||
target="_blank"
|
||||
class="inline-block mt-4 bg-orange-600 text-white py-2 px-6 rounded-full hover:bg-orange-700 transition"
|
||||
<!-- Waktu -->
|
||||
<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">
|
||||
<div class="text-3xl">⏰</div>
|
||||
<div class="text-left">
|
||||
<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
|
||||
</a>
|
||||
🗺️ Link Maps Menyusul
|
||||
</button>
|
||||
</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>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
|
||||
defineProps({
|
||||
hari_tanggal_acara: String,
|
||||
waktu: String,
|
||||
alamat: String,
|
||||
link_gmaps: String
|
||||
})
|
||||
link_gmaps: String,
|
||||
});
|
||||
|
||||
const showSpider = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
setTimeout(() => {
|
||||
showSpider.value = true;
|
||||
}, 2000);
|
||||
});
|
||||
|
||||
const formatDate = (dateStr) => {
|
||||
if (!dateStr) return '-'
|
||||
const d = new Date(dateStr)
|
||||
return d.toLocaleDateString('id-ID', { weekday: 'long', day: 'numeric', month: 'long', year: 'numeric' })
|
||||
}
|
||||
if (!dateStr) return "Akan diumumkan";
|
||||
try {
|
||||
const d = new Date(dateStr);
|
||||
return d.toLocaleDateString("id-ID", {
|
||||
weekday: "long",
|
||||
day: "numeric",
|
||||
month: "long",
|
||||
year: "numeric",
|
||||
});
|
||||
} catch {
|
||||
return dateStr;
|
||||
}
|
||||
};
|
||||
</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>
|
||||
<div class="min-h-screen bg-yellow-100 py-10 px-4">
|
||||
<h2 class="text-3xl font-bold text-orange-700 text-center mb-8">📸 Galeri Foto</h2>
|
||||
<section
|
||||
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
|
||||
v-for="(img, index) in images"
|
||||
: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>
|
||||
|
||||
<!-- 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>
|
||||
|
||||
<script setup>
|
||||
@ -22,3 +75,30 @@ defineProps({
|
||||
}
|
||||
})
|
||||
</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>
|
||||
<div class="flex flex-col items-center text-center min-h-screen bg-yellow-200 py-12 px-6">
|
||||
<img
|
||||
v-if="childPhoto"
|
||||
:src="childPhoto"
|
||||
alt="Foto Anak"
|
||||
class="w-40 h-40 rounded-full shadow-lg mb-6 object-cover border-4 border-yellow-500"
|
||||
/>
|
||||
<section
|
||||
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"
|
||||
>
|
||||
<!-- 🕸️ Background grid lembut -->
|
||||
<div class="absolute inset-0 opacity-10 pointer-events-none">
|
||||
<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>
|
||||
<p class="text-lg text-gray-700 mb-4">Berusia {{ age }} tahun 🎂</p>
|
||||
<p class="text-md text-gray-600 mb-6">Putra/Putri dari {{ parentsName }}</p>
|
||||
<!-- 🕷️ Laba-laba animasi turun dari atas -->
|
||||
<div
|
||||
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
|
||||
ke-{{ age }}!
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- ✨ Konten utama -->
|
||||
<div class="relative z-10 w-full px-6 max-w-2xl mt-16 md:mt-0 animate-slide-up">
|
||||
<!-- Foto Anak -->
|
||||
<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>
|
||||
|
||||
<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({
|
||||
age: [String, Number],
|
||||
childName: String,
|
||||
childOrder: [String, Number],
|
||||
parentsName: String,
|
||||
childPhoto: String
|
||||
childPhoto: String,
|
||||
})
|
||||
</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>
|
||||
<div
|
||||
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"
|
||||
<section
|
||||
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">
|
||||
🎉 Selamat Datang di Undangan Ulang Tahun 🎉
|
||||
<!-- 🕸️ BACKGROUND SPIDER WEB -->
|
||||
<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>
|
||||
|
||||
<p class="text-lg mb-2">Halo, <span class="font-semibold">{{ guestName || 'Tamu Spesial' }}</span>!</p>
|
||||
<p class="text-xl font-semibold mb-8">Kami mengundangmu ke pesta ulang tahun {{ childName }} 🎂</p>
|
||||
<!-- 👋 GREETING -->
|
||||
<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
|
||||
@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>
|
||||
</div>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
@ -24,3 +68,39 @@ defineProps({
|
||||
childName: String
|
||||
})
|
||||
</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>
|
||||
<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">
|
||||
<h2 class="text-4xl font-bold mb-4">Terima Kasih! 💖</h2>
|
||||
<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>
|
||||
|
||||
<div class="bg-white/20 rounded-2xl p-4 shadow-md max-w-md">
|
||||
<p><strong>Nama Pemesan:</strong> {{ jsonData.nama_pemesan }}</p>
|
||||
<p><strong>Email:</strong> {{ jsonData.email }}</p>
|
||||
<p><strong>No Telepon:</strong> {{ jsonData.no_telepon }}</p>
|
||||
<section
|
||||
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"
|
||||
>
|
||||
<!-- 🌐 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>
|
||||
|
||||
<button
|
||||
@click="reloadPage"
|
||||
class="mt-8 bg-white text-orange-700 py-3 px-6 rounded-full font-semibold shadow hover:bg-yellow-100 transition"
|
||||
<!-- 🕷️ Laba-laba animasi -->
|
||||
<div v-if="showSpider" class="absolute top-10 left-10 text-4xl animate-bounce hidden sm:block">🕷️</div>
|
||||
<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
|
||||
</button>
|
||||
</div>
|
||||
<div class="text-5xl sm:text-6xl animate-bounce">🕷️</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>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from "vue";
|
||||
|
||||
defineProps({
|
||||
childName: String,
|
||||
jsonData: Object
|
||||
})
|
||||
jsonData: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
|
||||
const reloadPage = () => {
|
||||
window.location.reload()
|
||||
}
|
||||
const showSpider = ref(false);
|
||||
|
||||
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>
|
||||
|
||||
<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>
|
||||
|
||||
@ -1,180 +1,202 @@
|
||||
<template>
|
||||
<div class="min-h-screen bg-gradient-to-br from-yellow-200 via-yellow-300 to-yellow-400 relative overflow-hidden">
|
||||
<!-- Background decorations -->
|
||||
<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>
|
||||
<div class="absolute top-1/4 right-16 w-16 h-16 bg-orange-500/20 rounded-full blur-lg"></div>
|
||||
<div class="absolute bottom-20 left-1/4 w-24 h-24 bg-pink-500/15 rounded-full blur-xl"></div>
|
||||
<div class="absolute bottom-10 right-10 w-20 h-20 bg-red-500/15 rounded-full blur-lg"></div>
|
||||
</div>
|
||||
<div
|
||||
class="relative min-h-screen w-full bg-gradient-to-br from-red-900 via-red-800 to-blue-900 overflow-hidden text-white"
|
||||
>
|
||||
<!-- 🕸️ ANIMATED SPIDER-WEB BACKGROUND -->
|
||||
<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>
|
||||
|
||||
<!-- Navigation -->
|
||||
<nav
|
||||
v-if="currentSection !== 'landing'"
|
||||
class="fixed top-6 left-1/2 transform -translate-x-1/2 z-20 animate-fade-in"
|
||||
<!-- 💫 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
|
||||
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"
|
||||
>
|
||||
<li><button @click="switchSection('introduction')" :class="navClass('introduction')" class="px-3 py-1 rounded-full transition-all duration-300">Intro</button></li>
|
||||
<li><button @click="switchSection('event')" :class="navClass('event')" class="px-3 py-1 rounded-full transition-all duration-300">Event</button></li>
|
||||
<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>
|
||||
<li><button @click="switchSection('thanks')" :class="navClass('thanks')" class="px-3 py-1 rounded-full transition-all duration-300">Thanks</button></li>
|
||||
</ul>
|
||||
</nav>
|
||||
<li v-for="section in sections" :key="section.key">
|
||||
<button
|
||||
@click="switchSection(section.key)"
|
||||
:class="navClass(section.key)"
|
||||
class="px-3 py-1 rounded-full transition-all duration-300"
|
||||
>
|
||||
{{ section.label }}
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<!-- Tombol Musik -->
|
||||
<div class="fixed bottom-6 left-6 z-30" v-if="currentSection !== 'landing'">
|
||||
<button
|
||||
@click="toggleMusic"
|
||||
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"
|
||||
>
|
||||
<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"
|
||||
<!-- 🎵 MUSIC BUTTON -->
|
||||
<div class="fixed bottom-6 left-6 z-40" v-if="currentSection !== 'landing'">
|
||||
<button
|
||||
@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"
|
||||
>
|
||||
<!-- Landing -->
|
||||
<Landing
|
||||
v-if="currentSection === 'landing'"
|
||||
:childName="formData.nama_panggilan"
|
||||
:guestName="data.nama_tamu"
|
||||
<span class="text-lg">{{ isPlaying ? '⏸️' : '▶️' }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 🌆 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')"
|
||||
/>
|
||||
|
||||
<!-- 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"
|
||||
/>
|
||||
</transition>
|
||||
</main>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- Thank You -->
|
||||
<ThankYou
|
||||
v-if="currentSection === 'thanks'"
|
||||
:childName="formData.nama_panggilan"
|
||||
:jsonData="formData"
|
||||
/>
|
||||
</main>
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { useRuntimeConfig } from '#app'
|
||||
|
||||
<!-- 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>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, watchEffect } from 'vue'
|
||||
import { useRuntimeConfig } from '#app'
|
||||
|
||||
// Import Komponen
|
||||
import Landing from '~/components/templates/UltahStarter/Landing.vue'
|
||||
// 🧩 Import Semua Komponen
|
||||
import Landing from '~/components/templates/UltahStarter/Landing.vue'
|
||||
import Introduction from '~/components/templates/UltahStarter/Introduction.vue'
|
||||
import Event from '~/components/templates/UltahStarter/Event.vue'
|
||||
import Gallery from '~/components/templates/UltahStarter/Gallery.vue'
|
||||
import ThankYou from '~/components/templates/UltahStarter/ThankYou.vue'
|
||||
|
||||
// Props dari induk
|
||||
const props = defineProps({ data: Object })
|
||||
|
||||
// Props dari halaman induk
|
||||
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()
|
||||
const backendUrl = config.public.apiBaseUrl
|
||||
// Data backend
|
||||
const formData = computed(() => props.data.form || {})
|
||||
|
||||
// Data dari backend
|
||||
const formData = computed(() => props.data.form || {})
|
||||
// ✅ Gambar galeri
|
||||
const galleryImages = computed(() => {
|
||||
const f = formData.value
|
||||
return [f.foto_1, f.foto_2, f.foto_3, f.foto_4, f.foto_5]
|
||||
.filter(Boolean)
|
||||
.map(img => `${backendUrl}/storage/${img.replace(/^public\//, '')}`)
|
||||
})
|
||||
|
||||
// ✅ FIX: Galeri gambar (hapus prefix public/, tambahkan /storage/)
|
||||
const galleryImages = computed(() => {
|
||||
const f = formData.value
|
||||
const imageList = [
|
||||
f.foto_1,
|
||||
f.foto_2,
|
||||
f.foto_3,
|
||||
f.foto_4,
|
||||
f.foto_5
|
||||
].filter(Boolean)
|
||||
// 🌍 Navigasi section
|
||||
const currentSection = ref('landing')
|
||||
const sections = [
|
||||
{ key: 'introduction', label: 'Intro' },
|
||||
{ key: 'event', label: 'Event' },
|
||||
{ key: 'gallery', label: 'Gallery' },
|
||||
{ key: 'thanks', label: 'Thanks' }
|
||||
]
|
||||
|
||||
return imageList.map(img => {
|
||||
const cleanPath = img.replace(/^public\//, '')
|
||||
return `${backendUrl}/storage/${cleanPath}`
|
||||
})
|
||||
})
|
||||
const switchSection = (section) => (currentSection.value = section)
|
||||
|
||||
watchEffect(() => {
|
||||
console.log("🧾 formData:", formData.value)
|
||||
console.log("🖼️ galleryImages:", galleryImages.value)
|
||||
})
|
||||
// 🔊 Musik
|
||||
const isPlaying = ref(false)
|
||||
const toggleMusic = () => (isPlaying.value = !isPlaying.value)
|
||||
|
||||
// Navigasi antar bagian
|
||||
const currentSection = ref('landing')
|
||||
const switchSection = (s) => (currentSection.value = s)
|
||||
// 💬 Buku tamu
|
||||
const messages = ref([])
|
||||
const addMessage = (msg) => messages.value.push(msg)
|
||||
|
||||
// Musik toggle
|
||||
const isPlaying = ref(false)
|
||||
const toggleMusic = () => (isPlaying.value = !isPlaying.value)
|
||||
|
||||
// Buku tamu
|
||||
const messages = ref([])
|
||||
const addMessage = (msg) => messages.value.push(msg)
|
||||
|
||||
// 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;
|
||||
// 🎭 Komponen dinamis berdasarkan section
|
||||
const currentComponent = computed(() => {
|
||||
switch (currentSection.value) {
|
||||
case 'landing': return Landing
|
||||
case 'introduction': return Introduction
|
||||
case 'event': return Event
|
||||
case 'gallery': return Gallery
|
||||
case 'guestbook': return GuestBook
|
||||
case 'thanks': return ThankYou
|
||||
default: return Landing
|
||||
}
|
||||
})
|
||||
|
||||
button {
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
// 🎁 Props untuk tiap komponen
|
||||
const componentProps = computed(() => ({
|
||||
childName: formData.value.nama_panggilan,
|
||||
guestName: props.data.nama_tamu,
|
||||
age: formData.value.umur_yang_dirayakan,
|
||||
childOrder: formData.value.anak_ke,
|
||||
parentsName: `${formData.value.nama_bapak} & ${formData.value.nama_ibu}`,
|
||||
childPhoto: formData.value.foto?.length
|
||||
? `${backendUrl}/storage/${formData.value.foto[0]}`
|
||||
: null,
|
||||
hari_tanggal_acara: formData.value.hari_tanggal_acara,
|
||||
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
|
||||
}))
|
||||
|
||||
@keyframes fade-in {
|
||||
from { opacity: 0; transform: translateY(-10px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
}
|
||||
// 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>
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fade-in 0.5s ease-out;
|
||||
}
|
||||
</style>
|
||||
<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/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