add
This commit is contained in:
parent
8dbe97a4b0
commit
b27f6a47fb
@ -4,6 +4,9 @@ import { ref, computed } from 'vue'
|
|||||||
// ID template yang mau ditampilkan
|
// ID template yang mau ditampilkan
|
||||||
const selectedIds = [3, 6, 9]
|
const selectedIds = [3, 6, 9]
|
||||||
|
|
||||||
|
const config = useRuntimeConfig()
|
||||||
|
const backendUrl = config.public.apiBaseUrl
|
||||||
|
|
||||||
// State dropdown
|
// State dropdown
|
||||||
const openDropdownId = ref(null)
|
const openDropdownId = ref(null)
|
||||||
const toggleDropdown = (templateId) => {
|
const toggleDropdown = (templateId) => {
|
||||||
@ -87,7 +90,7 @@ const formMapping = {
|
|||||||
|
|
||||||
|
|
||||||
// Fetch data template dari backend (nama_template, harga, kategori, foto)
|
// Fetch data template dari backend (nama_template, harga, kategori, foto)
|
||||||
const { data: templatesData, error } = await useFetch('http://localhost:8000/api/templates')
|
const { data: templatesData, error } = await useFetch(`${backendUrl}/api/templates`)
|
||||||
console.log(templatesData.value)
|
console.log(templatesData.value)
|
||||||
|
|
||||||
// Mapping template: gabungkan backend + paket & fitur hardcode
|
// Mapping template: gabungkan backend + paket & fitur hardcode
|
||||||
@ -134,7 +137,7 @@ const templates = computed(() =>
|
|||||||
<div v-for="t in templates" :key="t.id"
|
<div v-for="t in templates" :key="t.id"
|
||||||
class="bg-white border rounded-lg overflow-hidden shadow-md hover:shadow-xl transition-shadow duration-300">
|
class="bg-white border rounded-lg overflow-hidden shadow-md hover:shadow-xl transition-shadow duration-300">
|
||||||
<!-- Gambar -->
|
<!-- Gambar -->
|
||||||
<img :src="t.foto ? (t.foto.startsWith('http') ? t.foto : `http://localhost:8000${t.foto}`) : '/default.jpg'" :alt="t.nama_template" class="w-full h-48 object-cover" />
|
<img :src="t.foto ? (t.foto.startsWith('http') ? t.foto : `${backendUrl}${t.foto}`) : '/default.jpg'" :alt="t.nama_template" class="w-full h-48 object-cover" />
|
||||||
|
|
||||||
|
|
||||||
<!-- Body -->
|
<!-- Body -->
|
||||||
@ -180,7 +183,7 @@ const templates = computed(() =>
|
|||||||
class="w-full bg-white border border-gray-300 text-gray-800 font-semibold py-2 px-4 rounded-lg hover:bg-gray-100 transition-colors">
|
class="w-full bg-white border border-gray-300 text-gray-800 font-semibold py-2 px-4 rounded-lg hover:bg-gray-100 transition-colors">
|
||||||
Preview
|
Preview
|
||||||
</button>
|
</button>
|
||||||
<NuxtLink :to="`form/${t.formPath}`"
|
<NuxtLink :to="`form/${t.kategori}/${t.paket}`"
|
||||||
class="w-full bg-blue-600 text-white font-semibold py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors text-center">
|
class="w-full bg-blue-600 text-white font-semibold py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors text-center">
|
||||||
Order
|
Order
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
|
|||||||
@ -121,7 +121,7 @@
|
|||||||
class="w-full bg-white border border-gray-300 text-gray-800 font-semibold py-2 px-4 rounded-lg hover:bg-gray-100 transition-colors">
|
class="w-full bg-white border border-gray-300 text-gray-800 font-semibold py-2 px-4 rounded-lg hover:bg-gray-100 transition-colors">
|
||||||
Preview
|
Preview
|
||||||
</button>
|
</button>
|
||||||
<NuxtLink :to="`form/${t.formPath}`"
|
<NuxtLink :to="`form/${t.kategori}/${t.paket.toLowerCase()}`"
|
||||||
class="w-full bg-blue-600 text-white font-semibold py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors text-center">
|
class="w-full bg-blue-600 text-white font-semibold py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors text-center">
|
||||||
Order
|
Order
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
@ -147,15 +147,8 @@ const emit = defineEmits(['category-selected', 'template-selected'])
|
|||||||
const categories = ref([])
|
const categories = ref([])
|
||||||
const isLoading = ref(true)
|
const isLoading = ref(true)
|
||||||
const error = ref(null)
|
const error = ref(null)
|
||||||
|
const config = useRuntimeConfig()
|
||||||
|
const backendUrl = config.public.apiBaseUrl
|
||||||
const formMapping = {
|
|
||||||
'Undangan Pernikahan Premium': '/form/pernikahan/b',
|
|
||||||
'Undangan Minimalis': '/form/pernikahan/a',
|
|
||||||
'Undangan Ulang Tahun Premium': '/form/ulang-tahun/a',
|
|
||||||
'Undangan Khitan Premium': '/form/khitan/a',
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// state dropdown fitur
|
// state dropdown fitur
|
||||||
const openDropdownId = ref(null)
|
const openDropdownId = ref(null)
|
||||||
@ -163,8 +156,6 @@ const toggleDropdown = (templateId) => {
|
|||||||
openDropdownId.value = openDropdownId.value === templateId ? null : templateId
|
openDropdownId.value = openDropdownId.value === templateId ? null : templateId
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Paket & fitur hardcode
|
// Paket & fitur hardcode
|
||||||
const paketData = [
|
const paketData = [
|
||||||
{
|
{
|
||||||
@ -215,8 +206,10 @@ const fetchCategories = async () => {
|
|||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
error.value = null
|
error.value = null
|
||||||
try {
|
try {
|
||||||
const res = await $fetch('http://localhost:8000/api/kategoris')
|
const res = await $fetch(`${backendUrl}/api/kategoris`)
|
||||||
categories.value = res
|
categories.value = res
|
||||||
|
console.log("Kategori", categories.value);
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
error.value = 'Gagal memuat kategori.'
|
error.value = 'Gagal memuat kategori.'
|
||||||
@ -232,7 +225,7 @@ const isLoadingTemplates = ref(true)
|
|||||||
const fetchTemplates = async () => {
|
const fetchTemplates = async () => {
|
||||||
isLoadingTemplates.value = true
|
isLoadingTemplates.value = true
|
||||||
try {
|
try {
|
||||||
const res = await $fetch('http://localhost:8000/api/templates')
|
const res = await $fetch(`${backendUrl}/api/templates`)
|
||||||
templatesRaw.value = res
|
templatesRaw.value = res
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Gagal fetch templates', err)
|
console.error('Gagal fetch templates', err)
|
||||||
|
|||||||
@ -76,7 +76,7 @@
|
|||||||
<!-- Buttons -->
|
<!-- Buttons -->
|
||||||
<div class="flex items-center gap-3 mt-6">
|
<div class="flex items-center gap-3 mt-6">
|
||||||
|
|
||||||
<NuxtLink ::to="`/form/${tpl.kategori.nama}/${tpl.slug}`"
|
<NuxtLink ::to="`/form/${tpl.kategori.nama}/${tpl.kategori}/${tpl.paket.toLowerCase()}`"
|
||||||
class="w-full bg-blue-600 text-white font-semibold py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors text-center">
|
class="w-full bg-blue-600 text-white font-semibold py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors text-center">
|
||||||
Order
|
Order
|
||||||
<p class="text-xs text-gray-400 mt-2">Path: {{ `/form/${tpl.kategori?.nama}/${tpl.slug}` }}</p>
|
<p class="text-xs text-gray-400 mt-2">Path: {{ `/form/${tpl.kategori?.nama}/${tpl.slug}` }}</p>
|
||||||
|
|||||||
@ -9,7 +9,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import WeddingA from '~/components/templates/wedding/weddingA.vue'
|
import WeddingA from '~/components/templates/wedding/WeddingA.vue'
|
||||||
|
|
||||||
// Props dari parent (/p/[code].vue)
|
// Props dari parent (/p/[code].vue)
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
|||||||
@ -1,282 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="max-w-5xl mx-auto p-8 bg-gradient-to-b from-green-50 to-blue-50 shadow-lg rounded-xl">
|
|
||||||
<!-- Judul Form -->
|
|
||||||
<div class="text-center mb-10">
|
|
||||||
<h1 class="text-3xl md:text-4xl font-extrabold text-green-700 drop-shadow-sm">
|
|
||||||
🕌 Form Pemesanan Undangan Khitan Premium ✨
|
|
||||||
</h1>
|
|
||||||
<p class="text-gray-600 mt-2">
|
|
||||||
Isi data berikut dengan lengkap untuk pemesanan undangan khitan.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Info Paket Premium -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200 mb-10">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Paket Premium (Informasi)</h2>
|
|
||||||
<ul class="list-disc pl-5 space-y-1 text-gray-700 text-sm">
|
|
||||||
<li>Maksimal 3x Acara (Akad, Resepsi, Syukuran)</li>
|
|
||||||
<li>Unlimited Galeri Foto</li>
|
|
||||||
<li>Timeline Story</li>
|
|
||||||
<li>Google Maps</li>
|
|
||||||
<li>Reminder Google Calendar</li>
|
|
||||||
<li>Link Instagram Live Streaming</li>
|
|
||||||
<li>Amplop Digital</li>
|
|
||||||
<li>Placement Video Cinematic</li>
|
|
||||||
<li>Bonus Undangan Image Post Story</li>
|
|
||||||
<li>Masa Aktif 12 Bulan</li>
|
|
||||||
<li>Fitur standar: Nama Tamu Personal Unlimited Tamu, Request Musik</li>
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Form Pemesanan -->
|
|
||||||
<form @submit.prevent="submitForm" class="space-y-10">
|
|
||||||
|
|
||||||
<!-- Tema Undangan (otomatis isi) -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4 flex items-center gap-2">
|
|
||||||
<span class="w-1.5 h-6 bg-blue-600 rounded-full"></span> Tema Undangan
|
|
||||||
</h2>
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
||||||
<input :value="form.nama_template" type="text" placeholder="Nama Template" class="input-readonly" readonly />
|
|
||||||
<input :value="form.kategori" type="text" placeholder="Kategori" class="input-readonly" readonly />
|
|
||||||
<input :value="form.harga" type="text" placeholder="Harga" class="input-readonly" readonly />
|
|
||||||
<input :value="form.tanggal_pemesanan" type="text" placeholder="Tanggal Pemesanan" class="input-readonly" readonly />
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Anak yang dikhitan -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Anak yang Dikhitan</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div class="relative">
|
|
||||||
<input v-model="form.nama_anak" id="nama_anak" type="text" placeholder=" " required class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<label for="nama_anak" class="absolute left-2 top-1 text-gray-500 text-xs transition-all duration-200 peer-placeholder-shown:top-5 peer-placeholder-shown:text-sm peer-placeholder-shown:text-gray-400 peer-focus:top-1 peer-focus:text-xs peer-focus:text-green-600">Nama Anak</label>
|
|
||||||
</div>
|
|
||||||
<div class="relative">
|
|
||||||
<input v-model="form.umur_anak" id="umur_anak" type="number" placeholder=" " class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<label for="umur_anak" class="absolute left-2 top-1 text-gray-500 text-xs transition-all duration-200 peer-placeholder-shown:top-5 peer-placeholder-shown:text-sm peer-placeholder-shown:text-gray-400 peer-focus:top-1 peer-focus:text-xs peer-focus:text-green-600">Umur Anak</label>
|
|
||||||
</div>
|
|
||||||
<div class="relative md:col-span-2">
|
|
||||||
<input v-model="form.tempat_lahir" id="tempat_lahir" type="text" placeholder=" " class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<label for="tempat_lahir" class="absolute left-2 top-1 text-gray-500 text-xs transition-all duration-200 peer-placeholder-shown:top-5 peer-placeholder-shown:text-sm peer-placeholder-shown:text-gray-400 peer-focus:top-1 peer-focus:text-xs peer-focus:text-green-600">Tempat Lahir</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Informasi Orang Tua -->
|
|
||||||
<div class="relative md:col-span-2">
|
|
||||||
<input v-model="form.nama_orang_tua" type="text" placeholder="Nama Orang Tua" class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<label class="absolute left-2 top-1 text-gray-500 text-xs transition-all duration-200 peer-placeholder-shown:top-5 peer-placeholder-shown:text-sm peer-placeholder-shown:text-gray-400 peer-focus:top-1 peer-focus:text-xs peer-focus:text-green-600">Nama Orang Tua</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Jadwal Acara -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200 space-y-4">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800">Jadwal Acara & Countdown</h2>
|
|
||||||
<div v-for="(acara, index) in form.jadwal_acara" :key="index" class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-3">
|
|
||||||
<input v-model="acara.nama_acara" type="text" placeholder="Nama Acara" class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<input v-model="acara.tanggal" type="date" placeholder="Tanggal" class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<input v-model="acara.waktu" type="text" placeholder="Waktu" class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<div class="text-sm font-medium text-red-600 flex items-center justify-center">
|
|
||||||
{{ countdowns[index] }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button type="button" @click="addAcara" class="text-green-700 font-semibold">+ Tambah Acara</button>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Fitur Premium & Amplop Digital -->
|
|
||||||
<!-- Bagian Fitur Premium & Amplop Digital diperbarui -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200 space-y-4">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800">Fitur Premium</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div class="relative">
|
|
||||||
<input v-model="form.maps_acara" type="url" placeholder="" class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<label class="absolute left-2 top-1 text-gray-500 text-xs transition-all duration-200 peer-placeholder-shown:top-5 peer-placeholder-shown:text-sm peer-placeholder-shown:text-gray-400 peer-focus:top-1 peer-focus:text-xs peer-focus:text-green-600">Link Google Maps</label>
|
|
||||||
</div>
|
|
||||||
<div class="relative">
|
|
||||||
<input v-model="form.link_live" type="url" placeholder="" class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<label class="absolute left-2 top-1 text-gray-500 text-xs transition-all duration-200 peer-placeholder-shown:top-5 peer-placeholder-shown:text-sm peer-placeholder-shown:text-gray-400 peer-focus:top-1 peer-focus:text-xs peer-focus:text-green-600">Link Instagram Live</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<input type="checkbox" v-model="form.amplop_digital" /> Amplop Digital
|
|
||||||
</div>
|
|
||||||
<div class="relative" v-if="form.amplop_digital">
|
|
||||||
<input v-model="form.no_rekening" type="text" placeholder="Nomor Rekening" class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<label class="absolute left-2 top-1 text-gray-500 text-xs transition-all duration-200 peer-placeholder-shown:top-5 peer-placeholder-shown:text-sm peer-placeholder-shown:text-gray-400 peer-focus:top-1 peer-focus:text-xs peer-focus:text-green-600">No. Rekening</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<input type="checkbox" v-model="form.placement_video" /> Placement Video Cinematic
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<input type="checkbox" v-model="form.bonus_image_post" /> Bonus Undangan Image Post Story
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Reminder Google Calendar -->
|
|
||||||
<div class="flex items-center gap-2">
|
|
||||||
<input type="checkbox" v-model="form.reminder_calendar" /> Reminder Google Calendar
|
|
||||||
</div>
|
|
||||||
<div class="relative" v-if="form.reminder_calendar">
|
|
||||||
<input v-model="form.reminder_notes" type="text" placeholder="Catatan Reminder (opsional)" class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500" />
|
|
||||||
<label class="absolute left-2 top-1 text-gray-500 text-xs transition-all duration-200 peer-placeholder-shown:top-5 peer-placeholder-shown:text-sm peer-placeholder-shown:text-gray-400 peer-focus:top-1 peer-focus:text-xs peer-focus:text-green-600">Catatan Reminder</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative md:col-span-2">
|
|
||||||
<textarea v-model="form.timeline_story" rows="3" placeholder="" class="peer w-full border border-gray-300 rounded-lg px-3 pt-5 pb-2 text-sm focus:outline-none focus:ring-2 focus:ring-green-500 resize-none"></textarea>
|
|
||||||
<label class="absolute left-2 top-1 text-gray-500 text-xs transition-all duration-200 peer-placeholder-shown:top-5 peer-placeholder-shown:text-sm peer-placeholder-shown:text-gray-400 peer-focus:top-1 peer-focus:text-xs peer-focus:text-green-600">Timeline Story</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Galeri Upload -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Galeri</h2>
|
|
||||||
<input type="file" multiple accept="image/*" @change="handleFileUpload" class="hidden" id="gallery-upload" />
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-3 gap-3">
|
|
||||||
<div v-for="(img, i) in previewImages" :key="i" class="relative w-full aspect-square rounded-lg overflow-hidden shadow-sm group">
|
|
||||||
<img :src="img" alt="Preview" class="object-cover w-full h-full" />
|
|
||||||
<button type="button" @click="removeImage(i)" class="absolute top-1 right-1 bg-red-600 text-white rounded-full w-6 h-6 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity font-bold">×</button>
|
|
||||||
</div>
|
|
||||||
<label for="gallery-upload" class="flex items-center justify-center w-full aspect-square bg-gray-50 border-2 border-dashed border-gray-300 rounded-lg cursor-pointer hover:bg-gray-100 transition">
|
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
|
||||||
</svg>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Submit -->
|
|
||||||
<div class="mt-10 text-center">
|
|
||||||
<button type="submit" class="bg-blue-600 text-white px-10 py-3 rounded-xl font-semibold shadow-md hover:bg-blue-700 hover:shadow-lg transition" :disabled="loading">
|
|
||||||
{{ loading ? "Mengirim..." : "Kirim & Konfirmasi Admin" }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Alert -->
|
|
||||||
<div v-if="success" class="mt-6 p-4 text-green-800 bg-green-100 rounded-lg text-center font-medium">
|
|
||||||
✅ Form berhasil dikirim!
|
|
||||||
</div>
|
|
||||||
<div v-if="error" class="mt-6 p-4 text-red-800 bg-red-100 rounded-lg text-center font-medium">
|
|
||||||
❌ Gagal mengirim form. Pastikan semua data yang wajib diisi sudah lengkap.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, onMounted } from "vue";
|
|
||||||
|
|
||||||
const form = ref({
|
|
||||||
template_id: "",
|
|
||||||
nama_template: "",
|
|
||||||
kategori: "",
|
|
||||||
harga: "",
|
|
||||||
tanggal_pemesanan: new Date().toISOString().split("T")[0],
|
|
||||||
nama_pemesan: "",
|
|
||||||
no_hp: "",
|
|
||||||
email: "",
|
|
||||||
nama_anak: "",
|
|
||||||
umur_anak: "",
|
|
||||||
tempat_lahir: "",
|
|
||||||
nama_orang_tua: "",
|
|
||||||
jadwal_acara: [{ nama_acara: "", tanggal: "", waktu: "" }],
|
|
||||||
maps_acara: "",
|
|
||||||
link_live: "",
|
|
||||||
amplop_digital: false,
|
|
||||||
no_rekening: "",
|
|
||||||
placement_video: false,
|
|
||||||
bonus_image_post: false,
|
|
||||||
timeline_story: "",
|
|
||||||
galeri: [],
|
|
||||||
selectedFiturs: {},
|
|
||||||
});
|
|
||||||
|
|
||||||
const previewImages = ref([]);
|
|
||||||
const loading = ref(false);
|
|
||||||
const success = ref(false);
|
|
||||||
const error = ref(false);
|
|
||||||
const countdowns = ref([""]); // array countdown tiap acara
|
|
||||||
|
|
||||||
const addAcara = () => {
|
|
||||||
if (form.value.jadwal_acara.length < 3) {
|
|
||||||
form.value.jadwal_acara.push({ nama_acara: "", tanggal: "", waktu: "" });
|
|
||||||
countdowns.value.push("");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Countdown real-time
|
|
||||||
const updateCountdowns = () => {
|
|
||||||
form.value.jadwal_acara.forEach((acara, i) => {
|
|
||||||
if (!acara.tanggal) {
|
|
||||||
countdowns.value[i] = "-";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const acaraTime = new Date(`${acara.tanggal}T${acara.waktu || "00:00"}`).getTime();
|
|
||||||
const now = Date.now();
|
|
||||||
const diff = acaraTime - now;
|
|
||||||
|
|
||||||
if (diff <= 0) {
|
|
||||||
countdowns.value[i] = "Acara sedang berlangsung / selesai";
|
|
||||||
} else {
|
|
||||||
const d = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
||||||
const h = Math.floor((diff / (1000 * 60 * 60)) % 24);
|
|
||||||
const m = Math.floor((diff / (1000 * 60)) % 60);
|
|
||||||
const s = Math.floor((diff / 1000) % 60);
|
|
||||||
countdowns.value[i] = `${d}d ${h}h ${m}m ${s}s`;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
setInterval(updateCountdowns, 1000);
|
|
||||||
});
|
|
||||||
|
|
||||||
const handleFileUpload = (event) => {
|
|
||||||
const newFiles = Array.from(event.target.files);
|
|
||||||
form.value.galeri.push(...newFiles);
|
|
||||||
previewImages.value = [];
|
|
||||||
form.value.galeri.forEach(file => {
|
|
||||||
const reader = new FileReader();
|
|
||||||
reader.onload = e => previewImages.value.push(e.target.result);
|
|
||||||
reader.readAsDataURL(file);
|
|
||||||
});
|
|
||||||
event.target.value = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const removeImage = (index) => {
|
|
||||||
form.value.galeri.splice(index, 1);
|
|
||||||
previewImages.value.splice(index, 1);
|
|
||||||
};
|
|
||||||
|
|
||||||
const submitForm = async () => {
|
|
||||||
loading.value = true;
|
|
||||||
success.value = false;
|
|
||||||
error.value = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
const body = new FormData();
|
|
||||||
for (const key in form.value) {
|
|
||||||
if (key === "galeri") form.value.galeri.forEach(f => body.append("galeri[]", f));
|
|
||||||
else if (key === "jadwal_acara") form.value.jadwal_acara.forEach(a => body.append("jadwal_acara[]", JSON.stringify(a)));
|
|
||||||
else if (key !== "selectedFiturs") body.append(key, form.value[key]);
|
|
||||||
}
|
|
||||||
for (const kategoriId in form.value.selectedFiturs) {
|
|
||||||
const fiturs = Array.isArray(form.value.selectedFiturs[kategoriId]) ? form.value.selectedFiturs[kategoriId] : [form.value.selectedFiturs[kategoriId]];
|
|
||||||
fiturs.forEach(fiturId => body.append("fiturs[]", fiturId));
|
|
||||||
}
|
|
||||||
|
|
||||||
await $fetch("http://localhost:8000/api/form", { method: "POST", body, headers: { Accept: "application/json" } });
|
|
||||||
success.value = true;
|
|
||||||
|
|
||||||
const adminNumber = "62895602603247";
|
|
||||||
const message = `Halo Admin, ada pemesanan undangan khitan baru 🎉\nNama Pemesan: ${form.value.nama_pemesan}\nNo WA: ${form.value.no_hp}\nEmail: ${form.value.email}\nTemplate: ${form.value.nama_template} (${form.value.kategori})\nHarga: ${form.value.harga}\nTanggal Pemesanan: ${form.value.tanggal_pemesanan}`;
|
|
||||||
window.location.href = `https://wa.me/${adminNumber}?text=${encodeURIComponent(message)}`;
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
error.value = true;
|
|
||||||
} finally {
|
|
||||||
loading.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="p-10 max-w-2xl mx-auto">
|
|
||||||
<h1 class="text-2xl font-bold mb-6">Form Pemesanan - Khitan B</h1>
|
|
||||||
<form class="space-y-4">
|
|
||||||
<input type="text" placeholder="Nama Pemesan" class="border px-4 py-2 rounded w-full" />
|
|
||||||
<input type="text" placeholder="Nama Anak" class="border px-4 py-2 rounded w-full" />
|
|
||||||
<input type="date" class="border px-4 py-2 rounded w-full" />
|
|
||||||
<textarea placeholder="Alamat Acara" class="border px-4 py-2 rounded w-full"></textarea>
|
|
||||||
<button class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700">
|
|
||||||
Kirim
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@ -1,252 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="max-w-6xl mx-auto p-8 bg-gradient-to-b from-pink-50 to-red-50 shadow-lg rounded-xl">
|
|
||||||
<!-- Judul -->
|
|
||||||
<div class="text-center mb-10">
|
|
||||||
<h1 class="text-3xl md:text-4xl font-extrabold text-red-700 drop-shadow-sm">
|
|
||||||
💍 Form Pemesanan Undangan Pernikahan 💐
|
|
||||||
</h1>
|
|
||||||
<p class="text-gray-600 mt-2">Isi data berikut untuk membuat undangan pernikahan Anda</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form @submit.prevent="submitForm" class="space-y-10">
|
|
||||||
<!-- Paket Starter (Informasi) -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Paket Undangan</h2>
|
|
||||||
<div class="p-4 border rounded-xl bg-blue-50">
|
|
||||||
<div class="font-semibold text-gray-800 mb-2">Starter</div>
|
|
||||||
<div class="text-gray-600 mb-2">Fitur:</div>
|
|
||||||
<ul class="list-disc list-inside text-gray-600">
|
|
||||||
<li>1x Acara</li>
|
|
||||||
<li>Masa Aktif 3 Bulan</li>
|
|
||||||
<li>Fitur standar: Nama Tamu Personal, maks. 100 Tamu, Request Musik</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Info Template -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Template & Detail Paket</h2>
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
||||||
<input v-model="form.nama_template" type="text" placeholder="Nama Template" class="input-readonly" readonly />
|
|
||||||
<input v-model="form.kategori" type="text" placeholder="Kategori" class="input-readonly" readonly />
|
|
||||||
<input v-model="form.harga" type="text" placeholder="Harga" class="input-readonly" readonly />
|
|
||||||
<input v-model="form.tanggal_pemesanan" type="text" placeholder="Tanggal Pemesanan" class="input-readonly"
|
|
||||||
readonly />
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Data Pemesan -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Data Pemesan</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm text-gray-600 mb-1">Nama Pemesan</label>
|
|
||||||
<input v-model="form.nama_pemesan" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm text-gray-600 mb-1">No. WhatsApp</label>
|
|
||||||
<input v-model="form.no_hp" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div class="md:col-span-2">
|
|
||||||
<label class="block text-sm text-gray-600 mb-1">Email</label>
|
|
||||||
<input v-model="form.email" type="email" class="input" required />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Data Pengantin -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Data Pengantin</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Nama Pengantin Pria</label>
|
|
||||||
<input v-model="form.nama_pria" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Nama Pengantin Wanita</label>
|
|
||||||
<input v-model="form.nama_wanita" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Orang Tua Pengantin Pria</label>
|
|
||||||
<input v-model="form.ortu_pria" type="text" class="input" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Orang Tua Pengantin Wanita</label>
|
|
||||||
<input v-model="form.ortu_wanita" type="text" class="input" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Data Acara -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Detail Acara (1x Acara)</h2>
|
|
||||||
<div v-for="(acara, index) in form.acaras" :key="index" class="mb-6 border-b pb-4">
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Nama Acara</label>
|
|
||||||
<input v-model="acara.nama" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Tanggal Acara</label>
|
|
||||||
<input v-model="acara.tanggal" type="date" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Jam</label>
|
|
||||||
<input v-model="acara.jam" type="time" class="input" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Lokasi</label>
|
|
||||||
<input v-model="acara.lokasi" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div class="md:col-span-2">
|
|
||||||
<label class="block text-sm mb-1">Request Lagu</label>
|
|
||||||
<input v-model="acara.request_lagu" type="text" class="input"
|
|
||||||
placeholder="Contoh: Lagu pengantin, playlist, dsb." />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Submit -->
|
|
||||||
<div class="mt-10 text-center">
|
|
||||||
<button type="submit"
|
|
||||||
class="bg-blue-600 text-white px-10 py-3 rounded-xl font-semibold shadow-md hover:bg-blue-700 hover:shadow-lg transition"
|
|
||||||
:disabled="loading">
|
|
||||||
{{ loading ? "Mengirim..." : "Kirim & Konfirmasi Admin" }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Alert -->
|
|
||||||
<div v-if="success" class="mt-6 p-4 text-green-800 bg-green-100 rounded-lg text-center font-medium">
|
|
||||||
✅ Form berhasil dikirim! Tunggu konfirmasi admin.
|
|
||||||
</div>
|
|
||||||
<div v-if="error" class="mt-6 p-4 text-red-800 bg-red-100 rounded-lg text-center font-medium">
|
|
||||||
❌ Gagal mengirim form. Cek kembali inputan Anda.
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref, onMounted } from "vue"
|
|
||||||
import { useRoute } from "vue-router"
|
|
||||||
|
|
||||||
const form = ref({
|
|
||||||
selectedPaket: "starter",
|
|
||||||
nama_template: "Undangan Minimalis",
|
|
||||||
kategori: "Pernikahan",
|
|
||||||
harga: "100.000",
|
|
||||||
tanggal_pemesanan: new Date().toLocaleDateString("id-ID"),
|
|
||||||
nama_pemesan: "",
|
|
||||||
no_hp: "",
|
|
||||||
email: "",
|
|
||||||
nama_pria: "",
|
|
||||||
nama_wanita: "",
|
|
||||||
ortu_pria: "",
|
|
||||||
ortu_wanita: "",
|
|
||||||
acaras: [{ nama: "", tanggal: "", jam: "", lokasi: "", request_lagu: "" }],
|
|
||||||
})
|
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const success = ref(false)
|
|
||||||
const error = ref(false)
|
|
||||||
const template = ref(null)
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
const adminWaNumber = "6281234567890" // ganti dengan nomor WA admin
|
|
||||||
|
|
||||||
onMounted(async () => {
|
|
||||||
try {
|
|
||||||
const templateId = route.query.template_id
|
|
||||||
if (!templateId) throw new Error("Template ID tidak ditemukan di URL")
|
|
||||||
|
|
||||||
const res = await fetch(`http://localhost:8000/api/templates/${templateId}`)
|
|
||||||
if (!res.ok) throw new Error("Gagal ambil template")
|
|
||||||
template.value = await res.json()
|
|
||||||
|
|
||||||
form.value.nama_template = template.value.nama_template
|
|
||||||
form.value.kategori = template.value.kategori?.nama || "Pernikahan"
|
|
||||||
form.value.harga = new Intl.NumberFormat('id-ID').format(template.value.harga)
|
|
||||||
form.value.tanggal_pemesanan = new Date().toLocaleDateString("id-ID")
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Error fetch template:", err)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const submitForm = async () => {
|
|
||||||
try {
|
|
||||||
if (!template.value) {
|
|
||||||
throw new Error("Template belum dimuat, tidak bisa submit!")
|
|
||||||
}
|
|
||||||
loading.value = true
|
|
||||||
success.value = false
|
|
||||||
error.value = false
|
|
||||||
|
|
||||||
const res = await fetch("http://localhost:8000/api/pelanggans", {
|
|
||||||
method: "POST",
|
|
||||||
headers: { "Content-Type": "application/json" },
|
|
||||||
body: JSON.stringify({
|
|
||||||
nama_pemesan: form.value.nama_pemesan,
|
|
||||||
email: form.value.email,
|
|
||||||
no_tlpn: form.value.no_hp, // 🔥 ganti no_hp -> no_tlpn
|
|
||||||
template_id: template.value.id,
|
|
||||||
form: JSON.stringify({ // 🔥 pastikan dikirim string, bukan object
|
|
||||||
nama_pengantin: form.value.nama_pria + " & " + form.value.nama_wanita,
|
|
||||||
tanggal_acara: form.value.acaras[0].tanggal,
|
|
||||||
lokasi: form.value.acaras[0].lokasi
|
|
||||||
})
|
|
||||||
}),
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
const data = await res.json()
|
|
||||||
if (!res.ok) throw new Error(data.message || "Gagal simpan data")
|
|
||||||
success.value = true
|
|
||||||
|
|
||||||
// --- Langsung buka WhatsApp Admin ---
|
|
||||||
const f = form.value
|
|
||||||
const pesan = `
|
|
||||||
Halo Admin, saya ingin memesan undangan.
|
|
||||||
Nama Pemesan: ${f.nama_pemesan}
|
|
||||||
No. WA: ${f.no_hp}
|
|
||||||
Email: ${f.email}
|
|
||||||
|
|
||||||
Template: ${f.nama_template}
|
|
||||||
Kategori: ${f.kategori}
|
|
||||||
Harga: ${f.harga}
|
|
||||||
|
|
||||||
Nama Pengantin: ${f.nama_pria} & ${f.nama_wanita}
|
|
||||||
Orang Tua Pria: ${f.ortu_pria}
|
|
||||||
Orang Tua Wanita: ${f.ortu_wanita}
|
|
||||||
|
|
||||||
Acara:
|
|
||||||
${f.acaras.map(a => `- ${a.nama}, ${a.tanggal}, ${a.jam || "-"} WIB, Lokasi: ${a.lokasi}, Request Lagu: ${a.request_lagu || "-"}`).join("\n")}
|
|
||||||
`
|
|
||||||
window.open(`https://wa.me/${adminWaNumber}?text=${encodeURIComponent(pesan)}`, "_blank")
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Catch error:", err)
|
|
||||||
error.value = true
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.input {
|
|
||||||
border: 1px solid #d1d5db;
|
|
||||||
padding: 0.5rem 0.75rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-readonly {
|
|
||||||
border: 1px solid #d1d5db;
|
|
||||||
padding: 0.5rem 0.75rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
background-color: #f9fafb;
|
|
||||||
color: #4b5563;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="p-10 max-w-2xl mx-auto">
|
|
||||||
<h1 class="text-2xl font-bold mb-6">Form Pemesanan - Wedding B</h1>
|
|
||||||
<form class="space-y-4">
|
|
||||||
<input type="text" placeholder="Nama Pemesan" class="border px-4 py-2 rounded w-full" />
|
|
||||||
<input type="text" placeholder="Nama Pasangan" class="border px-4 py-2 rounded w-full" />
|
|
||||||
<input type="date" class="border px-4 py-2 rounded w-full" />
|
|
||||||
<textarea placeholder="Alamat Acara" class="border px-4 py-2 rounded w-full"></textarea>
|
|
||||||
<button class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700">
|
|
||||||
Kirim
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@ -1,275 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="max-w-6xl mx-auto p-8 bg-gradient-to-b from-blue-50 to-indigo-50 shadow-lg rounded-xl">
|
|
||||||
<!-- Judul -->
|
|
||||||
<div class="text-center mb-10">
|
|
||||||
<h1 class="text-3xl md:text-4xl font-extrabold text-indigo-700 drop-shadow-sm">
|
|
||||||
🎂 Form Pemesanan Undangan Ulang Tahun 🎉
|
|
||||||
</h1>
|
|
||||||
<p class="text-gray-600 mt-2">Isi data berikut untuk membuat undangan ulang tahun anak Anda</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<form @submit.prevent="submitForm" class="space-y-10">
|
|
||||||
|
|
||||||
<!-- Pilih Paket -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Pilih Paket</h2>
|
|
||||||
<div class="flex flex-col md:flex-row gap-4">
|
|
||||||
<label v-for="paket in paketList" :key="paket.id"
|
|
||||||
class="flex-1 p-4 border rounded-xl cursor-pointer hover:shadow-lg transition-all"
|
|
||||||
:class="{'border-blue-600 bg-blue-50': form.selectedPaket === paket.id}">
|
|
||||||
<input type="radio" class="hidden" v-model="form.selectedPaket" :value="paket.id" />
|
|
||||||
<div class="font-semibold text-gray-800">{{ paket.nama }}</div>
|
|
||||||
<div class="text-gray-600">{{ paket.deskripsi }}</div>
|
|
||||||
<div class="font-bold mt-2 text-blue-700">{{ formatRupiah(paket.harga) }}</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Info Template -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Template</h2>
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
|
||||||
<input v-model="form.nama_template" type="text" placeholder="Nama Template" class="input-readonly" readonly />
|
|
||||||
<input v-model="form.kategori" type="text" placeholder="Kategori" class="input-readonly" readonly />
|
|
||||||
<input v-model="form.harga" type="text" placeholder="Harga" class="input-readonly" readonly />
|
|
||||||
<input v-model="form.tanggal_pemesanan" type="text" placeholder="Tanggal Pemesanan" class="input-readonly" readonly />
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Data Pemesan -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Data Pemesan</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm text-gray-600 mb-1">Nama Pemesan</label>
|
|
||||||
<input v-model="form.nama_pemesan" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm text-gray-600 mb-1">No. WhatsApp</label>
|
|
||||||
<input v-model="form.no_hp" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div class="md:col-span-2">
|
|
||||||
<label class="block text-sm text-gray-600 mb-1">Email</label>
|
|
||||||
<input v-model="form.email" type="email" class="input" required />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Data Anak -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Data Anak</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Nama Lengkap Anak</label>
|
|
||||||
<input v-model="form.nama_lengkap_anak" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Nama Panggilan Anak</label>
|
|
||||||
<input v-model="form.nama_panggilan_anak" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Nama Bapak</label>
|
|
||||||
<input v-model="form.bapak_anak" type="text" class="input" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Nama Ibu</label>
|
|
||||||
<input v-model="form.ibu_anak" type="text" class="input" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Ulang Tahun ke-</label>
|
|
||||||
<input v-model="form.umur_dirayakan" type="number" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Anak ke-</label>
|
|
||||||
<input v-model="form.anak_ke" type="number" class="input" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Detail Acara -->
|
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Detail Acara</h2>
|
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Hari & Tanggal</label>
|
|
||||||
<input v-model="form.hari_tanggal_acara" type="date" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm mb-1">Waktu Acara</label>
|
|
||||||
<input v-model="form.waktu_acara" type="text" class="input" required />
|
|
||||||
</div>
|
|
||||||
<div class="md:col-span-2">
|
|
||||||
<label class="block text-sm mb-1">Alamat Lengkap</label>
|
|
||||||
<textarea v-model="form.alamat_acara" class="input"></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="md:col-span-2">
|
|
||||||
<label class="block text-sm mb-1">Link Google Maps (opsional)</label>
|
|
||||||
<input v-model="form.maps_acara" type="text" class="input" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Galeri Foto -->
|
|
||||||
<section v-if="form.selectedPaket === 'basic' || form.selectedPaket === 'premium'" class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">
|
|
||||||
Galeri Foto
|
|
||||||
<span v-if="form.selectedPaket === 'basic'">(max 6 gambar)</span>
|
|
||||||
<span v-if="form.selectedPaket === 'premium'">(unlimited)</span>
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<label for="gallery-upload"
|
|
||||||
class="cursor-pointer bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded-lg text-sm font-medium inline-block mb-4">
|
|
||||||
+ Tambah Foto
|
|
||||||
</label>
|
|
||||||
<input type="file" multiple accept="image/*" @change="handleFileUpload" class="hidden" id="gallery-upload" />
|
|
||||||
|
|
||||||
<div class="grid grid-cols-2 md:grid-cols-3 gap-3">
|
|
||||||
<div v-for="(img, i) in previewImages" :key="i"
|
|
||||||
class="relative w-full aspect-square rounded-lg overflow-hidden shadow-sm group">
|
|
||||||
<img :src="img" alt="Preview" class="object-cover w-full h-full" />
|
|
||||||
<button type="button" @click="removeImage(i)"
|
|
||||||
class="absolute top-1 right-1 bg-red-600 text-white rounded-full w-6 h-6 flex items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity font-bold">
|
|
||||||
×
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Upload Video (Premium Only) -->
|
|
||||||
<section v-if="form.selectedPaket === 'premium'" class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Video Ucapan (Premium)</h2>
|
|
||||||
<input type="file" accept="video/*" @change="handleVideoUpload" class="block w-full text-sm text-gray-600" />
|
|
||||||
<div v-if="previewVideo" class="mt-4">
|
|
||||||
<video controls class="w-full rounded-lg shadow">
|
|
||||||
<source :src="previewVideo" type="video/mp4" />
|
|
||||||
Browser Anda tidak mendukung video.
|
|
||||||
</video>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- Submit -->
|
|
||||||
<div class="mt-10 text-center">
|
|
||||||
<button type="submit"
|
|
||||||
class="bg-blue-600 text-white px-10 py-3 rounded-xl font-semibold shadow-md hover:bg-blue-700 hover:shadow-lg transition"
|
|
||||||
:disabled="loading">
|
|
||||||
{{ loading ? "Mengirim..." : "Kirim & Konfirmasi Admin" }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Alert -->
|
|
||||||
<div v-if="success" class="mt-6 p-4 text-green-800 bg-green-100 rounded-lg text-center font-medium">
|
|
||||||
✅ Form berhasil dikirim! Tunggu konfirmasi admin.
|
|
||||||
</div>
|
|
||||||
<div v-if="error" class="mt-6 p-4 text-red-800 bg-red-100 rounded-lg text-center font-medium">
|
|
||||||
❌ Gagal mengirim form. Cek kembali inputan Anda.
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from "vue"
|
|
||||||
|
|
||||||
const paketList = ref([
|
|
||||||
{ id: "starter", nama: "Starter", deskripsi: "Fitur dasar (tanpa galeri)", harga: 100000 },
|
|
||||||
{ id: "basic", nama: "Basic", deskripsi: "Tambahan galeri (max 6 foto)", harga: 200000 },
|
|
||||||
{ id: "premium", nama: "Premium", deskripsi: "Unlimited galeri + upload video", harga: 350000 },
|
|
||||||
])
|
|
||||||
|
|
||||||
const form = ref({
|
|
||||||
selectedPaket: "",
|
|
||||||
nama_template: "",
|
|
||||||
kategori: "Ulang Tahun",
|
|
||||||
harga: "",
|
|
||||||
tanggal_pemesanan: new Date().toLocaleDateString("id-ID"),
|
|
||||||
nama_pemesan: "",
|
|
||||||
no_hp: "",
|
|
||||||
email: "",
|
|
||||||
nama_lengkap_anak: "",
|
|
||||||
nama_panggilan_anak: "",
|
|
||||||
bapak_anak: "",
|
|
||||||
ibu_anak: "",
|
|
||||||
umur_dirayakan: "",
|
|
||||||
anak_ke: "",
|
|
||||||
hari_tanggal_acara: "",
|
|
||||||
waktu_acara: "",
|
|
||||||
alamat_acara: "",
|
|
||||||
maps_acara: "",
|
|
||||||
galeri: [],
|
|
||||||
video: null
|
|
||||||
})
|
|
||||||
|
|
||||||
const previewImages = ref([])
|
|
||||||
const previewVideo = ref(null)
|
|
||||||
|
|
||||||
const loading = ref(false)
|
|
||||||
const success = ref(false)
|
|
||||||
const error = ref(false)
|
|
||||||
|
|
||||||
const formatRupiah = (num) => new Intl.NumberFormat("id-ID", { style: "currency", currency: "IDR" }).format(num)
|
|
||||||
|
|
||||||
const handleFileUpload = (event) => {
|
|
||||||
const files = Array.from(event.target.files)
|
|
||||||
|
|
||||||
if (form.value.selectedPaket === "basic" && (form.value.galeri.length + files.length) > 6) {
|
|
||||||
alert("Paket Basic hanya bisa upload maksimal 6 foto!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
form.value.galeri.push(...files)
|
|
||||||
files.forEach(file => {
|
|
||||||
const reader = new FileReader()
|
|
||||||
reader.onload = e => previewImages.value.push(e.target.result)
|
|
||||||
reader.readAsDataURL(file)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleVideoUpload = (event) => {
|
|
||||||
const file = event.target.files[0]
|
|
||||||
if (file) {
|
|
||||||
form.value.video = file
|
|
||||||
const reader = new FileReader()
|
|
||||||
reader.onload = e => previewVideo.value = e.target.result
|
|
||||||
reader.readAsDataURL(file)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const removeImage = (index) => {
|
|
||||||
form.value.galeri.splice(index, 1)
|
|
||||||
previewImages.value.splice(index, 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
const submitForm = async () => {
|
|
||||||
try {
|
|
||||||
loading.value = true
|
|
||||||
success.value = false
|
|
||||||
error.value = false
|
|
||||||
|
|
||||||
console.log("Data dikirim:", form.value)
|
|
||||||
await new Promise(res => setTimeout(res, 1000))
|
|
||||||
|
|
||||||
success.value = true
|
|
||||||
} catch (err) {
|
|
||||||
error.value = true
|
|
||||||
} finally {
|
|
||||||
loading.value = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.input {
|
|
||||||
border: 1px solid #d1d5db;
|
|
||||||
padding: 0.5rem 0.75rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
}
|
|
||||||
.input-readonly {
|
|
||||||
border: 1px solid #d1d5db;
|
|
||||||
padding: 0.5rem 0.75rem;
|
|
||||||
border-radius: 0.5rem;
|
|
||||||
background-color: #f9fafb;
|
|
||||||
color: #4b5563;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="p-10 max-w-2xl mx-auto">
|
|
||||||
<h1 class="text-2xl font-bold mb-6">Form Pemesanan - Ulang Tahun B</h1>
|
|
||||||
<form class="space-y-4">
|
|
||||||
<input type="text" placeholder="Nama Pemesan" class="border px-4 py-2 rounded w-full" />
|
|
||||||
<input type="text" placeholder="Nama Anak / Orang yang Berulang Tahun" class="border px-4 py-2 rounded w-full" />
|
|
||||||
<input type="date" class="border px-4 py-2 rounded w-full" />
|
|
||||||
<textarea placeholder="Alamat Acara" class="border px-4 py-2 rounded w-full"></textarea>
|
|
||||||
<button class="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700">
|
|
||||||
Kirim
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
bla
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
</script>
|
|
||||||
@ -1,89 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<KhitanA
|
|
||||||
v-if="isCoverVisible"
|
|
||||||
:data="invitationData"
|
|
||||||
@next-page="openInvitation"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div v-else class="min-h-screen bg-blue-900 overflow-hidden">
|
|
||||||
<div class="fixed top-6 left-1/2 transform -translate-x-1/2 z-50">
|
|
||||||
<div class="flex space-x-2 bg-white/20 backdrop-blur-sm rounded-full px-4 py-2">
|
|
||||||
<button
|
|
||||||
v-for="(page, index) in pages"
|
|
||||||
:key="index"
|
|
||||||
@click="goToPage(index)"
|
|
||||||
:class="[
|
|
||||||
'px-3 py-1 rounded-full text-sm font-medium transition-all duration-300',
|
|
||||||
currentPage === index
|
|
||||||
? 'bg-yellow-400 text-blue-900'
|
|
||||||
: 'text-white hover:bg-white/20'
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
{{ page.title }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="relative h-screen">
|
|
||||||
<Transition :name="transitionName" mode="out-in">
|
|
||||||
<component
|
|
||||||
:is="pages[currentPage].component"
|
|
||||||
:key="currentPage"
|
|
||||||
:data="invitationData"
|
|
||||||
class="absolute inset-0"
|
|
||||||
/>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
|
|
||||||
// 3. Import SEMUA komponen, termasuk komponen sampul
|
|
||||||
import KhitanA from '~/components/templates/khitan/KhitanA.vue' // <-- IMPORT INI
|
|
||||||
import KhitanIntroduction from '~/components/templates/khitan/Introduction.vue'
|
|
||||||
import KhitanEvent from '~/components/templates/khitan/Event.vue'
|
|
||||||
import KhitanGallery from '~/components/templates/khitan/Gallery.vue'
|
|
||||||
import KhitanSay from '~/components/templates/khitan/GuestBook.vue'
|
|
||||||
import KhitanThankYou from '~/components/templates/khitan/ThankYou.vue'
|
|
||||||
|
|
||||||
// 4. Tambahkan state untuk mengontrol sampul
|
|
||||||
const isCoverVisible = ref(true) // <-- TAMBAHKAN INI
|
|
||||||
|
|
||||||
// --- Kode Anda yang sudah ada sebelumnya ---
|
|
||||||
const currentPage = ref(0)
|
|
||||||
const transitionName = ref('slide-right')
|
|
||||||
|
|
||||||
const pages = [
|
|
||||||
{ title: 'Introduction', component: KhitanIntroduction },
|
|
||||||
{ title: 'Event', component: KhitanEvent },
|
|
||||||
{ title: 'Gallery', component: KhitanGallery },
|
|
||||||
{ title: 'Say', component: KhitanSay },
|
|
||||||
{ title: 'Thank You', component: KhitanThankYou }
|
|
||||||
]
|
|
||||||
|
|
||||||
const invitationData = {
|
|
||||||
// Menambahkan guestName agar bisa ditampilkan di sampul
|
|
||||||
guestName: 'Tamu Undangan',
|
|
||||||
childName: 'Satria Huda Dinata',
|
|
||||||
fatherName: 'Bpk H. Munawar Huda, S.H.',
|
|
||||||
motherName: 'Ibu Hj. Dinah, A.M.Keb',
|
|
||||||
eventDate: '20-21 Juni 2025',
|
|
||||||
eventTime: '09:00 WIB s.d Selesai',
|
|
||||||
eventLocation: 'TMC Mangrove, Tanjung Pasir'
|
|
||||||
}
|
|
||||||
|
|
||||||
const goToPage = (index) => {
|
|
||||||
transitionName.value = index > currentPage.value ? 'slide-left' : 'slide-right'
|
|
||||||
currentPage.value = index
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Tambahkan fungsi untuk membuka undangan
|
|
||||||
const openInvitation = () => {
|
|
||||||
isCoverVisible.value = false;
|
|
||||||
// Opsional: Anda bisa mulai putar musik di sini
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -1,79 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="min-h-screen bg-gradient-to-br from-yellow-300 via-yellow-400 to-yellow-500 relative overflow-hidden">
|
|
||||||
<!-- Navigation (hanya muncul kalau bukan di landing) -->
|
|
||||||
<nav v-if="currentSection !== 'landing'"
|
|
||||||
class="absolute top-4 left-1/2 transform -translate-x-1/2 z-20">
|
|
||||||
<ul class="flex space-x-6 bg-white/40 backdrop-blur-md px-6 py-3 rounded-full shadow-md text-sm font-semibold text-gray-800">
|
|
||||||
<li>
|
|
||||||
<button @click="currentSection='introduction'" :class="navClass('introduction')">Intro</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button @click="currentSection='event'" :class="navClass('event')">Event</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button @click="currentSection='galeri'" :class="navClass('galeri')">Gallery</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button @click="currentSection='say'" :class="navClass('say')">Guest Book</button>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<button @click="currentSection='thanks'" :class="navClass('thanks')">Thanks</button>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<!-- Music Icon -->
|
|
||||||
<div class="fixed bottom-4 left-4 z-30" v-if="currentSection !== 'landing'">
|
|
||||||
<button @click="toggleMusic" class="bg-orange-600 p-3 rounded-full text-white shadow-lg">
|
|
||||||
{{ isPlaying ? '⏸️' : '▶️' }}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Main Content -->
|
|
||||||
<main class="relative z-10 min-h-screen flex items-center justify-center p-4">
|
|
||||||
<Landing v-if="currentSection==='landing'"
|
|
||||||
:childName="childName"
|
|
||||||
:guestName="guestName"
|
|
||||||
@open-invitation="currentSection='introduction'" />
|
|
||||||
|
|
||||||
<Introduction v-if="currentSection==='introduction'"
|
|
||||||
:age="age"
|
|
||||||
:childName="childName"
|
|
||||||
:childOrder="childOrder"
|
|
||||||
:parentNames="parentNames"
|
|
||||||
:childPhoto="childPhoto"/>
|
|
||||||
|
|
||||||
<Event v-if="currentSection==='event'" />
|
|
||||||
<Gallery v-if="currentSection==='galeri'" />
|
|
||||||
<GuestBook v-if="currentSection==='say'" />
|
|
||||||
<ThankYou v-if="currentSection==='thanks'" />
|
|
||||||
</main>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import Landing from '~/components/templates/Ultah/Landing.vue'
|
|
||||||
import Introduction from '~/components/templates/Ultah/Introduction.vue'
|
|
||||||
import Event from '~/components/templates/Ultah/Event.vue'
|
|
||||||
import Gallery from '~/components/templates/Ultah/Gallery.vue'
|
|
||||||
import GuestBook from '~/components/templates/Ultah/GuestBook.vue'
|
|
||||||
import ThankYou from '~/components/templates/Ultah/ThankYou.vue'
|
|
||||||
|
|
||||||
const childName = ref('Rayyanza Malik Ahmad')
|
|
||||||
const guestName = ref('Gempita Nora Marten')
|
|
||||||
const age = ref(4)
|
|
||||||
const childOrder = ref(2)
|
|
||||||
const parentNames = ref('Raffi Ahmad & Nagita Slavina')
|
|
||||||
const childPhoto = ref('')
|
|
||||||
const isPlaying = ref(false)
|
|
||||||
const currentSection = ref('landing')
|
|
||||||
|
|
||||||
const toggleMusic = () => { isPlaying.value = !isPlaying.value }
|
|
||||||
|
|
||||||
const navClass = (section) => {
|
|
||||||
return currentSection.value === section
|
|
||||||
? 'text-orange-700 underline'
|
|
||||||
: 'hover:text-orange-600'
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div>
|
|
||||||
<WeddingA
|
|
||||||
namaPengantinPria="Ahmad"
|
|
||||||
namaPengantinWanita="Aisyah"
|
|
||||||
namaAyahPria="Budi"
|
|
||||||
namaIbuPria="Siti"
|
|
||||||
namaAyahWanita="Hendra"
|
|
||||||
namaIbuWanita="Nur"
|
|
||||||
tanggalAkad="Minggu, 15 Oktober 2025"
|
|
||||||
lokasiAkad="Masjid Raya Padang"
|
|
||||||
tanggalResepsi="Senin, 16 Oktober 2025"
|
|
||||||
lokasiResepsi="Gedung Serbaguna Padang"
|
|
||||||
fotoBackground="/img/background.jpg"
|
|
||||||
fotoPengantinPria="/img/groom.jpg"
|
|
||||||
fotoPengantinWanita="/img/bride.jpg"
|
|
||||||
linkMaps="https://maps.google.com"
|
|
||||||
:gallery="[
|
|
||||||
'/img/gallery1.jpg',
|
|
||||||
'/img/gallery2.jpg',
|
|
||||||
'/img/gallery3.jpg'
|
|
||||||
]"
|
|
||||||
rekeningDigital="BCA - 1234567890 a/n Ahmad"
|
|
||||||
alamatGift="Jl. Merpati No. 45, Padang"
|
|
||||||
:ucapanDoa="[
|
|
||||||
{ nama: 'Rizki', pesan: 'Selamat menempuh hidup baru!' },
|
|
||||||
{ nama: 'Dewi', pesan: 'Semoga menjadi keluarga sakinah mawaddah warahmah' }
|
|
||||||
]"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import WeddingA from '~/components/templates/wedding/weddingA.vue'
|
|
||||||
</script>
|
|
||||||
Loading…
Reference in New Issue
Block a user