This commit is contained in:
Haqeem Solehan 2024-09-04 13:37:01 +08:00
parent 4d31939b0f
commit e7cd3fd367
3 changed files with 713 additions and 210 deletions

View File

@ -1,17 +1,17 @@
<template>
<div>
<div class="space-y-6">
<!-- CARD: Status Semakan & Status Penerimaan -->
<rs-card class="mt-4 p-4">
<div class="flex justify-between">
<h3>Status Semakan</h3>
<rs-card class="p-6">
<div class="flex justify-between items-center">
<h3 class="text-lg font-semibold">Status Semakan</h3>
<rs-badge
:variant="statusSemakan === 'Selesai' ? 'success' : 'warning'"
>
{{ statusSemakan }}
</rs-badge>
</div>
<div class="flex justify-between mt-2">
<h3>Status Penerimaan</h3>
<div class="flex justify-between items-center mt-4">
<h3 class="text-lg font-semibold">Status Penerimaan</h3>
<rs-badge
:variant="statusPenerimaan === 'Diterima' ? 'success' : 'danger'"
>
@ -21,27 +21,39 @@
</rs-card>
<!-- LIST: Pegawai Forensic Yang Terlibat -->
<rs-card class="mt-4 p-4">
<div class="flex justify-between items-center">
<h3>Pegawai Forensik Yang Terlibat</h3>
<rs-card class="p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold">Pegawai Forensik Yang Terlibat</h3>
<rs-button
v-if="isKetuaBahagian"
@click="addPegawai"
@click="openAddModal"
variant="primary"
size="sm"
>Tambah Pegawai</rs-button
>
Tambah Pegawai
</rs-button>
</div>
<rs-table
v-if="forensicOfficers.length > 0"
:data="forensicOfficers"
:options="{ striped: true, borderless: true }"
:options="{
variant: 'default',
striped: true,
borderless: false,
}"
:options-advanced="{
sortable: true,
responsive: true,
filterable: false,
}"
advanced
>
<template v-slot:header>
<tr>
<th>Pangkat</th>
<th>Nama</th>
<th>No Pegawai</th>
<th v-if="isKetuaBahagian">Tindakan</th>
<th>Tindakan</th>
</tr>
</template>
<template v-slot:pangkat="data">
@ -53,28 +65,46 @@
<template v-slot:noPegawai="data">
{{ data.text }}
</template>
<template v-slot:action="data" v-if="isKetuaBahagian">
<template v-slot:tindakan="data">
<div class="flex gap-2">
<rs-button @click="editPegawai(data.value)" variant="info" size="sm"
>Edit</rs-button
>
<rs-button
@click="deletePegawai(data.value)"
@click="openEditModal(data.value)"
variant="info"
size="sm"
>
<Icon name="ic:baseline-edit" size="1.2rem" />
</rs-button>
<rs-button
@click="confirmDelete(data.value)"
variant="danger"
size="sm"
>Delete</rs-button
>
<Icon name="ic:baseline-delete" size="1.2rem" />
</rs-button>
</div>
</template>
</rs-table>
<div v-else class="text-center p-10">
<p>Tidak ada pegawai forensik yang terlibat.</p>
</div>
</rs-card>
<!-- LIST: Bahan Bukti -->
<rs-card class="mt-4 p-4">
<h3>Bahan Bukti</h3>
<rs-card class="p-6">
<h3 class="text-lg font-semibold mb-4">Bahan Bukti</h3>
<rs-table
:data="evidences"
:options="{ striped: true, borderless: true }"
:options="{
variant: 'default',
striped: true,
borderless: false,
}"
:options-advanced="{
sortable: true,
responsive: true,
filterable: false,
}"
advanced
>
<template v-slot:header>
<tr>
@ -83,7 +113,7 @@
<th>Tag No.</th>
<th>Keadaan</th>
<th>Kuantiti</th>
<th v-if="!isKetuaJabatan">Tindakan</th>
<th>Tindakan</th>
</tr>
</template>
<template v-slot:no="data">
@ -106,29 +136,114 @@
@click="generateReport(data.value)"
variant="primary"
size="sm"
>Jana Laporan</rs-button
>
Jana Laporan
</rs-button>
</template>
</rs-table>
</rs-card>
<!-- Add/Edit Modal -->
<rs-modal v-model="showModal" @close="closeModal">
<template #header>
<h3>
{{ editMode ? "Edit Pegawai Forensik" : "Tambah Pegawai Forensik" }}
</h3>
</template>
<template #body>
<FormKit
type="form"
:actions="false"
@submit="handleSubmit"
:value="pegawaiForm"
>
<FormKit
v-if="!editMode"
type="select"
name="id"
label="Pilih Pegawai"
:options="pegawaiList.map(p => ({ value: p.id, label: `${p.pangkat} ${p.nama} (${p.noPegawai})` }))"
validation="required"
:validation-messages="{
required: 'Sila pilih pegawai',
}"
/>
<template v-else>
<FormKit
type="text"
name="pangkat"
label="Pangkat"
validation="required"
:validation-messages="{
required: 'Pangkat diperlukan',
}"
/>
<FormKit
type="text"
name="nama"
label="Nama"
validation="required"
:validation-messages="{
required: 'Nama diperlukan',
}"
/>
<FormKit
type="text"
name="noPegawai"
label="No Pegawai"
validation="required|unique:noPegawai"
:validation-messages="{
required: 'No Pegawai diperlukan',
unique: 'No Pegawai sudah wujud',
}"
/>
</template>
<div class="flex justify-end gap-2">
<rs-button variant="secondary" @click="closeModal">Tutup</rs-button>
<rs-button variant="primary" btn-type="submit">
Simpan
</rs-button>
</div>
</FormKit>
</template>
<template #footer> </template>
</rs-modal>
</div>
</template>
<script setup>
import { ref } from "vue";
import { useNuxtApp } from "nuxt/app";
import { ref, computed, onMounted } from "vue";
definePageMeta({
layout: "default",
});
const { $swal } = useNuxtApp();
// Status data
const statusSemakan = ref("Selesai"); // Can be dynamic (e.g., "Dalam Proses", "Selesai")
const statusPenerimaan = ref("Diterima"); // Can be dynamic (e.g., "Diterima", "Ditolak")
const statusSemakan = ref("Selesai");
const statusPenerimaan = ref("Diterima");
// Forensic Officers Data (Pangkat, Nama, No Pegawai)
// Forensic Officers Data
const forensicOfficers = ref([
{ pangkat: "Inspektor", nama: "Ali bin Abu", noPegawai: "PG12345" },
{ pangkat: "Sarjan", nama: "Siti binti Ahmad", noPegawai: "PG54321" },
{
id: 1,
pangkat: "Inspektor",
nama: "Ali bin Abu",
noPegawai: "PG12345",
tindakan: 1,
},
{
id: 2,
pangkat: "Sarjan",
nama: "Siti binti Ahmad",
noPegawai: "PG54321",
tindakan: 2,
},
]);
// Evidence Data (No, Jenis Barang, Tag No, Keadaan, Kuantiti)
// Evidence Data
const evidences = ref([
{
no: 1,
@ -136,6 +251,7 @@ const evidences = ref([
tagNo: "TAG001",
keadaan: "Baik",
kuantiti: 3,
tindakan: 1,
},
{
no: 2,
@ -143,27 +259,133 @@ const evidences = ref([
tagNo: "TAG002",
keadaan: "Rosak",
kuantiti: 5,
tindakan: 2,
},
]);
// User Roles
const isKetuaBahagian = ref(true); // Simulate role check
const isKetuaJabatan = ref(false); // Simulate role check
const isKetuaBahagian = ref(true);
const isKetuaJabatan = ref(false);
// Modal Controls
const showModal = ref(false);
const editMode = ref(false);
const pegawaiForm = ref({ id: "", pangkat: "", nama: "", noPegawai: "" });
// Sample pegawai listing (simulating API response)
const pegawaiList = ref([]);
// Fetch pegawai list (simulated API call)
const fetchPegawaiList = () => {
// In a real scenario, this would be an API call
pegawaiList.value = [
{ id: 'PG001', nama: 'Ahmad bin Ali', pangkat: 'Inspektor', noPegawai: 'PG12345' },
{ id: 'PG002', nama: 'Siti binti Omar', pangkat: 'Sarjan', noPegawai: 'PG67890' },
{ id: 'PG003', nama: 'Muthu a/l Rajan', pangkat: 'Koperal', noPegawai: 'PG24680' },
];
};
onMounted(() => {
fetchPegawaiList();
});
// Computed property for form validation
const isFormValid = computed(() => {
return (
pegawaiForm.value.pangkat &&
pegawaiForm.value.nama &&
pegawaiForm.value.noPegawai
);
});
// Actions
const addPegawai = () => {
console.log("Add Pegawai clicked");
const openAddModal = () => {
editMode.value = false;
pegawaiForm.value = { id: "" }; // Only store the selected pegawai id
showModal.value = true;
};
const editPegawai = (pegawai) => {
console.log("Edit Pegawai:", pegawai);
const openEditModal = (pegawai) => {
editMode.value = true;
pegawaiForm.value = { ...pegawai };
showModal.value = true;
};
const deletePegawai = (pegawai) => {
console.log("Delete Pegawai:", pegawai);
forensicOfficers.value = forensicOfficers.value.filter(
(officer) => officer.noPegawai !== pegawai.noPegawai
const closeModal = () => {
showModal.value = false;
pegawaiForm.value = { id: "", pangkat: "", nama: "", noPegawai: "" };
};
const handleSubmit = () => {
if (editMode.value) {
updatePegawai();
} else {
addNewPegawai();
}
};
const addNewPegawai = () => {
if (pegawaiForm.value.id) {
const selectedPegawai = pegawaiList.value.find(p => p.id === pegawaiForm.value.id);
if (selectedPegawai) {
const newPegawai = { ...selectedPegawai, tindakan: uuidv4() };
forensicOfficers.value.push(newPegawai);
$swal.fire("Berjaya", "Pegawai baru telah ditambah", "success");
closeModal();
} else {
$swal.fire("Ralat", "Pegawai tidak dijumpai", "error");
}
} else {
$swal.fire("Ralat", "Sila pilih pegawai", "error");
}
};
const updatePegawai = () => {
if (isFormValid.value) {
const index = forensicOfficers.value.findIndex(
(officer) => officer.id === pegawaiForm.value.id
);
if (index !== -1) {
forensicOfficers.value[index] = { ...pegawaiForm.value };
$swal.fire("Berjaya", "Maklumat pegawai telah dikemaskini", "success");
closeModal();
} else {
$swal.fire("Ralat", "Pegawai tidak dijumpai", "error");
}
} else {
$swal.fire("Ralat", "Sila isi semua maklumat yang diperlukan", "error");
}
};
const confirmDelete = (pegawai) => {
$swal
.fire({
title: "Anda pasti?",
text: "Pegawai ini akan dipadamkan.",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#d33",
cancelButtonColor: "#3085d6",
confirmButtonText: "Ya, padam",
cancelButtonText: "Batal",
})
.then((result) => {
if (result.isConfirmed) {
deletePegawai(pegawai.id);
}
});
};
const deletePegawai = (id) => {
const index = forensicOfficers.value.findIndex(
(officer) => officer.id === id
);
if (index !== -1) {
forensicOfficers.value.splice(index, 1);
$swal.fire("Dihapuskan!", "Pegawai telah dipadam.", "success");
} else {
$swal.fire("Ralat", "Pegawai tidak dijumpai", "error");
}
};
const generateReport = (bahanBukti) => {
@ -171,6 +393,4 @@ const generateReport = (bahanBukti) => {
};
</script>
<style lang="scss" scoped>
/* Style customizations for table or buttons */
</style>
<style lang="scss" scoped></style>

View File

@ -80,55 +80,53 @@
validation="required|number"
/>
<!-- Jenis Barang Input -->
<FormKit
type="text"
label="Jenis Barang"
v-model="jenisBarang"
validation="required"
/>
<!-- Tanda Barang Input -->
<FormKit
type="text"
label="Tanda Barang"
v-model="tandaBarang"
validation="required"
/>
<!-- Keadaan Barang Input -->
<FormKit
type="text"
label="Keadaan Barang"
v-model="keadaanBarang"
validation="required"
/>
<!-- Kuantiti Barang Input -->
<FormKit
type="number"
label="Kuantiti Barang"
v-model="kuantitiBarang"
validation="required|number"
/>
<!-- Jenis Barang Detail Select Input -->
<FormKit
type="select"
label="Jenis Barang"
v-model="jenisBarangDetail"
:options="jenisBarangDetailOptions"
validation="required"
/>
<!-- Jenis Barang Siber Select Input -->
<FormKit
type="select"
label="Jenis Barang Siber"
v-model="jenisBarangSiber"
:options="jenisBarangSiberOptions"
validation="required"
/>
<!-- Barang Section -->
<div class="mb-4">
<h3 class="mb-2">Senarai Barang</h3>
<table
v-if="barangList.length > 0"
class="w-full border-collapse border border-gray-300 mb-2"
>
<thead>
<tr class="bg-gray-100">
<th class="border border-gray-300 p-2">Jenis Barang</th>
<th class="border border-gray-300 p-2">Kuantiti</th>
<th class="border border-gray-300 p-2">Tindakan</th>
</tr>
</thead>
<tbody>
<tr v-for="(barang, index) in barangList" :key="index">
<td class="border border-gray-300 p-2">
{{ barang.jenisBarang }}
</td>
<td class="border border-gray-300 p-2">
{{ barang.kuantitiBarang }}
</td>
<td class="border border-gray-300 p-2">
<rs-button
type="button"
@click="editBarang(index)"
variant="secondary"
class="mr-2"
>
Edit
</rs-button>
<rs-button
type="button"
@click="removeBarang(index)"
variant="danger"
>
Buang
</rs-button>
</td>
</tr>
</tbody>
</table>
<div v-else class="text-gray-500 mb-2">Tiada barang ditambah</div>
<rs-button type="button" @click="openBarangModal" variant="primary">
Tambah Barang
</rs-button>
</div>
<!-- No Kertas Siasatan Input -->
<FormKit
@ -179,14 +177,120 @@
>
<rs-button
type="submit"
@click="submitForm"
btn-type="submit"
:disabled="!isFormValid"
variant="success"
>Hantar</rs-button
>
</div>
</FormKit>
</rs-card>
<!-- Barang Modal -->
<div
v-if="isBarangModalOpen"
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"
>
<div class="bg-white p-6 rounded-lg w-full max-w-2xl">
<h2 class="text-2xl font-bold mb-4">
{{ editingBarangIndex === null ? "Tambah" : "Edit" }} Barang
</h2>
<FormKit
type="form"
:actions="false"
@submit="saveBarangModal"
#default="{ state: formState }"
>
<FormKit
type="text"
name="jenisBarang"
label="Jenis Barang"
v-model="currentBarang.jenisBarang"
validation="required"
:validation-messages="{
required: 'Jenis Barang diperlukan',
}"
/>
<FormKit
type="text"
name="tandaBarang"
label="Tanda Barang"
v-model="currentBarang.tandaBarang"
validation="required"
:validation-messages="{
required: 'Tanda Barang diperlukan',
}"
/>
<FormKit
type="text"
name="keadaanBarang"
label="Keadaan Barang"
v-model="currentBarang.keadaanBarang"
validation="required"
:validation-messages="{
required: 'Keadaan Barang diperlukan',
}"
/>
<FormKit
type="number"
name="kuantitiBarang"
label="Kuantiti Barang"
v-model="currentBarang.kuantitiBarang"
validation="required|number|min:1"
:validation-messages="{
required: 'Kuantiti Barang diperlukan',
number: 'Kuantiti Barang mesti nombor',
min: 'Kuantiti Barang mesti sekurang-kurangnya 1',
}"
/>
<FormKit
type="select"
name="jenisBarangDetail"
label="Jenis Barang Detail"
v-model="currentBarang.jenisBarangDetail"
:options="jenisBarangDetailOptions"
validation="required"
:validation-messages="{
required: 'Jenis Barang Detail diperlukan',
}"
/>
<FormKit
type="select"
name="jenisBarangSiber"
label="Jenis Barang Siber"
v-model="currentBarang.jenisBarangSiber"
:options="jenisBarangSiberOptions"
validation="required"
:validation-messages="{
required: 'Jenis Barang Siber diperlukan',
}"
/>
<div class="flex justify-end gap-2 mt-4">
<rs-button
type="button"
btn-type="reset"
@click="cancelBarangModal"
variant="danger"
>Batal</rs-button
>
<rs-button
type="submit"
btn-type="submit"
variant="success"
:disabled="!formState.valid"
>Simpan</rs-button
>
</div>
</FormKit>
</div>
</div>
</div>
</template>
@ -204,12 +308,7 @@ const pangkatPenghantar = ref("");
const noPegawaiPenghantar = ref("");
const ringkasanKenyataanKes = ref("");
const bilangan = ref(0);
const jenisBarang = ref("");
const tandaBarang = ref("");
const keadaanBarang = ref("");
const kuantitiBarang = ref(0);
const jenisBarangDetail = ref("");
const jenisBarangSiber = ref("");
const barangList = ref([]);
const noKertasSiasatan = ref("");
const noLaporanPolis = ref("");
const tarikhTemujanji = ref("");
@ -218,6 +317,17 @@ const slotMasa = ref("");
// State for single checkbox
const isPenghantarSameAsPemohon = ref(false);
const isBarangModalOpen = ref(false);
const editingBarangIndex = ref(null);
const currentBarang = ref({
jenisBarang: "",
tandaBarang: "",
keadaanBarang: "",
kuantitiBarang: 1,
jenisBarangDetail: "",
jenisBarangSiber: "",
});
const jenisBarangDetailOptions = [
"PASPORT",
"MALPASS",
@ -249,6 +359,42 @@ const navigateBack = () => {
router.back();
};
const openBarangModal = () => {
editingBarangIndex.value = null;
currentBarang.value = {
jenisBarang: "",
tandaBarang: "",
keadaanBarang: "",
kuantitiBarang: 1,
jenisBarangDetail: "",
jenisBarangSiber: "",
};
isBarangModalOpen.value = true;
};
const editBarang = (index) => {
editingBarangIndex.value = index;
currentBarang.value = { ...barangList.value[index] };
isBarangModalOpen.value = true;
};
const removeBarang = (index) => {
barangList.value.splice(index, 1);
};
const cancelBarangModal = () => {
isBarangModalOpen.value = false;
};
const saveBarangModal = () => {
if (editingBarangIndex.value === null) {
barangList.value.push({ ...currentBarang.value });
} else {
barangList.value[editingBarangIndex.value] = { ...currentBarang.value };
}
isBarangModalOpen.value = false;
};
const isFormValid = () => {
const requiredFields = [
namaPemohon,
@ -259,21 +405,25 @@ const isFormValid = () => {
noPegawaiPenghantar,
ringkasanKenyataanKes,
bilangan,
jenisBarang,
tandaBarang,
keadaanBarang,
kuantitiBarang,
jenisBarangDetail,
jenisBarangSiber,
noKertasSiasatan,
noLaporanPolis,
tarikhTemujanji,
slotMasa,
];
return requiredFields.every(
const areRequiredFieldsFilled = requiredFields.every(
(field) => field.value !== "" && field.value !== 0
);
const areBarangFieldsValid = barangList.value.every((barang) =>
Object.values(barang).every((value) => value !== "" && value !== 0)
);
return (
areRequiredFieldsFilled &&
areBarangFieldsValid &&
barangList.value.length > 0
);
};
const simpan = () => {
@ -298,12 +448,7 @@ const simpan = () => {
noPegawaiPenghantar: noPegawaiPenghantar.value,
ringkasanKenyataanKes: ringkasanKenyataanKes.value,
bilangan: bilangan.value,
jenisBarang: jenisBarang.value,
tandaBarang: tandaBarang.value,
keadaanBarang: keadaanBarang.value,
kuantitiBarang: kuantitiBarang.value,
jenisBarangDetail: jenisBarangDetail.value,
jenisBarangSiber: jenisBarangSiber.value,
barangList: barangList.value,
noKertasSiasatan: noKertasSiasatan.value,
noLaporanPolis: noLaporanPolis.value,
tarikhTemujanji: tarikhTemujanji.value,
@ -344,12 +489,7 @@ const submitForm = () => {
noPegawaiPenghantar: noPegawaiPenghantar.value,
ringkasanKenyataanKes: ringkasanKenyataanKes.value,
bilangan: bilangan.value,
jenisBarang: jenisBarang.value,
tandaBarang: tandaBarang.value,
keadaanBarang: keadaanBarang.value,
kuantitiBarang: kuantitiBarang.value,
jenisBarangDetail: jenisBarangDetail.value,
jenisBarangSiber: jenisBarangSiber.value,
barangList: barangList.value,
noKertasSiasatan: noKertasSiasatan.value,
noLaporanPolis: noLaporanPolis.value,
tarikhTemujanji: tarikhTemujanji.value,
@ -367,7 +507,7 @@ const submitForm = () => {
// Show error message
$swal.fire({
title: "Ralat!",
text: "Sila isi semua medan yang diperlukan.",
text: "Sila isi semua medan yang diperlukan dan tambah sekurang-kurangnya satu barang.",
icon: "error",
confirmButtonText: "OK",
});

View File

@ -1,7 +1,7 @@
<template>
<div>
<div class="flex justify-between items-center">
<h1>Kemaskini Permohonan</h1>
<h1>Permohonan Baru</h1>
</div>
<rs-card class="mt-4 p-4">
@ -80,55 +80,53 @@
validation="required|number"
/>
<!-- Jenis Barang Input -->
<FormKit
type="text"
label="Jenis Barang"
v-model="jenisBarang"
validation="required"
/>
<!-- Tanda Barang Input -->
<FormKit
type="text"
label="Tanda Barang"
v-model="tandaBarang"
validation="required"
/>
<!-- Keadaan Barang Input -->
<FormKit
type="text"
label="Keadaan Barang"
v-model="keadaanBarang"
validation="required"
/>
<!-- Kuantiti Barang Input -->
<FormKit
type="number"
label="Kuantiti Barang"
v-model="kuantitiBarang"
validation="required|number"
/>
<!-- Jenis Barang Detail Select Input -->
<FormKit
type="select"
label="Jenis Barang"
v-model="jenisBarangDetail"
:options="jenisBarangDetailOptions"
validation="required"
/>
<!-- Jenis Barang Siber Select Input -->
<FormKit
type="select"
label="Jenis Barang Siber"
v-model="jenisBarangSiber"
:options="jenisBarangSiberOptions"
validation="required"
/>
<!-- Barang Section -->
<div class="mb-4">
<h3 class="mb-2">Senarai Barang</h3>
<table
v-if="barangList.length > 0"
class="w-full border-collapse border border-gray-300 mb-2"
>
<thead>
<tr class="bg-gray-100">
<th class="border border-gray-300 p-2">Jenis Barang</th>
<th class="border border-gray-300 p-2">Kuantiti</th>
<th class="border border-gray-300 p-2">Tindakan</th>
</tr>
</thead>
<tbody>
<tr v-for="(barang, index) in barangList" :key="index">
<td class="border border-gray-300 p-2">
{{ barang.jenisBarang }}
</td>
<td class="border border-gray-300 p-2">
{{ barang.kuantitiBarang }}
</td>
<td class="border border-gray-300 p-2">
<rs-button
type="button"
@click="editBarang(index)"
variant="secondary"
class="mr-2"
>
Edit
</rs-button>
<rs-button
type="button"
@click="removeBarang(index)"
variant="danger"
>
Buang
</rs-button>
</td>
</tr>
</tbody>
</table>
<div v-else class="text-gray-500 mb-2">Tiada barang ditambah</div>
<rs-button type="button" @click="openBarangModal" variant="primary">
Tambah Barang
</rs-button>
</div>
<!-- No Kertas Siasatan Input -->
<FormKit
@ -182,6 +180,112 @@
</div>
</FormKit>
</rs-card>
<!-- Barang Modal -->
<div
v-if="isBarangModalOpen"
class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center"
>
<div class="bg-white p-6 rounded-lg w-full max-w-2xl">
<h2 class="text-2xl font-bold mb-4">
{{ editingBarangIndex === null ? "Tambah" : "Edit" }} Barang
</h2>
<FormKit
type="form"
:actions="false"
@submit="saveBarangModal"
#default="{ state: formState }"
>
<FormKit
type="text"
name="jenisBarang"
label="Jenis Barang"
v-model="currentBarang.jenisBarang"
validation="required"
:validation-messages="{
required: 'Jenis Barang diperlukan',
}"
/>
<FormKit
type="text"
name="tandaBarang"
label="Tanda Barang"
v-model="currentBarang.tandaBarang"
validation="required"
:validation-messages="{
required: 'Tanda Barang diperlukan',
}"
/>
<FormKit
type="text"
name="keadaanBarang"
label="Keadaan Barang"
v-model="currentBarang.keadaanBarang"
validation="required"
:validation-messages="{
required: 'Keadaan Barang diperlukan',
}"
/>
<FormKit
type="number"
name="kuantitiBarang"
label="Kuantiti Barang"
v-model="currentBarang.kuantitiBarang"
validation="required|number|min:1"
:validation-messages="{
required: 'Kuantiti Barang diperlukan',
number: 'Kuantiti Barang mesti nombor',
min: 'Kuantiti Barang mesti sekurang-kurangnya 1',
}"
/>
<FormKit
type="select"
name="jenisBarangDetail"
label="Jenis Barang Detail"
v-model="currentBarang.jenisBarangDetail"
:options="jenisBarangDetailOptions"
validation="required"
:validation-messages="{
required: 'Jenis Barang Detail diperlukan',
}"
/>
<FormKit
type="select"
name="jenisBarangSiber"
label="Jenis Barang Siber"
v-model="currentBarang.jenisBarangSiber"
:options="jenisBarangSiberOptions"
validation="required"
:validation-messages="{
required: 'Jenis Barang Siber diperlukan',
}"
/>
<div class="flex justify-end gap-2 mt-4">
<rs-button
type="button"
btn-type="reset"
@click="cancelBarangModal"
variant="danger"
>Batal</rs-button
>
<rs-button
type="submit"
btn-type="submit"
variant="success"
:disabled="!formState.valid"
>Simpan</rs-button
>
</div>
</FormKit>
</div>
</div>
</div>
</template>
@ -203,12 +307,7 @@ const pangkatPenghantar = ref("");
const noPegawaiPenghantar = ref("");
const ringkasanKenyataanKes = ref("");
const bilangan = ref(0);
const jenisBarang = ref("");
const tandaBarang = ref("");
const keadaanBarang = ref("");
const kuantitiBarang = ref(0);
const jenisBarangDetail = ref("");
const jenisBarangSiber = ref("");
const barangList = ref([]);
const noKertasSiasatan = ref("");
const noLaporanPolis = ref("");
const tarikhTemujanji = ref("");
@ -229,6 +328,18 @@ const jenisBarangDetailOptions = [
const jenisBarangSiberOptions = ["SIBER", "TULISAN TANGAN"];
// Barang modal state
const isBarangModalOpen = ref(false);
const editingBarangIndex = ref(null);
const currentBarang = ref({
jenisBarang: "",
tandaBarang: "",
keadaanBarang: "",
kuantitiBarang: 1,
jenisBarangDetail: "",
jenisBarangSiber: "",
});
// Watcher to update Penghantar fields when the checkbox is checked
watch(isPenghantarSameAsPemohon, (newValue) => {
if (newValue) {
@ -248,6 +359,43 @@ const navigateBack = () => {
router.back();
};
// Barang modal functions
const openBarangModal = () => {
editingBarangIndex.value = null;
currentBarang.value = {
jenisBarang: "",
tandaBarang: "",
keadaanBarang: "",
kuantitiBarang: 1,
jenisBarangDetail: "",
jenisBarangSiber: "",
};
isBarangModalOpen.value = true;
};
const editBarang = (index) => {
editingBarangIndex.value = index;
currentBarang.value = { ...barangList.value[index] };
isBarangModalOpen.value = true;
};
const removeBarang = (index) => {
barangList.value.splice(index, 1);
};
const cancelBarangModal = () => {
isBarangModalOpen.value = false;
};
const saveBarangModal = () => {
if (editingBarangIndex.value === null) {
barangList.value.push({ ...currentBarang.value });
} else {
barangList.value[editingBarangIndex.value] = { ...currentBarang.value };
}
isBarangModalOpen.value = false;
};
// Validate the form
const isFormValid = () => {
const requiredFields = [
@ -259,21 +407,25 @@ const isFormValid = () => {
noPegawaiPenghantar,
ringkasanKenyataanKes,
bilangan,
jenisBarang,
tandaBarang,
keadaanBarang,
kuantitiBarang,
jenisBarangDetail,
jenisBarangSiber,
noKertasSiasatan,
noLaporanPolis,
tarikhTemujanji,
slotMasa,
];
return requiredFields.every(
const areRequiredFieldsFilled = requiredFields.every(
(field) => field.value !== "" && field.value !== 0
);
const areBarangFieldsValid = barangList.value.every((barang) =>
Object.values(barang).every((value) => value !== "" && value !== 0)
);
return (
areRequiredFieldsFilled &&
areBarangFieldsValid &&
barangList.value.length > 0
);
};
const simpan = () => {
@ -298,12 +450,7 @@ const simpan = () => {
noPegawaiPenghantar: noPegawaiPenghantar.value,
ringkasanKenyataanKes: ringkasanKenyataanKes.value,
bilangan: bilangan.value,
jenisBarang: jenisBarang.value,
tandaBarang: tandaBarang.value,
keadaanBarang: keadaanBarang.value,
kuantitiBarang: kuantitiBarang.value,
jenisBarangDetail: jenisBarangDetail.value,
jenisBarangSiber: jenisBarangSiber.value,
barangList: barangList.value,
noKertasSiasatan: noKertasSiasatan.value,
noLaporanPolis: noLaporanPolis.value,
tarikhTemujanji: tarikhTemujanji.value,
@ -344,12 +491,7 @@ const submitForm = () => {
noPegawaiPenghantar: noPegawaiPenghantar.value,
ringkasanKenyataanKes: ringkasanKenyataanKes.value,
bilangan: bilangan.value,
jenisBarang: jenisBarang.value,
tandaBarang: tandaBarang.value,
keadaanBarang: keadaanBarang.value,
kuantitiBarang: kuantitiBarang.value,
jenisBarangDetail: jenisBarangDetail.value,
jenisBarangSiber: jenisBarangSiber.value,
barangList: barangList.value,
noKertasSiasatan: noKertasSiasatan.value,
noLaporanPolis: noLaporanPolis.value,
tarikhTemujanji: tarikhTemujanji.value,
@ -367,7 +509,7 @@ const submitForm = () => {
// Show error message
$swal.fire({
title: "Ralat!",
text: "Sila isi semua medan yang diperlukan.",
text: "Sila isi semua medan yang diperlukan dan tambah sekurang-kurangnya satu barang.",
icon: "error",
confirmButtonText: "OK",
});
@ -398,6 +540,15 @@ function generateSampleData(noSiri) {
];
const keadaanBarangOptions = ["Baik", "Sederhana", "Rosak"];
const generateBarang = () => ({
jenisBarang: randomChoice(jenisBarangOptions),
tandaBarang: `TB-${randomNumber(1000, 9999)}`,
keadaanBarang: randomChoice(keadaanBarangOptions),
kuantitiBarang: randomNumber(1, 10),
jenisBarangDetail: randomChoice(jenisBarangDetailOptions),
jenisBarangSiber: randomChoice(jenisBarangSiberOptions),
});
return {
noSiri: noSiri,
namaPemohon: randomChoice(namaPemohon),
@ -405,16 +556,12 @@ function generateSampleData(noSiri) {
noPegawaiPemohon: `PG${randomNumber(10000, 99999)}`,
namaPenghantar: randomChoice(namaPemohon),
pangkatPenghantar: randomChoice(pangkat),
noPegawaiPenghantar: `PG${randomNumber(10000, 99999)}`,
ringkasanKenyataanKes: `Kes ${noSiri}: Penemuan barang bukti dalam serbuan di lokasi ${randomChoice(
["A", "B", "C", "D"]
)}`,
bilangan: randomNumber(1, 10),
jenisBarang: randomChoice(jenisBarangOptions),
tandaBarang: `TB-${randomNumber(1000, 9999)}`,
keadaanBarang: randomChoice(keadaanBarangOptions),
kuantitiBarang: randomNumber(1, 100),
jenisBarangDetail: randomChoice(jenisBarangDetailOptions),
jenisBarangSiber: randomChoice(jenisBarangSiberOptions),
bilangan: randomNumber(1, 5),
barangList: Array.from({ length: randomNumber(1, 3) }, generateBarang),
noKertasSiasatan: `KS-${randomNumber(10000, 99999)}`,
noLaporanPolis: `RPT-${randomNumber(100000, 999999)}`,
tarikhTemujanji: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000)
@ -432,14 +579,10 @@ onMounted(() => {
noPegawaiPemohon.value = sampleData.noPegawaiPemohon;
namaPenghantar.value = sampleData.namaPenghantar;
pangkatPenghantar.value = sampleData.pangkatPenghantar;
noPegawaiPenghantar.value = sampleData.noPegawaiPenghantar;
ringkasanKenyataanKes.value = sampleData.ringkasanKenyataanKes;
bilangan.value = sampleData.bilangan;
jenisBarang.value = sampleData.jenisBarang;
tandaBarang.value = sampleData.tandaBarang;
keadaanBarang.value = sampleData.keadaanBarang;
kuantitiBarang.value = sampleData.kuantitiBarang;
jenisBarangDetail.value = sampleData.jenisBarangDetail;
jenisBarangSiber.value = sampleData.jenisBarangSiber;
barangList.value = sampleData.barangList;
noKertasSiasatan.value = sampleData.noKertasSiasatan;
noLaporanPolis.value = sampleData.noLaporanPolis;
tarikhTemujanji.value = sampleData.tarikhTemujanji;