update form
This commit is contained in:
parent
3dbd356d2f
commit
961fb7724e
@ -77,7 +77,7 @@ class TemplateApiController extends Controller
|
|||||||
});
|
});
|
||||||
|
|
||||||
return response()->json($templates);
|
return response()->json($templates);
|
||||||
|
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return response()->json([
|
return response()->json([
|
||||||
'error' => $e->getMessage(),
|
'error' => $e->getMessage(),
|
||||||
@ -87,4 +87,4 @@ class TemplateApiController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,7 +21,8 @@
|
|||||||
<input :value="form.nama_template" type="text" placeholder="Nama Template" class="input-readonly" readonly />
|
<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.kategori" type="text" placeholder="Kategori" class="input-readonly" readonly />
|
||||||
<input :value="form.harga" type="text" placeholder="Harga" 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 />
|
<input :value="form.tanggal_pemesanan" type="text" placeholder="Tanggal Pemesanan" class="input-readonly"
|
||||||
|
readonly />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -44,7 +45,8 @@
|
|||||||
<h2 class="text-lg font-bold text-gray-800 mb-4">Detail Khitan</h2>
|
<h2 class="text-lg font-bold text-gray-800 mb-4">Detail Khitan</h2>
|
||||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||||
<input v-model="form.nama_lengkap_anak" type="text" placeholder="Nama Lengkap Anak" class="input" required />
|
<input v-model="form.nama_lengkap_anak" type="text" placeholder="Nama Lengkap Anak" class="input" required />
|
||||||
<input v-model="form.nama_panggilan_anak" type="text" placeholder="Nama Panggilan Anak" class="input" required />
|
<input v-model="form.nama_panggilan_anak" type="text" placeholder="Nama Panggilan Anak" class="input"
|
||||||
|
required />
|
||||||
<input v-model="form.bapak_anak" type="text" placeholder="Nama Bapak" class="input" />
|
<input v-model="form.bapak_anak" type="text" placeholder="Nama Bapak" class="input" />
|
||||||
<input v-model="form.ibu_anak" type="text" placeholder="Nama Ibu" class="input" />
|
<input v-model="form.ibu_anak" type="text" placeholder="Nama Ibu" class="input" />
|
||||||
</div>
|
</div>
|
||||||
@ -76,36 +78,64 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
<div 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 (max 5 gambar)</h2>
|
<h2 class="text-lg font-bold text-gray-800 mb-4">Galeri (max 5 gambar)</h2>
|
||||||
<input type="file" multiple accept="image/*" @change="handleFileUpload" class="hidden" id="gallery-upload" />
|
<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 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">
|
<div v-for="(img, i) in previewImages" :key="i"
|
||||||
<img :src="img" alt="Preview" class="object-cover w-full h-full" />
|
class="relative w-full aspect-square rounded-lg overflow-hidden shadow-sm group">
|
||||||
<button
|
<img :src="img" alt="Preview" class="object-cover w-full h-full" />
|
||||||
type="button"
|
<button type="button" @click="removeImage(i)"
|
||||||
@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"
|
||||||
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"
|
aria-label="Hapus gambar">
|
||||||
aria-label="Hapus gambar"
|
×
|
||||||
>
|
</button>
|
||||||
×
|
</div>
|
||||||
</button>
|
|
||||||
</div>
|
<label v-if="previewImages.length < 5" 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">
|
||||||
<label v-if="previewImages.length < 5" 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"
|
||||||
<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">
|
stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<!-- Pilihan Fitur -->
|
||||||
|
<section v-for="kategori in kategoriFiturs" :key="kategori.id"
|
||||||
|
class="p-6 bg-white rounded-xl shadow-sm border border-gray-200 mb-6">
|
||||||
|
<h2 class="text-lg font-bold text-gray-800 mb-4">{{ kategori.nama }}</h2>
|
||||||
|
|
||||||
|
<!-- Radio -->
|
||||||
|
<div v-if="kategori.tipe === 'radio'" class="space-y-2">
|
||||||
|
<label v-for="fitur in kategori.fiturs" :key="fitur.id" class="flex items-center gap-2">
|
||||||
|
<input type="radio" :name="'fitur_' + kategori.id" :value="fitur.id"
|
||||||
|
v-model="form.selectedFiturs[kategori.id]" />
|
||||||
|
{{ fitur.deskripsi }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Checkbox -->
|
||||||
|
<div v-else class="space-y-2">
|
||||||
|
<label v-for="fitur in kategori.fiturs" :key="fitur.id" class="flex items-center gap-2">
|
||||||
|
<input type="checkbox" :value="fitur.id" v-model="form.selectedFiturs[kategori.id]" />
|
||||||
|
{{ fitur.deskripsi }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<!-- Submit -->
|
<!-- Submit -->
|
||||||
<div class="mt-10 text-center">
|
<div class="mt-10 text-center">
|
||||||
<button @click="submitForm" 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">
|
<button @click="submitForm"
|
||||||
|
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" }}
|
{{ loading ? "Mengirim..." : "Kirim & Konfirmasi Admin" }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -151,6 +181,8 @@ const form = ref({
|
|||||||
no_rekening2: "",
|
no_rekening2: "",
|
||||||
link_musik: "",
|
link_musik: "",
|
||||||
galeri: [],
|
galeri: [],
|
||||||
|
selectedFiturs: {}, // { kategori_id: [fitur_id] }
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const previewImages = ref([]);
|
const previewImages = ref([]);
|
||||||
@ -167,13 +199,16 @@ onMounted(async () => {
|
|||||||
form.value.kategori_id = template.kategori_id;
|
form.value.kategori_id = template.kategori_id;
|
||||||
form.value.kategori = template.kategori?.nama || "-";
|
form.value.kategori = template.kategori?.nama || "-";
|
||||||
form.value.harga = template.harga;
|
form.value.harga = template.harga;
|
||||||
form.value.fiturs = template.fiturs.map(f => f.deskripsi);
|
|
||||||
|
// simpan kategori fitur
|
||||||
|
kategoriFiturs.value = template.kategori_fiturs || [];
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Gagal ambil template", err);
|
console.error("Gagal ambil template", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// FUNGSI UNTUK MENAMBAH GAMBAR
|
// FUNGSI UNTUK MENAMBAH GAMBAR
|
||||||
const handleFileUpload = (event) => {
|
const handleFileUpload = (event) => {
|
||||||
const newFiles = Array.from(event.target.files);
|
const newFiles = Array.from(event.target.files);
|
||||||
@ -183,7 +218,7 @@ const handleFileUpload = (event) => {
|
|||||||
form.value.galeri = combinedFiles.slice(0, 5);
|
form.value.galeri = combinedFiles.slice(0, 5);
|
||||||
|
|
||||||
// Buat ulang array preview berdasarkan data file yang sudah final
|
// Buat ulang array preview berdasarkan data file yang sudah final
|
||||||
previewImages.value = [];
|
previewImages.value = [];
|
||||||
form.value.galeri.forEach(file => {
|
form.value.galeri.forEach(file => {
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
@ -212,11 +247,19 @@ const submitForm = async () => {
|
|||||||
for (const key in form.value) {
|
for (const key in form.value) {
|
||||||
if (key === "galeri") {
|
if (key === "galeri") {
|
||||||
form.value.galeri.forEach((file) => body.append("galeri[]", file));
|
form.value.galeri.forEach((file) => body.append("galeri[]", file));
|
||||||
} else {
|
} else if (key !== "selectedFiturs") {
|
||||||
body.append(key, form.value[key]);
|
body.append(key, form.value[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// kirim fitur sebagai array fitur_id
|
||||||
|
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/khitan", {
|
await $fetch("http://localhost:8000/api/form/khitan", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body,
|
body,
|
||||||
@ -224,45 +267,18 @@ const submitForm = async () => {
|
|||||||
|
|
||||||
success.value = true;
|
success.value = true;
|
||||||
|
|
||||||
|
// WA notif (biar tetap jalan)
|
||||||
const adminNumber = "62895602603247";
|
const adminNumber = "62895602603247";
|
||||||
|
const message = `
|
||||||
// ✅ Susun pesan otomatis
|
|
||||||
const message = `
|
|
||||||
Halo Admin, ada pemesanan undangan khitan baru 🎉
|
Halo Admin, ada pemesanan undangan khitan baru 🎉
|
||||||
|
|
||||||
📌 Data Pemesan:
|
|
||||||
Nama Pemesan: ${form.value.nama_pemesan}
|
Nama Pemesan: ${form.value.nama_pemesan}
|
||||||
No WA: ${form.value.no_hp}
|
No WA: ${form.value.no_hp}
|
||||||
Email: ${form.value.email}
|
Email: ${form.value.email}
|
||||||
|
|
||||||
👦 Data Anak:
|
|
||||||
Nama Lengkap: ${form.value.nama_lengkap_anak}
|
|
||||||
Nama Panggilan: ${form.value.nama_panggilan_anak}
|
|
||||||
Ayah: ${form.value.bapak_anak || "-"}
|
|
||||||
Ibu: ${form.value.ibu_anak || "-"}
|
|
||||||
|
|
||||||
📅 Jadwal Acara:
|
|
||||||
Tanggal: ${form.value.hari_tanggal_acara}
|
|
||||||
Waktu: ${form.value.waktu_acara}
|
|
||||||
Alamat: ${form.value.alamat_acara}
|
|
||||||
Google Maps: ${form.value.maps_acara || "-"}
|
|
||||||
|
|
||||||
💳 Informasi Tambahan:
|
|
||||||
Rekening 1: ${form.value.no_rekening1 || "-"}
|
|
||||||
Rekening 2: ${form.value.no_rekening2 || "-"}
|
|
||||||
Musik: ${form.value.link_musik || "-"}
|
|
||||||
|
|
||||||
🎨 Template & Order:
|
|
||||||
Template: ${form.value.nama_template} (${form.value.kategori})
|
Template: ${form.value.nama_template} (${form.value.kategori})
|
||||||
Harga: ${form.value.harga}
|
Harga: ${form.value.harga}
|
||||||
Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
|
Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
|
||||||
`;
|
`;
|
||||||
|
window.location.href = `https://wa.me/${adminNumber}?text=${encodeURIComponent(message)}`;
|
||||||
// ✅ Redirect ke WhatsApp
|
|
||||||
const waUrl = `https://wa.me/${adminNumber}?text=${encodeURIComponent(message)}`;
|
|
||||||
window.location.href = waUrl;
|
|
||||||
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
error.value = true;
|
error.value = true;
|
||||||
@ -271,4 +287,3 @@ Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="max-w-5xl mx-auto p-8 bg-gradient-to-b from-pink-50 to-red-50 shadow-lg rounded-xl">
|
<div class="max-w-5xl mx-auto p-8 bg-gradient-to-b from-pink-50 to-red-50 shadow-lg rounded-xl">
|
||||||
<!-- Judul Form -->
|
<!-- Judul Form -->
|
||||||
<div class="text-center mb-10">
|
<div class="text-center mb-10">
|
||||||
<h1 class="text-3xl md:text-4xl font-extrabold text-red-700 drop-shadow-sm">
|
<h1 class="text-3xl md:text-4xl font-extrabold text-red-700 drop-shadow-sm">
|
||||||
@ -21,7 +21,8 @@
|
|||||||
<input :value="form.nama_template" type="text" placeholder="Nama Template" class="input-readonly" readonly />
|
<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.kategori" type="text" placeholder="Kategori" class="input-readonly" readonly />
|
||||||
<input :value="form.harga" type="text" placeholder="Harga" 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 />
|
<input :value="form.tanggal_pemesanan" type="text" placeholder="Tanggal Pemesanan" class="input-readonly"
|
||||||
|
readonly />
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@ -66,13 +67,9 @@
|
|||||||
<!-- Cerita Kita -->
|
<!-- Cerita Kita -->
|
||||||
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
<section class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
||||||
<h2 class="text-lg font-bold text-gray-800 mb-10">Cerita Kita</h2>
|
<h2 class="text-lg font-bold text-gray-800 mb-10">Cerita Kita</h2>
|
||||||
<textarea
|
<textarea v-model="form.cerita_kita" placeholder="Tuliskan cerita indah kalian di sini..." rows="1"
|
||||||
v-model="form.cerita_kita"
|
class="w-full border border-gray-300 rounded-md px-3 py-3 focus:ring-2 focus:ring-blue-500 focus:outline-none transition resize-none"
|
||||||
placeholder="Tuliskan cerita indah kalian di sini..."
|
@input="e => { e.target.style.height = 'auto'; e.target.style.height = e.target.scrollHeight + 'px' }" />
|
||||||
rows="1"
|
|
||||||
class="w-full border border-gray-300 rounded-md px-3 py-3 focus:ring-2 focus:ring-blue-500 focus:outline-none transition resize-none"
|
|
||||||
@input="e => { e.target.style.height = 'auto'; e.target.style.height = e.target.scrollHeight + 'px' }"
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
@ -109,40 +106,70 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
<div 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 (max 5 gambar)</h2>
|
<h2 class="text-lg font-bold text-gray-800 mb-4">Galeri (max 5 gambar)</h2>
|
||||||
<input type="file" multiple accept="image/*" @change="handleFileUpload" class="hidden" id="gallery-upload" />
|
<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 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">
|
<div v-for="(img, i) in previewImages" :key="i"
|
||||||
<img :src="img" alt="Preview" class="object-cover w-full h-full" />
|
class="relative w-full aspect-square rounded-lg overflow-hidden shadow-sm group">
|
||||||
<button
|
<img :src="img" alt="Preview" class="object-cover w-full h-full" />
|
||||||
type="button"
|
<button type="button" @click="removeImage(i)"
|
||||||
@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"
|
||||||
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"
|
aria-label="Hapus gambar">
|
||||||
aria-label="Hapus gambar"
|
×
|
||||||
>
|
</button>
|
||||||
×
|
</div>
|
||||||
</button>
|
<label v-if="previewImages.length < 5" for="gallery-upload"
|
||||||
</div>
|
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">
|
||||||
<label v-if="previewImages.length < 5" 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"
|
||||||
<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">
|
stroke="currentColor">
|
||||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4" />
|
||||||
</svg>
|
</svg>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</form>
|
</form>
|
||||||
|
|
||||||
|
<!-- Kategori & Fitur -->
|
||||||
|
<section v-for="kategori in kategoriFiturs" :key="kategori.id"
|
||||||
|
class="p-6 bg-white rounded-xl shadow-sm border border-gray-200">
|
||||||
|
<h2 class="text-lg font-bold text-gray-800 mb-4">
|
||||||
|
{{ kategori.nama }}
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<!-- Radio -->
|
||||||
|
<div v-if="kategori.tipe === 'radio'">
|
||||||
|
<label v-for="fitur in kategori.fiturs" :key="fitur.id" class="flex items-center gap-2 mb-2">
|
||||||
|
<input type="radio" :name="'kategori_' + kategori.id" :value="fitur.id"
|
||||||
|
v-model="form.selectedFiturs[kategori.id]" />
|
||||||
|
{{ fitur.deskripsi }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Checkbox -->
|
||||||
|
<div v-else>
|
||||||
|
<label v-for="fitur in kategori.fiturs" :key="fitur.id" class="flex items-center gap-2 mb-2">
|
||||||
|
<input type="checkbox" :value="fitur.id" v-model="form.selectedFiturs[kategori.id]" />
|
||||||
|
{{ fitur.deskripsi }}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<!-- Submit -->
|
<!-- Submit -->
|
||||||
<div class="mt-10 text-center">
|
<div class="mt-10 text-center">
|
||||||
<button @click="submitForm" 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">
|
<button @click="submitForm"
|
||||||
|
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" }}
|
{{ loading ? "Mengirim..." : "Kirim & Konfirmasi Admin" }}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Alert -->
|
<!-- 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! Silakan tunggu konfirmasi dari admin.</div>
|
<div v-if="success" class="mt-6 p-4 text-green-800 bg-green-100 rounded-lg text-center font-medium">✅ Form berhasil
|
||||||
<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>
|
dikirim! Silakan tunggu konfirmasi dari 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.
|
||||||
|
Pastikan semua data yang wajib diisi sudah lengkap.</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -152,13 +179,16 @@ import { useRoute } from "vue-router";
|
|||||||
|
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
// 1. STRUKTUR DATA DISESUAIKAN DENGAN BACKEND
|
|
||||||
const form = ref({
|
const form = ref({
|
||||||
template_id: "",
|
template_id: "",
|
||||||
nama_template: "",
|
nama_template: "",
|
||||||
kategori: "",
|
kategori: "",
|
||||||
harga: "",
|
harga: "",
|
||||||
tanggal_pemesanan: new Date().toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' }),
|
tanggal_pemesanan: new Date().toLocaleDateString("id-ID", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "long",
|
||||||
|
day: "numeric",
|
||||||
|
}),
|
||||||
|
|
||||||
nama_pemesan: "",
|
nama_pemesan: "",
|
||||||
no_hp: "",
|
no_hp: "",
|
||||||
@ -196,8 +226,12 @@ const form = ref({
|
|||||||
no_rekening2: "",
|
no_rekening2: "",
|
||||||
link_musik: "",
|
link_musik: "",
|
||||||
galeri: [],
|
galeri: [],
|
||||||
|
|
||||||
|
|
||||||
|
selectedFiturs: {}, // { kategori_id: [fitur_id] }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const kategoriFiturs = ref([]); // 🆕 simpan kategori fitur
|
||||||
const previewImages = ref([]);
|
const previewImages = ref([]);
|
||||||
const loading = ref(false);
|
const loading = ref(false);
|
||||||
const success = ref(false);
|
const success = ref(false);
|
||||||
@ -206,11 +240,20 @@ const error = ref(false);
|
|||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (route.query.template_id) {
|
if (route.query.template_id) {
|
||||||
try {
|
try {
|
||||||
const template = await $fetch(`http://localhost:8000/api/templates/${route.query.template_id}`);
|
const template = await $fetch(
|
||||||
|
`http://localhost:8000/api/templates/${route.query.template_id}`
|
||||||
|
);
|
||||||
|
|
||||||
form.value.template_id = template.id;
|
form.value.template_id = template.id;
|
||||||
form.value.nama_template = template.nama_template;
|
form.value.nama_template = template.nama_template;
|
||||||
form.value.kategori = template.kategori?.nama || "-";
|
form.value.kategori = template.kategori?.nama || "-";
|
||||||
form.value.harga = new Intl.NumberFormat('id-ID', { style: 'currency', currency: 'IDR' }).format(template.harga);
|
form.value.harga = new Intl.NumberFormat("id-ID", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "IDR",
|
||||||
|
}).format(template.harga);
|
||||||
|
|
||||||
|
// 🆕 simpan kategori fitur
|
||||||
|
kategoriFiturs.value = template.kategori_fiturs || [];
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Gagal ambil template", err);
|
console.error("Gagal ambil template", err);
|
||||||
}
|
}
|
||||||
@ -222,12 +265,10 @@ const handleFileUpload = (event) => {
|
|||||||
const newFiles = Array.from(event.target.files);
|
const newFiles = Array.from(event.target.files);
|
||||||
const combinedFiles = [...form.value.galeri, ...newFiles];
|
const combinedFiles = [...form.value.galeri, ...newFiles];
|
||||||
|
|
||||||
// Batasi total file menjadi 5
|
|
||||||
form.value.galeri = combinedFiles.slice(0, 5);
|
form.value.galeri = combinedFiles.slice(0, 5);
|
||||||
|
|
||||||
// Buat ulang array preview berdasarkan data file yang sudah final
|
previewImages.value = [];
|
||||||
previewImages.value = [];
|
form.value.galeri.forEach((file) => {
|
||||||
form.value.galeri.forEach(file => {
|
|
||||||
const reader = new FileReader();
|
const reader = new FileReader();
|
||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
previewImages.value.push(e.target.result);
|
previewImages.value.push(e.target.result);
|
||||||
@ -235,11 +276,10 @@ const handleFileUpload = (event) => {
|
|||||||
reader.readAsDataURL(file);
|
reader.readAsDataURL(file);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Reset input agar bisa memilih file yang sama lagi
|
|
||||||
event.target.value = null;
|
event.target.value = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
// FUNGSI UNTUK MENGHAPUS GAMBAR (SEKARANG DI LUAR)
|
// FUNGSI UNTUK MENGHAPUS GAMBAR
|
||||||
const removeImage = (index) => {
|
const removeImage = (index) => {
|
||||||
form.value.galeri.splice(index, 1);
|
form.value.galeri.splice(index, 1);
|
||||||
previewImages.value.splice(index, 1);
|
previewImages.value.splice(index, 1);
|
||||||
@ -252,15 +292,27 @@ const submitForm = async () => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
const body = new FormData();
|
const body = new FormData();
|
||||||
|
|
||||||
|
// field umum
|
||||||
for (const key in form.value) {
|
for (const key in form.value) {
|
||||||
if (key === "galeri") {
|
if (key === "galeri" || key === "selectedFiturs") continue;
|
||||||
form.value.galeri.forEach((file) => body.append("galeri[]", file));
|
if (form.value[key] !== null && form.value[key] !== undefined) {
|
||||||
} else if (form.value[key] !== null && form.value[key] !== undefined) {
|
|
||||||
body.append(key, form.value[key]);
|
body.append(key, form.value[key]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. ENDPOINT API SUDAH BENAR
|
// galeri
|
||||||
|
form.value.galeri.forEach((file) => body.append("galeri[]", file));
|
||||||
|
|
||||||
|
// 🆕 fiturs
|
||||||
|
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/pernikahan", {
|
await $fetch("http://localhost:8000/api/form/pernikahan", {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
body,
|
body,
|
||||||
@ -268,10 +320,7 @@ const submitForm = async () => {
|
|||||||
|
|
||||||
success.value = true;
|
success.value = true;
|
||||||
|
|
||||||
|
|
||||||
const adminNumber = "62895602603247";
|
const adminNumber = "62895602603247";
|
||||||
|
|
||||||
// ✅ Susun pesan otomatis
|
|
||||||
const message = `
|
const message = `
|
||||||
Halo Admin, ada pemesanan undangan pernikahan baru 🎉
|
Halo Admin, ada pemesanan undangan pernikahan baru 🎉
|
||||||
|
|
||||||
@ -293,13 +342,9 @@ Harga: ${form.value.harga}
|
|||||||
Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
|
Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
// ✅ Redirect ke WhatsApp
|
window.location.href = `https://wa.me/${adminNumber}?text=${encodeURIComponent(
|
||||||
const waUrl = `https://wa.me/${adminNumber}?text=${encodeURIComponent(message)}`;
|
message
|
||||||
window.location.href = waUrl;
|
)}`;
|
||||||
|
|
||||||
|
|
||||||
// Optional: Reset form after success
|
|
||||||
// Object.keys(form.value).forEach(key => form.value[key] = '');
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
error.value = true;
|
error.value = true;
|
||||||
@ -307,4 +352,4 @@ Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
|
|||||||
loading.value = false;
|
loading.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
<div class="footer-column">
|
<div class="footer-column">
|
||||||
<h4>Layanan</h4>
|
<h4>Layanan</h4>
|
||||||
<ul class="footer-links">
|
<ul class="footer-links">
|
||||||
<li><a href="#">Template Undangan Pernikahan</a></li>
|
<li><a href="/template/Pernikahan">Template Undangan Pernikahan</a></li>
|
||||||
<li><a href="#">Template Undangan Khitan</a></li>
|
<li><a href="#">Template Undangan Khitan</a></li>
|
||||||
<li><a href="#">Template Undangan Ulang Tahun</a></li>
|
<li><a href="#">Template Undangan Ulang Tahun</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
@ -19,19 +19,42 @@
|
|||||||
<ul class="footer-contact-list">
|
<ul class="footer-contact-list">
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="social-link">
|
<a href="#" class="social-link">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v2.385z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path
|
||||||
|
d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v2.385z" />
|
||||||
|
</svg>
|
||||||
<span>ABBAUF TECH</span>
|
<span>ABBAUF TECH</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="social-link">
|
<a href="https://instagram.com/abbauftech" target="_blank" class="inline-flex items-center gap-2 font-medium
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.85s-.011 3.584-.069 4.85c-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07s-3.584-.012-4.85-.07c-3.252-.148-4.771-1.691-4.919-4.919-.058-1.265-.069-1.645-.069-4.85s.011-3.584.069-4.85c.149-3.225 1.664-4.771 4.919-4.919 1.266-.057 1.644-.069 4.85-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948s.014 3.667.072 4.947c.2 4.359 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072s3.667-.014 4.947-.072c4.359-.2 6.78-2.618 6.98-6.98.058-1.281.072-1.689.072-4.948s-.014-3.667-.072-4.947c-.2-4.359-2.618-6.78-6.98-6.98-1.281-.058-1.689-.072-4.948-.072zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.162 6.162 6.162 6.162-2.759 6.162-6.162-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4s1.791-4 4-4 4 1.79 4 4-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.441 1.441 1.441 1.441-.645 1.441-1.441-.645-1.44-1.441-1.44z"/></svg>
|
bg-gradient-to-r from-purple-500 via-pink-500 to-orange-500
|
||||||
<span>@abbauf_tech</span>
|
bg-clip-text text-transparent
|
||||||
|
hover:scale-110 transition-all duration-300">
|
||||||
|
<!-- Ikon Instagram -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24"
|
||||||
|
fill="url(#igGradient)">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="igGradient" x1="0%" y1="0%" x2="100%" y2="100%">
|
||||||
|
<stop offset="0%" style="stop-color:#8a3ab9" />
|
||||||
|
<stop offset="50%" style="stop-color:#e95950" />
|
||||||
|
<stop offset="100%" style="stop-color:#fccc63" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<path d="M7.75 2h8.5A5.75 5.75 0 0 1 22 7.75v8.5A5.75 5.75 0 0 1 16.25 22h-8.5A5.75 5.75 0 0 1 2 16.25v-8.5A5.75 5.75 0 0 1 7.75 2zm0 1.5A4.25 4.25 0 0 0 3.5 7.75v8.5A4.25 4.25 0 0 0 7.75 20.5h8.5a4.25 4.25 0 0 0 4.25-4.25v-8.5A4.25 4.25 0 0 0 16.25 3.5h-8.5zm4.25 3a5.75 5.75 0 1 1 0 11.5 5.75 5.75 0 0 1 0-11.5zm0 1.5a4.25 4.25 0 1 0 0 8.5 4.25 4.25 0 0 0 0-8.5zm5-2.25a1 1 0 1 1 0 2 1 1 0 0 1 0-2z" />
|
||||||
|
</svg>
|
||||||
|
<!-- Nama IG -->
|
||||||
|
<span>@abbauftech</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<a href="#" class="social-link">
|
<a href="https://www.linkedin.com/posts/abbauf-tech_abbauftech-digitalstrategy-itconsulting-activity-7277021563982340099-8Byg" class="social-link">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M4.98 3.5c0 1.381-1.11 2.5-2.48 2.5s-2.48-1.119-2.48-2.5c0-1.38 1.11-2.5 2.48-2.5s2.48 1.12 2.48 2.5zm.02 4.5h-5v16h5v-16zm7.982 0h-4.968v16h4.969v-8.399c0-4.67 6.029-5.052 6.029 0v8.399h4.988v-10.131c0-7.88-8.922-7.593-11.018-3.714v-2.155z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path
|
||||||
|
d="M4.98 3.5c0 1.381-1.11 2.5-2.48 2.5s-2.48-1.119-2.48-2.5c0-1.38 1.11-2.5 2.48-2.5s2.48 1.12 2.48 2.5zm.02 4.5h-5v16h5v-16zm7.982 0h-4.968v16h4.969v-8.399c0-4.67 6.029-5.052 6.029 0v8.399h4.988v-10.131c0-7.88-8.922-7.593-11.018-3.714v-2.155z" />
|
||||||
|
</svg>
|
||||||
<span>ABBAUF TECH</span>
|
<span>ABBAUF TECH</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@ -42,26 +65,41 @@
|
|||||||
<h4>Kontak Kami</h4>
|
<h4>Kontak Kami</h4>
|
||||||
<ul class="footer-contact-list">
|
<ul class="footer-contact-list">
|
||||||
<li>
|
<li>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M0 3v18h24v-18h-24zm21.518 2l-9.518 7.713-9.518-7.713h19.036zm-19.518 14v-11.817l10 8.104 10-8.104v11.817h-20z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path
|
||||||
|
d="M0 3v18h24v-18h-24zm21.518 2l-9.518 7.713-9.518-7.713h19.036zm-19.518 14v-11.817l10 8.104 10-8.104v11.817h-20z" />
|
||||||
|
</svg>
|
||||||
<a href="mailto:contact@abbauf.com">contact@abbauf.com</a>
|
<a href="mailto:contact@abbauf.com">contact@abbauf.com</a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M20 22.621l-3.521-6.795c-.008.004-1.974.97-2.064 1.011-2.24 1.086-6.799-3.473-5.712-5.713.041-.09 1.011-2.064 1.011-2.064l-6.795-3.521-2.918 2.918c-1.603 1.603-1.425 4.933 1.011 7.37 4.301 4.301 9.962 3.593 12.301.954l2.688-2.355-2.356-2.688z"/></svg>
|
<a :href="waUrl" target="_blank"
|
||||||
<a href="tel:02127617679">(021) 2761-7679</a>
|
class="inline-flex items-center gap-2 hover:text-green-600 transition-colors">
|
||||||
|
<!-- Ikon WhatsApp -->
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path
|
||||||
|
d="M.057 24l1.687-6.163c-1.041-1.804-1.588-3.849-1.587-5.946.003-6.556 5.338-11.891 11.893-11.891 3.181.001 6.167 1.24 8.413 3.488 2.245 2.248 3.481 5.236 3.48 8.414-.003 6.557-5.338 11.892-11.894 11.892-1.99-.001-3.951-.5-5.688-1.448l-6.305 1.654zm6.597-3.807c1.676.995 3.276 1.591 5.392 1.592 5.448 0 9.886-4.434 9.889-9.885.002-5.462-4.415-9.89-9.881-9.892-5.452 0-9.887 4.434-9.889 9.884-.001 2.225.651 3.891 1.746 5.634l-.999 3.648 3.742-.981zm11.387-5.464c-.074-.124-.272-.198 -.57-.347-.297-.149-1.758-.868-2.031-.967-.272-.099-.47-.149-.669.149-.198.297-.768.967-.941 1.165-.173.198-.347.223-.644.074-.297-.14-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579 -.487-.5-.669-.51-.173-.008-.371-.01-.57-.01s-.52.074-.792.372 c-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.626.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29 .173-1.414z" />
|
||||||
|
</svg>
|
||||||
|
<!-- Nomor WA -->
|
||||||
|
<span>+62 878-7711-7847</span>
|
||||||
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li>
|
<li>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M.057 24l1.687-6.163c-1.041-1.804-1.588-3.849-1.587-5.946.003-6.556 5.338-11.891 11.893-11.891 3.181.001 6.167 1.24 8.413 3.488 2.245 2.248 3.481 5.236 3.48 8.414-.003 6.557-5.338 11.892-11.894 11.892-1.99-.001-3.951-.5-5.688-1.448l-6.305 1.654zm6.597-3.807c1.676.995 3.276 1.591 5.392 1.592 5.448 0 9.886-4.434 9.889-9.885.002-5.462-4.415-9.89-9.881-9.892-5.452 0-9.887 4.434-9.889 9.884-.001 2.225.651 3.891 1.746 5.634l-.999 3.648 3.742-.981zm11.387-5.464c-.074-.124-.272-.198-.57-.347-.297-.149-1.758-.868-2.031-.967-.272-.099-.47-.149-.669.149-.198.297-.768.967-.941 1.165-.173.198-.347.223-.644.074-.297-.149-1.255-.462-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.297-.347.446-.521.151-.172.2-.296.3-.495.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01s-.52.074-.792.372c-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.626.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.695.248-1.29.173-1.414z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||||
<a href="#">+62 878-7711-7847</a>
|
<path
|
||||||
</li>
|
d="M12 0c-4.198 0-8 3.403-8 7.602 0 4.198 3.469 9.21 8 16.398 4.531-7.188 8-12.2 8-16.398 0-4.199-3.801-7.602-8-7.602zm0 11c-1.657 0-3-1.343-3-3s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3z" />
|
||||||
<li>
|
</svg>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-4.198 0-8 3.403-8 7.602 0 4.198 3.469 9.21 8 16.398 4.531-7.188 8-12.2 8-16.398 0-4.199-3.801-7.602-8-7.602zm0 11c-1.657 0-3-1.343-3-3s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3z"/></svg>
|
|
||||||
<div>
|
<div>
|
||||||
<strong>Alamat Kantor Pusat</strong>
|
<strong>Alamat Kantor Pusat</strong>
|
||||||
<p>APL Tower Central Park Lantai 19 Unit T7, Jalan Letjen S. Parman, Kavling 28, RT. 012/006, Kel. Tanjung Duren, Kec. Grogol Petamburan, Jakarta Barat, DKI Jakarta 11470, ID</p>
|
<p>APL Tower Central Park Lantai 19 Unit T7, Jalan Letjen S. Parman, Kavling 28, RT. 012/006, Kel. Tanjung
|
||||||
|
Duren, Kec. Grogol Petamburan, Jakarta Barat, DKI Jakarta 11470, ID</p>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><path d="M12 0c-4.198 0-8 3.403-8 7.602 0 4.198 3.469 9.21 8 16.398 4.531-7.188 8-12.2 8-16.398 0-4.199-3.801-7.602-8-7.602zm0 11c-1.657 0-3-1.343-3-3s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3z"/></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor">
|
||||||
|
<path
|
||||||
|
d="M12 0c-4.198 0-8 3.403-8 7.602 0 4.198 3.469 9.21 8 16.398 4.531-7.188 8-12.2 8-16.398 0-4.199-3.801-7.602-8-7.602zm0 11c-1.657 0-3-1.343-3-3s1.343-3 3-3 3 1.343 3 3-1.343 3-3 3z" />
|
||||||
|
</svg>
|
||||||
<div>
|
<div>
|
||||||
<strong>Alamat Studio</strong>
|
<strong>Alamat Studio</strong>
|
||||||
<p>Jl. Adhi Karya No. 57 RT 003 RW 015, Kel. Depok, Kec. Pancoran Mas, Depok 16431</p>
|
<p>Jl. Adhi Karya No. 57 RT 003 RW 015, Kel. Depok, Kec. Pancoran Mas, Depok 16431</p>
|
||||||
@ -78,12 +116,16 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
// Tidak ada script yang dibutuhkan untuk footer statis ini
|
|
||||||
|
const adminNumber = "62895602603247";
|
||||||
|
const defaultMessage = "Halo Admin, saya mau tanya tentang undangan digital 🙏";
|
||||||
|
const waUrl = `https://wa.me/${adminNumber}?text=${encodeURIComponent(defaultMessage)}`;
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.site-footer {
|
.site-footer {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #f0f2f5;
|
background-color: #f0f2f5;
|
||||||
color: #333;
|
color: #333;
|
||||||
padding: 50px 0 20px 0;
|
padding: 50px 0 20px 0;
|
||||||
@ -98,7 +140,8 @@
|
|||||||
|
|
||||||
.footer-content {
|
.footer-content {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 2fr 1.5fr 1.5fr 2.5fr; /* Mengatur lebar kolom */
|
grid-template-columns: 2fr 1.5fr 1.5fr 2.5fr;
|
||||||
|
/* Mengatur lebar kolom */
|
||||||
gap: 40px;
|
gap: 40px;
|
||||||
padding-bottom: 30px;
|
padding-bottom: 30px;
|
||||||
border-bottom: 1px solid #d9dce1;
|
border-bottom: 1px solid #d9dce1;
|
||||||
@ -116,7 +159,8 @@
|
|||||||
color: #111;
|
color: #111;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-links, .footer-contact-list {
|
.footer-links,
|
||||||
|
.footer-contact-list {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -126,14 +170,17 @@
|
|||||||
margin-bottom: 12px;
|
margin-bottom: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-links a, .social-link {
|
.footer-links a,
|
||||||
|
.social-link {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #555;
|
color: #555;
|
||||||
transition: color 0.3s ease;
|
transition: color 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-links a:hover, .social-link:hover {
|
.footer-links a:hover,
|
||||||
color: #0d6efd; /* Biru Primer */
|
.social-link:hover {
|
||||||
|
color: #0d6efd;
|
||||||
|
/* Biru Primer */
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-contact-list li {
|
.footer-contact-list li {
|
||||||
@ -153,6 +200,7 @@
|
|||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
color: #555;
|
color: #555;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-contact-list a:hover {
|
.footer-contact-list a:hover {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
@ -185,21 +233,27 @@
|
|||||||
/* Penyesuaian untuk layar kecil (Mobile) */
|
/* Penyesuaian untuk layar kecil (Mobile) */
|
||||||
@media (max-width: 992px) {
|
@media (max-width: 992px) {
|
||||||
.footer-content {
|
.footer-content {
|
||||||
grid-template-columns: 1fr 1fr; /* 2 kolom di tablet */
|
grid-template-columns: 1fr 1fr;
|
||||||
|
/* 2 kolom di tablet */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.footer-content {
|
.footer-content {
|
||||||
grid-template-columns: 1fr; /* 1 kolom di mobile */
|
grid-template-columns: 1fr;
|
||||||
|
/* 1 kolom di mobile */
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-brand {
|
.footer-brand {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-logo {
|
.footer-logo {
|
||||||
margin: 0 auto; /* Logo di tengah */
|
margin: 0 auto;
|
||||||
|
/* Logo di tengah */
|
||||||
}
|
}
|
||||||
|
|
||||||
.footer-contact-list li {
|
.footer-contact-list li {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
|
|||||||
@ -1,8 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="flex items-center mb-8">
|
<div class="flex items-center mb-8">
|
||||||
<button @click="$emit('back')" class="text-blue-600 hover:text-blue-800 font-semibold inline-flex items-center mr-4">
|
<button @click="$emit('back')"
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z" clip-rule="evenodd" /></svg>
|
class="text-blue-600 hover:text-blue-800 font-semibold inline-flex items-center mr-4">
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5 mr-1" viewBox="0 0 20 20" fill="currentColor">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
|
||||||
|
clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
Kembali
|
Kembali
|
||||||
</button>
|
</button>
|
||||||
<h1 class="text-3xl md:text-4xl font-bold text-gray-800">
|
<h1 class="text-3xl md:text-4xl font-bold text-gray-800">
|
||||||
@ -10,58 +15,71 @@
|
|||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="isLoading" class="text-center py-10"><p>Memuat template...</p></div>
|
<div v-if="isLoading" class="text-center py-10">
|
||||||
<div v-else-if="error" class="text-center py-10 text-red-600"><p>Gagal memuat template.</p></div>
|
<p>Memuat template...</p>
|
||||||
|
|
||||||
<div v-else-if="templates && templates.length > 0" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8 items-start">
|
|
||||||
|
|
||||||
<div v-for="tpl in templates" :key="tpl.id" class="bg-white border rounded-lg overflow-hidden shadow-md hover:shadow-xl transition-shadow duration-300">
|
|
||||||
<img :src="`http://localhost:8000${tpl.foto}`" :alt="tpl.nama" class="w-full h-48 object-cover">
|
|
||||||
|
|
||||||
<div class="p-5 text-center">
|
|
||||||
<h4 class="text-xl font-bold text-gray-800 mb-2">{{ tpl.nama }}</h4>
|
|
||||||
<p class="text-green-600 font-semibold text-xl mb-4">
|
|
||||||
Rp {{ tpl.harga.toLocaleString('id-ID') }}
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div v-if="tpl.fitur && tpl.fitur.length > 0" class="relative mb-4">
|
|
||||||
<button @click="toggleDropdown(tpl.id)" class="w-full bg-white border border-gray-300 rounded-md shadow-sm px-4 py-2 inline-flex justify-between items-center text-center">
|
|
||||||
<span class="mx-auto text-gray-700 font-semibold">FITUR YANG TERSEDIA</span>
|
|
||||||
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor"><path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" /></svg>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div v-if="openDropdownId === tpl.id">
|
|
||||||
<ul class="mt-4 space-y-2 text-gray-600 text-left">
|
|
||||||
<li v-for="item_fitur in tpl.fitur" :key="item_fitur.id" class="flex items-center">
|
|
||||||
<svg class="h-4 w-4 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path></svg>
|
|
||||||
|
|
||||||
{{ item_fitur.deskripsi }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="mt-6">
|
|
||||||
<div class="flex items-center gap-3">
|
|
||||||
<!-- Tombol Preview (masih sama) -->
|
|
||||||
<button
|
|
||||||
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
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<!-- Tombol Order langsung ke form Khitan -->
|
|
||||||
<NuxtLink
|
|
||||||
:to="`/form/${tpl.kategori.nama.toLowerCase().replace(/ /g, '-')}` + `?template_id=${tpl.id}`"
|
|
||||||
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
|
|
||||||
</NuxtLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div v-else-if="error" class="text-center py-10 text-red-600">
|
||||||
|
<p>Gagal memuat template.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="templates && templates.length > 0"
|
||||||
|
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-8 items-start">
|
||||||
|
|
||||||
|
<div v-for="tpl in templates" :key="tpl.id"
|
||||||
|
class="bg-white border rounded-lg overflow-hidden shadow-md hover:shadow-xl transition-shadow duration-300">
|
||||||
|
<img :src="`http://localhost:8000${tpl.foto}`" :alt="tpl.nama" class="w-full h-48 object-cover">
|
||||||
|
|
||||||
|
<div class="p-5 text-center">
|
||||||
|
<h4 class="text-xl font-bold text-gray-800 mb-2">{{ tpl.nama }}</h4>
|
||||||
|
<p class="text-green-600 font-semibold text-xl mb-4">
|
||||||
|
Rp {{ tpl.harga.toLocaleString('id-ID') }}
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div v-if="tpl.fitur && tpl.fitur.length > 0" class="relative mb-4">
|
||||||
|
<button @click="toggleDropdown(tpl.id)"
|
||||||
|
class="w-full bg-white border border-gray-300 rounded-md shadow-sm px-4 py-2 inline-flex justify-between items-center text-center">
|
||||||
|
<span class="mx-auto text-gray-700 font-semibold">FITUR YANG TERSEDIA</span>
|
||||||
|
<svg class="h-5 w-5 text-gray-400" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"
|
||||||
|
fill="currentColor">
|
||||||
|
<path fill-rule="evenodd"
|
||||||
|
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
||||||
|
clip-rule="evenodd" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div v-if="openDropdownId === tpl.id">
|
||||||
|
<ul class="mt-4 space-y-2 text-gray-600 text-left">
|
||||||
|
<li v-for="item_fitur in tpl.fitur" :key="item_fitur.id" class="flex items-center">
|
||||||
|
<svg class="h-4 w-4 text-green-500 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
{{ item_fitur.deskripsi }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-6">
|
||||||
|
<div class="flex items-center gap-3">
|
||||||
|
<!-- Tombol Preview (masih sama) -->
|
||||||
|
<a :href="tpl.id === 1 ? 'https://www.figma.com/proto/T3EQf6Ip0dZIBZMvaKiefE/Mockup-Ivitation?node-id=272-1270&t=bbfeDM0cefEB4xRt-0&scaling=scale-down&content-scaling=fixed&page-id=272%3A228&starting-point-node-id=285%3A273&show-proto-sidebar=1' :
|
||||||
|
'https://www.figma.com/proto/T3EQf6Ip0dZIBZMvaKiefE/Mockup-Ivitation?node-id=285-273&t=bbfeDM0cefEB4xRt-0&scaling=scale-down&content-scaling=fixed&page-id=272%3A228&starting-point-node-id=285%3A273&show-proto-sidebar=1'"
|
||||||
|
target="_blank"
|
||||||
|
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 text-center block">
|
||||||
|
Preview
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<!-- Tombol Order langsung ke form Khitan -->
|
||||||
|
<NuxtLink :to="`/form/${tpl.kategori.nama.toLowerCase().replace(/ /g, '-')}` + `?template_id=${tpl.id}`"
|
||||||
|
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
|
||||||
|
</NuxtLink>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="text-center py-10 text-gray-500">
|
<div v-else class="text-center py-10 text-gray-500">
|
||||||
<p>Belum ada template untuk kategori ini.</p>
|
<p>Belum ada template untuk kategori ini.</p>
|
||||||
@ -94,7 +112,7 @@ const props = defineProps({
|
|||||||
defineEmits(['back']);
|
defineEmits(['back']);
|
||||||
|
|
||||||
const { data: templates, pending: isLoading, error } = useFetch(
|
const { data: templates, pending: isLoading, error } = useFetch(
|
||||||
() => `/api/templates/category/${props.id_category}`,
|
() => `/api/templates/category/${props.id_category}`,
|
||||||
{
|
{
|
||||||
baseURL: 'http://localhost:8000',
|
baseURL: 'http://localhost:8000',
|
||||||
key: () => `templates-${props.id_category}`,
|
key: () => `templates-${props.id_category}`,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user