diff --git a/backend/app/Http/Controllers/Api/TemplateApiController.php b/backend/app/Http/Controllers/Api/TemplateApiController.php
index eeec2be..7624f59 100644
--- a/backend/app/Http/Controllers/Api/TemplateApiController.php
+++ b/backend/app/Http/Controllers/Api/TemplateApiController.php
@@ -77,7 +77,7 @@ class TemplateApiController extends Controller
});
return response()->json($templates);
-
+
} catch (\Exception $e) {
return response()->json([
'error' => $e->getMessage(),
@@ -87,4 +87,4 @@ class TemplateApiController extends Controller
}
}
-}
\ No newline at end of file
+}
diff --git a/proyek-frontend/app/components/forms/KhitanForm.vue b/proyek-frontend/app/components/forms/KhitanForm.vue
index 0b8e960..4d55642 100644
--- a/proyek-frontend/app/components/forms/KhitanForm.vue
+++ b/proyek-frontend/app/components/forms/KhitanForm.vue
@@ -21,7 +21,8 @@
-
+
@@ -44,7 +45,8 @@
Detail Khitan
-
+
@@ -76,36 +78,64 @@
-
Galeri (max 5 gambar)
-
-
-
-
![Preview]()
-
-
-
-
-
-
-
-
+ Galeri (max 5 gambar)
+
+
+
+
![Preview]()
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
@@ -151,6 +181,8 @@ const form = ref({
no_rekening2: "",
link_musik: "",
galeri: [],
+ selectedFiturs: {}, // { kategori_id: [fitur_id] }
+
});
const previewImages = ref([]);
@@ -167,13 +199,16 @@ onMounted(async () => {
form.value.kategori_id = template.kategori_id;
form.value.kategori = template.kategori?.nama || "-";
form.value.harga = template.harga;
- form.value.fiturs = template.fiturs.map(f => f.deskripsi);
+
+ // simpan kategori fitur
+ kategoriFiturs.value = template.kategori_fiturs || [];
} catch (err) {
console.error("Gagal ambil template", err);
}
}
});
+
// FUNGSI UNTUK MENAMBAH GAMBAR
const handleFileUpload = (event) => {
const newFiles = Array.from(event.target.files);
@@ -183,7 +218,7 @@ const handleFileUpload = (event) => {
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 => {
const reader = new FileReader();
reader.onload = (e) => {
@@ -212,11 +247,19 @@ const submitForm = async () => {
for (const key in form.value) {
if (key === "galeri") {
form.value.galeri.forEach((file) => body.append("galeri[]", file));
- } else {
+ } else if (key !== "selectedFiturs") {
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", {
method: "POST",
body,
@@ -224,45 +267,18 @@ const submitForm = async () => {
success.value = true;
-
+ // WA notif (biar tetap jalan)
const adminNumber = "62895602603247";
-
- // ✅ Susun pesan otomatis
- const message = `
+ const message = `
Halo Admin, ada pemesanan undangan khitan baru 🎉
-
-📌 Data Pemesan:
Nama Pemesan: ${form.value.nama_pemesan}
No WA: ${form.value.no_hp}
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})
Harga: ${form.value.harga}
Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
-`;
-
- // ✅ Redirect ke WhatsApp
- const waUrl = `https://wa.me/${adminNumber}?text=${encodeURIComponent(message)}`;
- window.location.href = waUrl;
-
+ `;
+ window.location.href = `https://wa.me/${adminNumber}?text=${encodeURIComponent(message)}`;
} catch (err) {
console.error(err);
error.value = true;
@@ -271,4 +287,3 @@ Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
}
};
-
diff --git a/proyek-frontend/app/components/forms/PernikahanForm.vue b/proyek-frontend/app/components/forms/PernikahanForm.vue
index fa291f8..9d55b2c 100644
--- a/proyek-frontend/app/components/forms/PernikahanForm.vue
+++ b/proyek-frontend/app/components/forms/PernikahanForm.vue
@@ -1,5 +1,5 @@
-
-
Galeri (max 5 gambar)
-
-
-
-
![Preview]()
-
- ×
-
-
-
-
+
Galeri (max 5 gambar)
+
+
+
+
![Preview]()
+
+ ×
+
+
+
+
+
+
+
+
-
+
{{ loading ? "Mengirim..." : "Kirim & Konfirmasi Admin" }}
- ✅ Form berhasil dikirim! Silakan tunggu konfirmasi dari admin.
- ❌ Gagal mengirim form. Pastikan semua data yang wajib diisi sudah lengkap.
+ ✅ Form berhasil
+ dikirim! Silakan tunggu konfirmasi dari admin.
+ ❌ Gagal mengirim form.
+ Pastikan semua data yang wajib diisi sudah lengkap.
@@ -152,13 +179,16 @@ import { useRoute } from "vue-router";
const route = useRoute();
-// 1. STRUKTUR DATA DISESUAIKAN DENGAN BACKEND
const form = ref({
template_id: "",
nama_template: "",
kategori: "",
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: "",
no_hp: "",
@@ -196,8 +226,12 @@ const form = ref({
no_rekening2: "",
link_musik: "",
galeri: [],
+
+
+ selectedFiturs: {}, // { kategori_id: [fitur_id] }
});
+const kategoriFiturs = ref([]); // 🆕 simpan kategori fitur
const previewImages = ref([]);
const loading = ref(false);
const success = ref(false);
@@ -206,11 +240,20 @@ const error = ref(false);
onMounted(async () => {
if (route.query.template_id) {
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.nama_template = template.nama_template;
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) {
console.error("Gagal ambil template", err);
}
@@ -222,12 +265,10 @@ const handleFileUpload = (event) => {
const newFiles = Array.from(event.target.files);
const combinedFiles = [...form.value.galeri, ...newFiles];
- // Batasi total file menjadi 5
form.value.galeri = combinedFiles.slice(0, 5);
- // Buat ulang array preview berdasarkan data file yang sudah final
- previewImages.value = [];
- form.value.galeri.forEach(file => {
+ previewImages.value = [];
+ form.value.galeri.forEach((file) => {
const reader = new FileReader();
reader.onload = (e) => {
previewImages.value.push(e.target.result);
@@ -235,11 +276,10 @@ const handleFileUpload = (event) => {
reader.readAsDataURL(file);
});
- // Reset input agar bisa memilih file yang sama lagi
event.target.value = null;
};
-// FUNGSI UNTUK MENGHAPUS GAMBAR (SEKARANG DI LUAR)
+// FUNGSI UNTUK MENGHAPUS GAMBAR
const removeImage = (index) => {
form.value.galeri.splice(index, 1);
previewImages.value.splice(index, 1);
@@ -252,15 +292,27 @@ const submitForm = async () => {
try {
const body = new FormData();
+
+ // field umum
for (const key in form.value) {
- if (key === "galeri") {
- form.value.galeri.forEach((file) => body.append("galeri[]", file));
- } else if (form.value[key] !== null && form.value[key] !== undefined) {
+ if (key === "galeri" || key === "selectedFiturs") continue;
+ if (form.value[key] !== null && form.value[key] !== undefined) {
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", {
method: "POST",
body,
@@ -268,10 +320,7 @@ const submitForm = async () => {
success.value = true;
-
const adminNumber = "62895602603247";
-
- // ✅ Susun pesan otomatis
const message = `
Halo Admin, ada pemesanan undangan pernikahan baru 🎉
@@ -293,13 +342,9 @@ Harga: ${form.value.harga}
Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
`;
- // ✅ Redirect ke WhatsApp
- const waUrl = `https://wa.me/${adminNumber}?text=${encodeURIComponent(message)}`;
- window.location.href = waUrl;
-
-
- // Optional: Reset form after success
- // Object.keys(form.value).forEach(key => form.value[key] = '');
+ window.location.href = `https://wa.me/${adminNumber}?text=${encodeURIComponent(
+ message
+ )}`;
} catch (err) {
console.error(err);
error.value = true;
@@ -307,4 +352,4 @@ Tanggal Pemesanan: ${form.value.tanggal_pemesanan}
loading.value = false;
}
};
-
\ No newline at end of file
+
diff --git a/proyek-frontend/app/components/landing-page/footer.vue b/proyek-frontend/app/components/landing-page/footer.vue
index 475e516..b9a1d0c 100644
--- a/proyek-frontend/app/components/landing-page/footer.vue
+++ b/proyek-frontend/app/components/landing-page/footer.vue
@@ -8,7 +8,7 @@
Layanan
@@ -19,19 +19,42 @@