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

248 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- components/forms/KhitanForm.vue -->
<template>
<div class="h-screen w-full relative bg-gradient-to-br from-blue-900 via-blue-800 to-blue-900 overflow-hidden">
<!-- Background Pattern -->
<div class="absolute inset-0 bg-pattern opacity-30"></div>
<!-- Decorative Lanterns -->
<div class="absolute top-8 left-8 animate-sway">
<div class="w-16 h-20 relative">
<!-- Lantern Chain -->
<div class="absolute top-0 left-1/2 w-0.5 h-8 bg-yellow-400 transform -translate-x-1/2"></div>
<!-- Lantern Body -->
<div class="absolute bottom-0 w-full">
<svg viewBox="0 0 64 80" class="w-full h-full">
<defs>
<linearGradient id="lanternGradient" x1="0%" y1="0%" x2="100%" y2="0%">
<stop offset="0%" style="stop-color:#FFD700"/>
<stop offset="50%" style="stop-color:#FFA500"/>
<stop offset="100%" style="stop-color:#FFD700"/>
</linearGradient>
</defs>
<ellipse cx="32" cy="15" rx="28" ry="12" fill="url(#lanternGradient)"/>
<rect x="8" y="12" width="48" height="40" rx="24" fill="url(#lanternGradient)" opacity="0.9"/>
<ellipse cx="32" cy="55" rx="28" ry="12" fill="url(#lanternGradient)"/>
<rect x="20" y="20" width="24" height="4" rx="2" fill="#1e40af" opacity="0.6"/>
<rect x="20" y="30" width="24" height="4" rx="2" fill="#1e40af" opacity="0.6"/>
<rect x="20" y="40" width="24" height="4" rx="2" fill="#1e40af" opacity="0.6"/>
</svg>
</div>
</div>
</div>
<div class="absolute top-8 right-8 animate-sway animation-delay-1000">
<div class="w-16 h-20 relative">
<!-- Lantern Chain -->
<div class="absolute top-0 left-1/2 w-0.5 h-8 bg-yellow-400 transform -translate-x-1/2"></div>
<!-- Lantern Body -->
<div class="absolute bottom-0 w-full">
<svg viewBox="0 0 64 80" class="w-full h-full">
<!-- pakai gradient yang sama -->
<use href="#lanternGradient"></use>
<ellipse cx="32" cy="15" rx="28" ry="12" fill="url(#lanternGradient)"/>
<rect x="8" y="12" width="48" height="40" rx="24" fill="url(#lanternGradient)" opacity="0.9"/>
<ellipse cx="32" cy="55" rx="28" ry="12" fill="url(#lanternGradient)"/>
<rect x="20" y="20" width="24" height="4" rx="2" fill="#1e40af" opacity="0.6"/>
<rect x="20" y="30" width="24" height="4" rx="2" fill="#1e40af" opacity="0.6"/>
<rect x="20" y="40" width="24" height="4" rx="2" fill="#1e40af" opacity="0.6"/>
</svg>
</div>
</div>
</div>
<!-- Main Content -->
<div class="relative z-10 h-full flex items-center justify-center px-6">
<div class="text-center max-w-6xl mx-auto">
<!-- Bismillah -->
<div class="mb-8 animate-fade-in-down">
<h1 class="text-yellow-400 text-2xl md:text-3xl font-bold mb-6 arabic-text">
بِسْمِ اللَّهِ الرَّحْمَٰنِ الرَّحِيمِ
</h1>
</div>
<!-- Event Description -->
<div class="mb-8 animate-fade-in-up animation-delay-300">
<p class="text-white text-base md:text-lg leading-relaxed max-w-4xl mx-auto mb-6">
Dengan memohon rahmat dan ridho Allah Subhanahu wa Ta'ala, kami<br>
mengundang Bapak/Ibu/Saudara/i untuk hadir dan berbagi kebahagiaan<br>
dalam acara Khitanan putra kami tercinta, yang insya Allah akan<br>
diselenggarakan pada :
</p>
</div>
<!-- Event Details Container -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-8">
<!-- Date & Countdown -->
<div class="animate-fade-in-left animation-delay-600">
<div class="bg-white/10 backdrop-blur-sm rounded-2xl p-8 border border-yellow-400/30">
<h3 class="text-yellow-400 text-2xl font-bold mb-6 font-script">
Jum'at/Sabtu
</h3>
<div class="text-white text-3xl md:text-4xl font-bold mb-8">
{{ eventDate }}
</div>
<!-- Countdown Timer -->
<div class="grid grid-cols-4 gap-4 mb-6">
<div
v-for="(item, index) in countdownItems"
:key="index"
class="bg-blue-800/50 rounded-lg p-4 text-center border border-yellow-400/20"
>
<div class="text-yellow-400 text-2xl md:text-3xl font-bold">
{{ item.value }}
</div>
<div class="text-white text-sm uppercase tracking-wider">
{{ item.label }}
</div>
</div>
</div>
<!-- Add to Calendar Button -->
<button
@click="addToCalendar"
class="bg-yellow-400 hover:bg-yellow-500 text-blue-900 px-6 py-3 rounded-full font-semibold transition-all duration-300 transform hover:scale-105"
>
Add to Calendar
</button>
</div>
</div>
<!-- Location & Map -->
<div class="animate-fade-in-right animation-delay-600">
<div class="bg-white/10 backdrop-blur-sm rounded-2xl p-8 border border-yellow-400/30">
<div class="text-white mb-6">
<p class="text-lg mb-2">Pukul {{ eventTime }}</p>
<p class="text-lg mb-2">{{ eventLocation }}</p>
<p class="text-base opacity-80">{{ eventAddress }}</p>
</div>
<!-- Map Placeholder -->
<div class="bg-gray-300 rounded-lg h-32 mb-6 relative overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-r from-blue-400 to-blue-600 opacity-50"></div>
<div class="absolute inset-0 flex items-center justify-center">
<Icon name="lucide:map-pin" class="w-8 h-8 text-white" />
</div>
<img
src="https://via.placeholder.com/400x200/4299e1/ffffff?text=Map+Preview"
alt="Location Map"
class="w-full h-full object-cover opacity-80"
/>
</div>
<!-- Direction Button -->
<button
@click="openMap"
class="bg-yellow-400 hover:bg-yellow-500 text-blue-900 px-6 py-3 rounded-full font-semibold transition-all duration-300 transform hover:scale-105"
>
Direction
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Decorative Elements -->
<div class="absolute inset-0 pointer-events-none overflow-hidden">
<div class="absolute top-0 left-1/2 transform -translate-x-1/2">
<svg viewBox="0 0 200 100" class="w-48 h-24 text-yellow-400 opacity-20">
<path d="M100 20 Q120 0 140 20 Q160 40 140 60 Q120 40 100 60 Q80 40 60 60 Q40 40 60 20 Q80 0 100 20" fill="currentColor"/>
</svg>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue'
// Props
const props = defineProps({
data: {
type: Object,
default: () => ({})
}
})
// computed agar template tidak merah
const eventDate = computed(() => props.data.eventDate || '20-21 Juni 2025')
const eventTime = computed(() => props.data.eventTime || '09.00 WIB s.d Selesai')
const eventLocation = computed(() => props.data.eventLocation || 'TMC Mangrove, Tanjung Pasir')
const eventAddress = computed(() => props.data.eventAddress || 'Desa Tanjung Pasir')
const childPhoto = computed(() => props.data.childPhoto || '/images/khitan/child-photo.jpg')
const childName = computed(() => props.data.childName || 'Satria Huda Dinata')
const childTitle = computed(() => props.data.childTitle || 'SATRIA HUDA DINATA')
const childSubtitle = computed(() => props.data.childSubtitle || 'Putra Ke Dua Dari')
const fatherName = computed(() => props.data.fatherName || 'Bpk H. Munawar Huda, S.H.')
const motherName = computed(() => props.data.motherName || 'Ibu Hj. Dinah, A.M.Keb')
// countdown
const countdown = ref({ days: 7, hours: 11, minutes: 21, seconds: 45 })
let countdownInterval = null
const countdownItems = computed(() => [
{ value: String(countdown.value.days).padStart(2, '0'), label: 'D' },
{ value: String(countdown.value.hours).padStart(2, '0'), label: 'H' },
{ value: String(countdown.value.minutes).padStart(2, '0'), label: 'M' },
{ value: String(countdown.value.seconds).padStart(2, '0'), label: 'S' }
])
const updateCountdown = () => {
const eventDateObj = new Date('2025-06-20T09:00:00')
const now = new Date()
const diff = eventDateObj.getTime() - now.getTime()
if (diff > 0) {
countdown.value = {
days: Math.floor(diff / (1000 * 60 * 60 * 24)),
hours: Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
minutes: Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)),
seconds: Math.floor((diff % (1000 * 60)) / 1000)
}
} else {
countdown.value = { days: 0, hours: 0, minutes: 0, seconds: 0 }
if (countdownInterval) clearInterval(countdownInterval)
}
}
const addToCalendar = () => {
const eventDetails = {
title: `Tasyakuran Khitan ${childName.value}`,
start: '20250620T090000Z',
end: '20250621T170000Z',
description: 'Undangan Tasyakuran Khitan',
location: eventLocation.value
}
const url = `https://calendar.google.com/calendar/render?action=TEMPLATE&text=${encodeURIComponent(eventDetails.title)}&dates=${eventDetails.start}/${eventDetails.end}&details=${encodeURIComponent(eventDetails.description)}&location=${encodeURIComponent(eventDetails.location)}`
window.open(url, '_blank')
}
const openMap = () => {
const location = encodeURIComponent(eventLocation.value)
window.open(`https://maps.google.com/maps?q=${location}`, '_blank')
}
const handleImageError = (e) => {
e.target.src = 'https://via.placeholder.com/128x128/4299e1/ffffff?text=Photo'
}
onMounted(() => {
updateCountdown()
countdownInterval = setInterval(updateCountdown, 1000)
})
onUnmounted(() => {
if (countdownInterval) clearInterval(countdownInterval)
})
</script>
<style scoped>
/* ... tetap sama dengan punyamu, kecuali hapus selector .grid-cols-1.lg\:grid-cols-2 */
</style>