Undangan/proyek-frontend/app/components/undangan/undangan-ulang-tahun-starter.vue

180 lines
6.4 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

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

<template>
<div class="min-h-screen bg-gradient-to-br from-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>
<!-- Navigation -->
<nav
v-if="currentSection !== 'landing'"
class="fixed top-6 left-1/2 transform -translate-x-1/2 z-20 animate-fade-in"
>
<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>
<!-- 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"
>
<!-- Landing -->
<Landing
v-if="currentSection === 'landing'"
:childName="formData.nama_panggilan"
:guestName="data.nama_tamu"
@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"
/>
<!-- Thank You -->
<ThankYou
v-if="currentSection === 'thanks'"
:childName="formData.nama_panggilan"
:jsonData="formData"
/>
</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>
</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 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 halaman induk
const props = defineProps({
data: { type: Object, required: true }
})
// Runtime config (untuk backend URL)
const config = useRuntimeConfig()
const backendUrl = config.public.apiBaseUrl
// Data dari backend
const formData = computed(() => props.data.form || {})
// ✅ 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)
return imageList.map(img => {
const cleanPath = img.replace(/^public\//, '')
return `${backendUrl}/storage/${cleanPath}`
})
})
watchEffect(() => {
console.log("🧾 formData:", formData.value)
console.log("🖼️ galleryImages:", galleryImages.value)
})
// Navigasi antar bagian
const currentSection = ref('landing')
const switchSection = (s) => (currentSection.value = s)
// 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;
}
button {
transition: all 0.3s ease;
}
@keyframes fade-in {
from { opacity: 0; transform: translateY(-10px); }
to { opacity: 1; transform: translateY(0); }
}
.animate-fade-in {
animation: fade-in 0.5s ease-out;
}
</style>