Done for now

This commit is contained in:
Md Afiq Iskandar 2024-09-05 10:54:53 +08:00
parent 7b1e5bbc13
commit efdd28afbd
28 changed files with 1438 additions and 655 deletions

View File

@ -1,4 +1,34 @@
export default [
{
header: "Forensik",
description: "",
child: [
{
title: "FOR-01",
icon: "ph:number-circle-one-fill",
child: [
{
title: "Permohonan Temujanji",
path: "/permohonan-temujanji/senarai",
child: [],
meta: {},
},
{
title: "Kaunter Semakan ",
path: "/kemaskini-daftar/senarai",
child: [],
meta: {},
},
// {
// title: "Kemaskini Daftar",
// path: "/kemaskini-daftar/senarai",
// child: [],
// meta: {},
// },
],
},
],
},
{
header: "Utama",
description: "",
@ -122,36 +152,7 @@ export default [
],
meta: {},
},
{
header: "Prototaip Forensik",
description: "",
child: [
{
title: "FOR-01",
icon: "ph:number-circle-one-fill",
child: [
{
title: "Permohonan Temujanji",
path: "/permohonan-temujanji/senarai",
child: [],
meta: {},
},
{
title: "Kaunter Semakan ",
path: "/kemaskini-daftar/senarai",
child: [],
meta: {},
},
// {
// title: "Kemaskini Daftar",
// path: "/kemaskini-daftar/senarai",
// child: [],
// meta: {},
// },
],
},
],
},
{
header: "Pengurusan",
description: "",

View File

@ -159,7 +159,7 @@ const showTooltip = (codeId, message) => {
}"
:options-advanced="{
sortable: true,
responsive: true,
filterable: false,
}"
advanced
@ -217,7 +217,7 @@ const showTooltip = (codeId, message) => {
}"
:options-advanced="{
sortable: true,
responsive: true,
filterable: false,
}"
advanced

View File

@ -46,7 +46,6 @@
label="Ringkasan Kenyataan Kes"
v-model="ringkasanKenyataanKes"
validation="required"
disabled
/>
<FormKit
type="number"
@ -55,72 +54,56 @@
validation="required|number"
disabled
/>
<FormKit
type="text"
label="Jenis Barang"
v-model="jenisBarang"
validation="required"
disabled
/>
<FormKit
type="text"
label="Tanda Barang"
v-model="tandaBarang"
validation="required"
disabled
/>
<FormKit
type="text"
label="Keadaan Barang"
v-model="keadaanBarang"
validation="required"
disabled
/>
<FormKit
type="number"
label="Kuantiti Barang"
v-model="kuantitiBarang"
validation="required|number"
disabled
/>
<FormKit
type="select"
label="Jenis Barang"
v-model="jenisBarangDetail"
:options="jenisBarangDetailOptions"
validation="required"
disabled
/>
<FormKit
type="select"
label="Jenis Barang Siber"
v-model="jenisBarangSiber"
:options="jenisBarangSiberOptions"
validation="required"
disabled
/>
<!-- 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>
</tr>
</thead>
<tbody>
<tr v-for="(barang, index) in barangList" :key="index">
<td class="border border-gray-300 p-2">
{{
barang.jenisBarangDetailLabel
? barang.jenisBarangDetailLabel
: barang.jenisBarangDetail
}}
</td>
<td class="border border-gray-300 p-2">
{{ barang.kuantitiBarang }}
</td>
</tr>
</tbody>
</table>
<div v-else class="text-gray-500 mb-2">Tiada barang ditambah</div>
</div>
<FormKit
type="text"
label="No Kertas Siasatan"
v-model="noKertasSiasatan"
disabled
/>
<FormKit
type="text"
label="No Laporan Polis"
v-model="noLaporanPolis"
disabled
/>
<div class="flex justify-end gap-2 mt-4">
<rs-button type="button" @click="navi" variant="danger"
<rs-button type="button" @click="navigateBack" variant="danger"
>Kembali</rs-button
>
<rs-button type="button" @click="confirmBatal" variant="primary"
<!-- <rs-button type="button" @click="confirmBatal" variant="primary"
>Tolak</rs-button
>
<rs-button type="submit" @click="confirmSah" variant="success"
>Sah</rs-button
>
> -->
<rs-button btn-type="submit" variant="success">Hantar</rs-button>
</div>
</FormKit>
</rs-card>
@ -128,11 +111,9 @@
</template>
<script setup>
import { ref, onMounted } from "vue";
import { useRouter, useRoute } from "vue-router";
const router = useRouter();
const route = useRoute();
const { $swal } = useNuxtApp();
const noSiri = ref(route.params.noSiri);
@ -143,26 +124,11 @@ const namaPenghantar = ref("");
const pangkatPenghantar = 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 jenisBarangDetailOptions = [
"PASPORT",
"MALPASS",
"CAP KESELAMATAN",
"CAP JARI",
"PEMERIKSAAN",
"I-KAD",
"LAIN-LAIN",
];
const jenisBarangSiberOptions = ["SIBER", "TULISAN TANGAN"];
const jenisBarangDetailOptions = ref([]);
const navigateBack = () => {
router.back();
@ -177,12 +143,6 @@ const isFormValid = () => {
pangkatPenghantar,
ringkasanKenyataanKes,
bilangan,
jenisBarang,
tandaBarang,
keadaanBarang,
kuantitiBarang,
jenisBarangDetail,
jenisBarangSiber,
noKertasSiasatan,
noLaporanPolis,
];
@ -192,35 +152,38 @@ const isFormValid = () => {
);
};
const simpan = () => {
const submitForm = async () => {
if (isFormValid()) {
console.log("Form data saved");
} else {
console.error("Please fill in all required fields.");
}
};
try {
const response = await $fetch(`/api/kaunter-permohonan/${noSiri.value}`, {
method: "PUT",
body: {
ringkasanKenyataanKes: ringkasanKenyataanKes.value,
noKertasSiasatan: noKertasSiasatan.value,
noLaporanPolis: noLaporanPolis.value,
},
});
const submitForm = () => {
if (isFormValid()) {
console.log({
namaPemohon: namaPemohon.value,
pangkatPemohon: pangkatPemohon.value,
noPegawaiPemohon: noPegawaiPemohon.value,
namaPenghantar: namaPenghantar.value,
pangkatPenghantar: pangkatPenghantar.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,
noKertasSiasatan: noKertasSiasatan.value,
noLaporanPolis: noLaporanPolis.value,
});
if (response.statusCode === 200) {
await $swal.fire({
title: "Berjaya!",
text: "Permohonan telah berjaya dikemaskini.",
icon: "success",
confirmButtonText: "OK",
});
navigateTo(`/kemaskini-daftar/kemaskini/sah/${noSiri.value}`);
router.push("/kemaskini-daftar/senarai");
} else {
throw new Error(response.message);
}
} catch (error) {
$swal.fire({
title: "Ralat!",
text: error.message || "Gagal mengemaskini permohonan. Sila cuba lagi.",
icon: "error",
confirmButtonText: "OK",
});
}
} else {
$swal.fire({
title: "Ralat!",
@ -260,75 +223,64 @@ const confirmSah = () => {
})
.then((result) => {
if (result.isConfirmed) {
submitForm();
}
});
};
function generateSampleData(noSiri) {
const randomNumber = (min, max) =>
Math.floor(Math.random() * (max - min + 1) + min);
const randomChoice = (arr) => arr[Math.floor(Math.random() * arr.length)];
const fetchLookupData = async (type) => {
try {
const response = await $fetch(`/api/lookup?type=${type}`);
if (response.statusCode === 200) {
return response.data;
}
} catch (error) {
console.error(`Error fetching ${type} lookup data:`, error);
return [];
}
};
const namaPemohon = [
"Ali bin Abu",
"Siti binti Ahmad",
"Muthu a/l Rajan",
"Lim Wei Ling",
];
const pangkat = ["Inspektor", "Sarjan", "Koperal", "Konstabel"];
const jenisBarangOptions = [
"Dokumen",
"Peralatan Elektronik",
"Senjata",
"Dadah",
"Barang Kemas",
];
const keadaanBarangOptions = ["Baik", "Sederhana", "Rosak"];
const fetchExistingData = async (noSiri) => {
try {
const response = await $fetch(`/api/permohonan/${noSiri}`);
if (response.statusCode === 200) {
return response.data;
}
} catch (error) {
console.error("Error fetching existing data:", error);
$swal.fire({
title: "Ralat!",
text: "Gagal mendapatkan data permohonan.",
icon: "error",
confirmButtonText: "OK",
});
}
};
return {
noSiri: noSiri,
namaPemohon: randomChoice(namaPemohon),
pangkatPemohon: randomChoice(pangkat),
noPegawaiPemohon: `PG${randomNumber(10000, 99999)}`,
namaPenghantar: randomChoice(namaPemohon),
pangkatPenghantar: randomChoice(pangkat),
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),
noKertasSiasatan: `KS-${randomNumber(10000, 99999)}`,
noLaporanPolis: `RPT-${randomNumber(100000, 999999)}`,
};
}
onMounted(async () => {
const existingData = await fetchExistingData(noSiri.value);
onMounted(() => {
const sampleData = generateSampleData(noSiri.value);
if (existingData) {
namaPemohon.value = existingData.namaPemohon;
pangkatPemohon.value = existingData.pangkatPemohon;
noPegawaiPemohon.value = existingData.noPegawaiPemohon;
namaPenghantar.value = existingData.namaPenghantar;
pangkatPenghantar.value = existingData.pangkatPenghantar;
ringkasanKenyataanKes.value = existingData.ringkasanKenyataanKes;
bilangan.value = existingData.bilangan;
barangList.value = existingData.barangList;
noKertasSiasatan.value = existingData.noKertasSiasatan;
noLaporanPolis.value = existingData.noLaporanPolis;
}
namaPemohon.value = sampleData.namaPemohon;
pangkatPemohon.value = sampleData.pangkatPemohon;
noPegawaiPemohon.value = sampleData.noPegawaiPemohon;
namaPenghantar.value = sampleData.namaPenghantar;
pangkatPenghantar.value = sampleData.pangkatPenghantar;
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;
noKertasSiasatan.value = sampleData.noKertasSiasatan;
noLaporanPolis.value = sampleData.noLaporanPolis;
jenisBarangDetailOptions.value = await fetchLookupData("jenis_barang");
});
const { $swal } = useNuxtApp();
const getJenisBarangLabel = (value) => {
const option = jenisBarangDetailOptions.value.find(
(opt) => opt.__original === value
);
return option ? option.label : value;
};
</script>
<style lang="scss" scoped>

View File

@ -62,7 +62,7 @@
<div class="space-y-4">
<h2 class="text-xl font-semibold">Butiran Pegawai</h2>
<div
v-for="role in ['PENYIASAT', 'PENGHANTAR', 'PENERIMA', 'PEMERIKSA']"
v-for="role in ['PENYIASAT', 'PENGHANTAR', 'PEMERIKSA', 'PENERIMA']"
:key="role"
class="grid grid-cols-1 md:grid-cols-3 gap-4"
>
@ -71,8 +71,6 @@
:name="`pegawai.${role}.nama`"
:label="`${role} - Nama`"
v-model="generatedData.pegawai[role].nama"
validation="required"
:validation-messages="{ required: 'Nama diperlukan' }"
disabled
/>
<FormKit
@ -80,8 +78,6 @@
:name="`pegawai.${role}.pangkat`"
:label="`${role} - Pangkat`"
v-model="generatedData.pegawai[role].pangkat"
validation="required"
:validation-messages="{ required: 'Pangkat diperlukan' }"
disabled
/>
<FormKit
@ -89,8 +85,6 @@
:name="`pegawai.${role}.noPegawai`"
:label="`${role} - No Pegawai`"
v-model="generatedData.pegawai[role].noPegawai"
validation="required"
:validation-messages="{ required: 'No Pegawai diperlukan' }"
disabled
/>
</div>
@ -99,6 +93,7 @@
<!-- Peralatan and Langkah2 -->
<div class="space-y-4">
<FormKit
v-model="generatedData.peralatan"
type="textarea"
name="peralatan"
label="Peralatan"
@ -107,6 +102,7 @@
:rows="3"
/>
<FormKit
v-model="generatedData.langkah2"
type="textarea"
name="langkah2"
label="Langkah-langkah"
@ -118,10 +114,11 @@
<!-- Dapatan -->
<FormKit
v-model="generatedData.dapatan.value"
type="radio"
name="dapatan"
label="Dapatan"
:options="['Tulen', 'Palsu', 'Tidak dapat dikenalpasti']"
:options="dapatanOptions"
validation="required"
:validation-messages="{ required: 'Dapatan diperlukan' }"
/>
@ -130,7 +127,7 @@
<div>
<h2 class="text-xl font-semibold mb-2">Document Tambahan</h2>
<FormKit type="list" name="documentTambahan" :value="[]">
<FormKit type="group" :repeatable="true" :key="index">
<FormKit type="group" :repeatable="true">
<div class="flex items-center space-x-2">
<FormKit
type="text"
@ -152,7 +149,7 @@
</div>
<div class="flex justify-end gap-2">
<rs-button btn-type="reset" @click="previousPage()"
<rs-button variant="danger" btn-type="reset" @click="previousPage()"
>Kembali</rs-button
>
<rs-button type="submit" btn-type="submit">Hantar Laporan</rs-button>
@ -167,8 +164,9 @@ import { useRoute } from "vue-router";
import { ref, onMounted } from "vue";
import { jsPDF } from "jspdf";
const { $swal } = useNuxtApp();
const route = useRoute();
const bahanBukti = route.params.bahanBukti;
const reportID = route.params.reportID;
const generatedData = ref({
kesId: "",
@ -178,89 +176,119 @@ const generatedData = ref({
pegawai: {
PENYIASAT: { nama: "", pangkat: "", noPegawai: "" },
PENGHANTAR: { nama: "", pangkat: "", noPegawai: "" },
PENERIMA: { nama: "", pangkat: "", noPegawai: "" },
PEMERIKSA: { nama: "", pangkat: "", noPegawai: "" },
PENERIMA: { nama: "", pangkat: "", noPegawai: "" },
},
peralatan: "",
langkah2: "",
dapatan: "",
documentTambahan: [],
});
// State to store dapatan options
const dapatanOptions = ref([]);
onMounted(() => {
// Simulate fetching system-generated data
generatedData.value = {
kesId: `KES${Math.floor(Math.random() * 1000000)
.toString()
.padStart(6, "0")}`,
tagNo: `TAG${Math.floor(Math.random() * 10000)
.toString()
.padStart(4, "0")}`,
jenisBrg: ["Dokumen", "Elektronik", "Senjata"][
Math.floor(Math.random() * 3)
],
jenisPemeriksaan: ["Forensik", "Visual", "Kimia"][
Math.floor(Math.random() * 3)
],
pegawai: {
PENYIASAT: generatePegawai("KB"),
PENGHANTAR: generatePegawai(),
PENERIMA: generatePegawai(),
PEMERIKSA: generatePegawai(),
},
};
// Fetch dapatan options from the lookup API
const fetchDapatanOptions = async () => {
try {
const { data } = await useFetch("/api/lookup?type=dapatan");
if (data.value.statusCode === 200) {
dapatanOptions.value = data.value.data.map((item) => ({
label: item.label,
value: item.value,
}));
} else {
$swal.fire("Error", "Failed to fetch dapatan options.", "error");
}
} catch (error) {
$swal.fire("Error", "Failed to load dapatan options.", "error");
}
};
onMounted(async () => {
try {
const { data } = await useFetch(`/api/laporan/${reportID}`);
if (data.value.statusCode === 200) {
generatedData.value = {
...generatedData.value, // Keep the default structure
...data.value.data, // Merge API data
};
} else {
$swal.fire("Error", "Failed to fetch report data.", "error");
}
// Fetch dapatan options on mount
await fetchDapatanOptions();
} catch (error) {
$swal.fire("Error", "Failed to load data.", "error");
}
});
function generatePegawai(role = "") {
const names = ["Ahmad", "Siti", "Mohd", "Nurul", "Lim", "Raj"];
const surnames = ["Abdullah", "Tan", "Kumar", "Lee", "Muthu", "Hassan"];
const pangkat = ["Inspektor", "Sarjan", "Koperal", "Konstabel"];
// function generatePegawai(role = "") {
// const names = ["Ahmad", "Siti", "Mohd", "Nurul", "Lim", "Raj"];
// const surnames = ["Abdullah", "Tan", "Kumar", "Lee", "Muthu", "Hassan"];
// const pangkat = ["Inspektor", "Sarjan", "Koperal", "Konstabel"];
return {
nama: `${names[Math.floor(Math.random() * names.length)]} ${
surnames[Math.floor(Math.random() * surnames.length)]
}`,
pangkat:
role === "KB"
? "Ketua Bahagian"
: pangkat[Math.floor(Math.random() * pangkat.length)],
noPegawai: `P${Math.floor(Math.random() * 100000)
.toString()
.padStart(5, "0")}`,
};
}
// return {
// nama: `${names[Math.floor(Math.random() * names.length)]} ${
// surnames[Math.floor(Math.random() * surnames.length)]
// }`,
// pangkat:
// role === "KB"
// ? "Ketua Bahagian"
// : pangkat[Math.floor(Math.random() * pangkat.length)],
// noPegawai: `P${Math.floor(Math.random() * 100000)
// .toString()
// .padStart(5, "0")}`,
// };
// }
const submitForm = async (formData) => {
console.log("Form submitted:", formData);
// Implement your API call or form submission logic here
try {
const { data } = await useFetch(`/api/laporan/${reportID}`, {
method: "POST",
body: formData,
});
if (data.value.statusCode === 200) {
$swal.fire("Success", "Report updated successfully", "success");
} else {
$swal.fire("Error", data.value.message, "error");
}
} catch (error) {
$swal.fire("Error", "Failed to submit report", "error");
}
};
const generatePDF = () => {
const doc = new jsPDF();
// Set font sizes
const titleSize = 16;
const subtitleSize = 14;
const normalSize = 10;
// Add title
doc.setFontSize(titleSize);
doc.text("Laporan Bahan Bukti", 105, 20, { align: "center" });
// Add case details
doc.setFontSize(subtitleSize);
doc.text("Butiran Kes", 20, 40);
doc.setFontSize(normalSize);
doc.text(`KES ID: ${generatedData.value.kesId}`, 30, 50);
doc.text(`TAG NO: ${generatedData.value.tagNo}`, 30, 60);
doc.text(`Jenis Barang: ${generatedData.value.jenisBrg}`, 30, 70);
doc.text(`Jenis Pemeriksaan: ${generatedData.value.jenisPemeriksaan}`, 30, 80);
doc.text(
`Jenis Pemeriksaan: ${generatedData.value.jenisPemeriksaan}`,
30,
80
);
// Add officer details
doc.setFontSize(subtitleSize);
doc.text("Butiran Pegawai", 20, 100);
doc.setFontSize(normalSize);
let yPos = 110;
for (const [role, officer] of Object.entries(generatedData.value.pegawai)) {
@ -270,28 +298,39 @@ const generatePDF = () => {
doc.text(`No Pegawai: ${officer.noPegawai}`, 40, yPos + 30);
yPos += 45;
}
// Add examination details
doc.setFontSize(subtitleSize);
doc.text("Butiran Pemeriksaan", 20, yPos);
doc.setFontSize(normalSize);
doc.text(`Peralatan: ${generatedData.value.peralatan || "N/A"}`, 30, yPos + 10);
doc.text(`Langkah-langkah: ${generatedData.value.langkah2 || "N/A"}`, 30, yPos + 20);
doc.text(
`Peralatan: ${generatedData.value.peralatan || "N/A"}`,
30,
yPos + 10
);
doc.text(
`Langkah-langkah: ${generatedData.value.langkah2 || "N/A"}`,
30,
yPos + 20
);
doc.text(`Dapatan: ${generatedData.value.dapatan || "N/A"}`, 30, yPos + 30);
// Add additional documents
if (generatedData.value.documentTambahan && generatedData.value.documentTambahan.length > 0) {
yPos += 50;
doc.setFontSize(subtitleSize);
doc.text("Dokumen Tambahan", 20, yPos);
doc.setFontSize(normalSize);
generatedData.value.documentTambahan.forEach((doc, index) => {
doc.text(`${index + 1}. ${doc.nama}`, 30, yPos + 10 + (index * 10));
});
}
// if (
// generatedData.value.documentTambahan &&
// generatedData.value.documentTambahan.length > 0
// ) {
// yPos += 50;
// doc.setFontSize(subtitleSize);
// doc.text("Dokumen Tambahan", 20, yPos);
// doc.setFontSize(normalSize);
// generatedData.value.documentTambahan.forEach((doc, index) => {
// doc.text(`${index + 1}. ${doc.nama}`, 30, yPos + 10 + index * 10);
// });
// }
// Generate and download the PDF
doc.save(`Laporan_${generatedData.value.kesId}.pdf`);
};

View File

@ -4,21 +4,25 @@
<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'">
<rs-badge
:variant="statusSemakan === 'Selesai' ? 'success' : 'warning'"
>
{{ statusSemakan }}
</rs-badge>
</div>
<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'">
<rs-badge
:variant="statusPenerimaan === 'Diterima' ? 'success' : 'danger'"
>
{{ statusPenerimaan }}
</rs-badge>
</div>
<div class="flex gap-2 justify-end mt-5">
<rs-button @click="openSemakModal">Semak</rs-button>
<rs-button @click="openTerimaModal">Terima</rs-button>
<rs-button @click="openTolakModal">Tolak</rs-button>
<div class="flex gap-2 mt-5">
<rs-button @click="openSemakModal" variant="primary">Semak</rs-button>
<rs-button @click="openTerimaModal" variant="success">Terima</rs-button>
<rs-button @click="openTolakModal" variant="danger">Tolak</rs-button>
</div>
</rs-card>
@ -45,7 +49,7 @@
}"
:options-advanced="{
sortable: true,
responsive: true,
filterable: false,
}"
advanced
@ -70,13 +74,17 @@
<template v-slot:tindakan="data">
<div class="flex gap-2">
<rs-button
@click="openEditModal(data.text, data.index)"
@click="openEditModal(data.text.userID, data.text.assignID)"
variant="info"
size="sm"
>
<Icon name="ic:baseline-edit" size="1.2rem" />
</rs-button>
<rs-button @click="confirmDelete(data.text)" variant="danger" size="sm">
<rs-button
@click="confirmDelete(data.text.userID, data.text.assignID)"
variant="danger"
size="sm"
>
<Icon name="ic:baseline-delete" size="1.2rem" />
</rs-button>
</div>
@ -91,6 +99,7 @@
<rs-card class="p-6">
<h3 class="text-lg font-semibold mb-4">Bahan Bukti</h3>
<rs-table
v-if="evidences.length > 0"
:data="evidences"
:options="{
variant: 'default',
@ -99,7 +108,7 @@
}"
:options-advanced="{
sortable: true,
responsive: true,
filterable: false,
}"
advanced
@ -114,9 +123,6 @@
<th>Tindakan</th>
</tr>
</template>
<template v-slot:no="data">
{{ data.text }}
</template>
<template v-slot:jenisBarang="data">
{{ data.text }}
</template>
@ -140,6 +146,9 @@
</rs-button>
</template>
</rs-table>
<div v-else class="text-center p-10">
<p>Tidak ada bahan bukti yang terlibat.</p>
</div>
</rs-card>
<!-- Add/Edit Modal -->
@ -172,7 +181,6 @@
<template #footer> </template>
</rs-modal>
<!-- Semak Modal -->
<rs-modal v-model="showSemakModal" @close="closeSemakModal">
<template #header>
<h3>Semak Maklumat</h3>
@ -227,8 +235,10 @@
validation="required"
/>
<div class="flex justify-end gap-2 mt-4">
<rs-button variant="danger" @click="closeSemakModal">Batal</rs-button>
<rs-button variant="primary" type="submit">Hantar</rs-button>
<rs-button variant="danger" @click="closeSemakModal"
>Batal</rs-button
>
<rs-button variant="primary" btn-type="submit">Hantar</rs-button>
</div>
</FormKit>
@ -255,8 +265,10 @@
}"
/>
<div class="flex justify-end gap-2 mt-4">
<rs-button variant="danger" @click="closeSemakModal">Batal</rs-button>
<rs-button variant="primary" type="submit">Hantar</rs-button>
<rs-button variant="danger" @click="closeSemakModal"
>Batal</rs-button
>
<rs-button variant="primary" btn-type="submit">Hantar</rs-button>
</div>
</FormKit>
</template>
@ -314,8 +326,10 @@
validation="required"
/>
<div class="flex justify-end gap-2 mt-4">
<rs-button variant="danger" @click="closeTerimaModal">Batal</rs-button>
<rs-button variant="primary" type="submit">Hantar</rs-button>
<rs-button variant="danger" @click="closeTerimaModal"
>Batal</rs-button
>
<rs-button variant="primary" btn-type="submit">Hantar</rs-button>
</div>
</FormKit>
</template>
@ -335,12 +349,7 @@
type="select"
name="sebabPenolakan"
label="Sebab penolakan permohonan"
:options="[
'Dokumen tidak lengkap',
'Maklumat tidak tepat',
'Tidak memenuhi syarat',
'Lain-lain',
]"
:options="sebabPenolakanOptions"
validation="required"
:validation-messages="{
required: 'Sila pilih sebab penolakan',
@ -356,8 +365,10 @@
}"
/>
<div class="flex justify-end gap-2 mt-4">
<rs-button variant="secondary" @click="closeTolakModal">Batal</rs-button>
<rs-button variant="danger" type="submit">Hantar</rs-button>
<rs-button variant="secondary" @click="closeTolakModal"
>Batal</rs-button
>
<rs-button variant="danger" btn-type="submit">Hantar</rs-button>
</div>
</FormKit>
</template>
@ -369,127 +380,294 @@
</template>
<script setup>
import { ref, computed, onMounted } from "vue";
definePageMeta({
layout: "default",
});
const route = useRoute();
const { $swal } = useNuxtApp();
// Status data
const statusSemakan = ref("Selesai");
const statusPenerimaan = ref("Diterima");
// Forensic Officers Data
// State variables
const showModal = ref(false);
const forensicOfficers = ref([]);
// Evidence Data
const evidences = ref([
{
no: 1,
jenisBarang: "Dokumen",
tagNo: "TAG001",
keadaan: "Baik",
kuantiti: 3,
tindakan: 1,
},
{
no: 2,
jenisBarang: "Peralatan Elektronik",
tagNo: "TAG002",
keadaan: "Rosak",
kuantiti: 5,
tindakan: 2,
},
]);
// User Roles
const pegawaiOption = ref([]);
const selectedPegawai = ref(null);
const editMode = ref(false);
const currentOfficerID = ref(null);
const currentAssignID = ref(null);
const isKetuaBahagian = ref(true);
const isKetuaJabatan = ref(false);
// Modal Controls
const showModal = ref(false);
const editMode = ref(false);
const selectedPegawai = ref(null);
const sebabPenolakanOptions = ref([]);
// Sample pegawai listing (simulating API response)
const pegawaiList = ref([]);
const pegawaiOption = ref([
{
value: null,
label: "Pilih Pegawai",
},
]);
// Evidence Data
const evidences = 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",
tindakan: 1,
},
{
id: "PG002",
nama: "Siti binti Omar",
pangkat: "Sarjan",
noPegawai: "PG67890",
tindakan: 2,
},
{
id: "PG003",
nama: "Muthu a/l Rajan",
pangkat: "Koperal",
noPegawai: "PG24680",
tindakan: 3,
},
];
// Fetch the status data
const fetchStatusData = async () => {
try {
const { data } = await useFetch(
`/api/permohonan/${route.params.noSiri}/status`
);
if (data.value.statusCode === 200) {
statusSemakan.value = data.value.data.statusSemakan || "Belum Disemak";
statusPenerimaan.value =
data.value.data.statusPenerimaan || "Belum Diterima";
} else {
$swal.fire(
"Error",
"Gagal mendapatkan status semakan dan penerimaan.",
"error"
);
}
} catch (error) {
$swal.fire("Error", "Gagal memuatkan data status.", "error");
}
};
onMounted(() => {
fetchPegawaiList();
// Fetch reports (Bahan Bukti)
const fetchReports = async () => {
try {
const { data } = await useFetch(
`/api/permohonan/${route.params.noSiri}/reports`
);
for (let index = 0; index < pegawaiList.value.length; index++) {
pegawaiOption.value.push({
value: pegawaiList.value[index].tindakan,
label: `${pegawaiList.value[index].pangkat} ${pegawaiList.value[index].nama} (${pegawaiList.value[index].noPegawai})`,
});
if (data.value.statusCode === 200) {
evidences.value = data.value.data || [];
}
} catch (error) {
console.error("Error fetching reports:", error);
$swal.fire("Error", "Gagal mendapatkan senarai bahan bukti.", "error");
}
});
};
// Computed property for form validation
const isFormValid = computed(() => {
return (
// filter pegawaiList based on selectedPegawai
pegawaiList.value.filter((p) => p.tindakan === selectedPegawai.value)
);
});
// Fetch existing forensic officers and available officers
const fetchAssignedOfficers = async () => {
try {
const { data } = await useFetch(
`/api/permohonan/${route.params.noSiri}/forensik/list`
);
if (data.value.statusCode === 200) {
forensicOfficers.value = data.value.data || [];
}
} catch (error) {
console.error("Error fetching forensic officers:", error);
$swal.fire("Error", "Gagal mendapatkan senarai pegawai forensik.", "error");
}
};
// Actions
const fetchAvailableOfficers = async () => {
try {
const { data } = await useFetch(
`/api/permohonan/${route.params.noSiri}/forensik/available`
);
if (data.value.statusCode === 200) {
pegawaiOption.value = data.value.data || [];
}
} catch (error) {
console.error("Error fetching available officers:", error);
$swal.fire("Error", "Gagal mendapatkan senarai pegawai tersedia.", "error");
}
};
const fetchSebabPenolakanOptions = async () => {
try {
const { data } = await useFetch("/api/lookup?type=sebab_penolakan");
if (data.value.statusCode === 200) {
sebabPenolakanOptions.value = data.value.data;
} else {
$swal.fire("Error", "Failed to fetch sebab penolakan options", "error");
}
} catch (error) {
$swal.fire("Error", "Failed to load lookup data", "error");
}
};
// Open modals
const openAddModal = () => {
editMode.value = false;
selectedPegawai.value = null;
fetchAvailableOfficers();
showModal.value = true;
};
const openEditModal = (pegawai, index) => {
const openEditModal = (userID, assignID) => {
editMode.value = true;
selectedPegawai.value = pegawai;
console.log(selectedPegawai.value);
console.log("index", index);
currentOfficerID.value = userID;
currentAssignID.value = assignID;
selectedPegawai.value = null;
fetchAvailableOfficers(); // Get updated available officers for edit mode
showModal.value = true;
};
const confirmDelete = (userID, assignID) => {
$swal
.fire({
title: "Apakah anda pasti?",
text: "Anda tidak akan dapat mengembalikannya!",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "Ya, hapus!",
})
.then((result) => {
if (result.isConfirmed) {
deletePegawai(userID, assignID);
}
});
};
// Close modal
const closeModal = () => {
showModal.value = false;
selectedPegawai.value = null;
};
// Add new officer
const addNewPegawai = async () => {
try {
const response = await useFetch(
`/api/permohonan/${route.params.noSiri}/forensik/add`,
{
method: "POST",
body: { pegawaiID: selectedPegawai.value },
}
);
if (response.data.value.statusCode === 200) {
await fetchAssignedOfficers();
$swal.fire("Berjaya", "Pegawai baru telah ditambah", "success");
closeModal();
} else {
$swal.fire("Error", response.data.message, "error");
}
} catch (error) {
$swal.fire("Error", "Gagal menambah pegawai.", "error");
}
};
// Edit existing officer
const updatePegawai = async () => {
try {
const response = await useFetch(
`/api/permohonan/${route.params.noSiri}/forensik/edit`,
{
method: "PUT",
body: {
assignID: currentAssignID.value,
newPegawaiID: selectedPegawai.value,
},
}
);
if (response.data.value.statusCode === 200) {
await fetchAssignedOfficers(); // Refresh the list of officers
$swal.fire("Berjaya", "Maklumat pegawai telah dikemaskini", "success");
closeModal();
} else {
$swal.fire("Error", response.data.message, "error");
}
} catch (error) {
$swal.fire("Error", "Gagal mengemaskini maklumat pegawai.", "error");
}
};
// Delete officer
const deletePegawai = async (officer, assignID) => {
try {
const response = await useFetch(
`/api/permohonan/${route.params.noSiri}/forensik/delete`,
{
method: "DELETE",
body: { assignID: assignID },
}
);
if (response.data.value.statusCode === 200) {
await fetchAssignedOfficers();
$swal.fire("Dihapuskan!", "Pegawai telah dipadam.", "success");
} else {
$swal.fire("Error", response.data.message, "error");
}
} catch (error) {
$swal.fire("Error", "Gagal memadam pegawai.", "error");
}
};
// Submit Semak form
const handleSemakSubmit = async (formData) => {
try {
const response = await useFetch(
`/api/permohonan/${route.params.noSiri}/semak`,
{
method: "POST",
body: formData,
}
);
if (response.data.value.statusCode === 200) {
$swal.fire("Berjaya", "Maklumat semakan telah disimpan", "success");
await fetchStatusData();
} else {
$swal.fire("Error", response.data.message, "error");
}
} catch (error) {
$swal.fire("Error", "Gagal menyimpan semakan.", "error");
}
closeSemakModal();
};
// Submit Terima form
const handleTerimaSubmit = async (formData) => {
try {
const response = await useFetch(
`/api/permohonan/${route.params.noSiri}/terima`,
{
method: "POST",
body: formData,
}
);
if (response.data.value.statusCode === 200) {
$swal.fire("Berjaya", "Permohonan telah diterima", "success");
await fetchStatusData();
} else {
$swal.fire("Error", response.data.message, "error");
}
} catch (error) {
$swal.fire("Error", "Gagal menerima permohonan.", "error");
}
closeTerimaModal();
};
// Submit Tolak form
const handleTolakSubmit = async (formData) => {
try {
const response = await useFetch(
`/api/permohonan/${route.params.noSiri}/tolak`,
{
method: "POST",
body: formData,
}
);
if (response.data.value.statusCode === 200) {
$swal.fire("Berjaya", "Permohonan telah ditolak", "success");
navigateTo("/kemaskini-daftar/senarai");
} else {
$swal.fire("Error", response.data.message, "error");
}
} catch (error) {
$swal.fire("Error", "Gagal menolak permohonan.", "error");
}
closeTolakModal();
};
// Handle form submission (add/edit)
const handleSubmit = () => {
if (editMode.value) {
updatePegawai();
@ -498,93 +676,15 @@ const handleSubmit = () => {
}
};
const addNewPegawai = () => {
console.log(selectedPegawai.value);
if (selectedPegawai.value) {
const selectedPegawai_ = pegawaiList.value.find(
(p) => p.tindakan === selectedPegawai.value
);
if (selectedPegawai_) {
const newPegawai = {
...selectedPegawai_,
tindakan: selectedPegawai_.tindakan,
};
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 = () => {
console.log("masuk uodate");
if (selectedPegawai.value) {
console.log(selectedPegawai.value);
const selectedPegawai_ = pegawaiList.value.find(
(p) => p.tindakan == selectedPegawai.value
);
console.log("selectedPegawai_", selectedPegawai_);
if (selectedPegawai_) {
const pegawaiFromSelectedPegawais = forensicOfficers.value.findIndex(
(officer) => officer.tindakan === selectedPegawai.value
);
console.log("pegawaiFromSelectedPegawais", pegawaiFromSelectedPegawais);
if (pegawai_ !== -1) {
forensicOfficers.value[pegawai_] = {
...selectedPegawai_,
tindakan: selectedPegawai_.tindakan,
};
$swal.fire("Berjaya", "Maklumat pegawai telah dikemaskini", "success");
closeModal();
} else {
$swal.fire("Ralat", "Pegawai tidak dijumpai", "error");
}
} else {
$swal.fire("Ralat", "Pegawai tidak dijumpai", "error");
}
} else {
$swal.fire("Ralat", "Sila pilih pegawai", "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);
}
});
};
const deletePegawai = (pegawai) => {
const index = forensicOfficers.value.findIndex(
(officer) => officer.tindakan === pegawai
);
if (index !== -1) {
forensicOfficers.value.splice(index, 1);
$swal.fire("Dihapuskan!", "Pegawai telah dipadam.", "success");
} else {
$swal.fire("Ralat", "Pegawai tidak dijumpai", "error");
}
};
// Fetch officers when the component mounts
onMounted(() => {
fetchStatusData();
fetchAssignedOfficers();
fetchReports(); // Fetch reports related to the permohonan
});
const generateReport = (bahanBukti) => {
console.log("Generate Report for:", bahanBukti);
navigateTo(`/kemaskini-daftar/laporan/${bahanBukti}`);
};
@ -600,26 +700,11 @@ const closeSemakModal = () => {
};
// User role (you might want to fetch this from your auth system)
const userRole = ref("Pegawai Kaunter"); // Change this to 'ketuaBahagian' to test the other form
const userRole = ref("Pegawai Kaunter"); // Change this to 'Ketua Bahagian' to test the other form
// For ketua bahagian form
const kelulusanKetuaBahagian = ref(null);
const handleSemakSubmit = (formData) => {
console.log("Semak form submitted:", formData);
// Here you would typically send the data to your API
let successMessage = "";
if (userRole.value === "Pegawai Kaunter") {
successMessage = "Maklumat semakan telah disimpan";
} else if (userRole.value === "Ketua Bahagian") {
const decision =
formData.kelulusanKetuaBahagian === "Diterima" ? "diterima" : "ditolak";
successMessage = `Permohonan telah ${decision}. Ulasan: ${formData.ulasanKetuaBahagian}`;
}
$swal.fire("Berjaya", successMessage, "success");
closeSemakModal();
};
// Terima Modal Controls
const showTerimaModal = ref(false);
@ -631,53 +716,19 @@ const closeTerimaModal = () => {
showTerimaModal.value = false;
};
const handleTerimaSubmit = (formData) => {
console.log("Terima form submitted:", formData);
// Here you would typically send the data to your API
let successMessage = "Permohonan telah diterima.";
// Check if any of the radio button answers are 'Tidak'
const hasNegativeResponse = [
"peralatanBaik",
"pegawaiBerkelayakan",
"kaedahDapatDilakukan",
"tugasanDiterima",
].some((field) => formData[field] === "Tidak");
if (hasNegativeResponse) {
successMessage += " Namun, terdapat beberapa perkara yang perlu diberi perhatian.";
}
successMessage += ` Ulasan: ${formData.ulasanPegawaiKaunter}`;
$swal.fire("Berjaya", successMessage, "success");
closeTerimaModal();
};
// Tolak Modal Controls
const showTolakModal = ref(false);
const openTolakModal = () => {
const openTolakModal = async () => {
await fetchSebabPenolakanOptions();
showTolakModal.value = true;
};
const closeTolakModal = () => {
showTolakModal.value = false;
};
const handleTolakSubmit = (formData) => {
console.log("Tolak form submitted:", formData);
// Here you would typically send the data to your API
let rejectionReason = formData.sebabPenolakan;
if (rejectionReason === "Lain-lain") {
rejectionReason += `: ${formData.lainLainSebab}`;
}
const successMessage = `Permohonan telah ditolak. Sebab: ${rejectionReason}`;
$swal.fire("Berjaya", successMessage, "success");
closeTolakModal();
};
</script>
<style lang="scss" scoped></style>
<style scoped>
/* Your existing styles */
</style>

View File

@ -7,16 +7,16 @@
<rs-card class="mt-4 py-2">
<rs-table
:data="tableData"
:options='{
variant: "default",
:options="{
variant: 'default',
striped: true,
borderless: true
}'
:options-advanced='{
borderless: true,
}"
:options-advanced="{
sortable: true,
responsive: true,
filterable: false
}'
filterable: false,
}"
advanced
>
<template v-slot:header>
@ -73,50 +73,29 @@
</template>
<script setup>
import { ref } from "vue";
const { $swal } = useNuxtApp();
definePageMeta({
title: "Senarai Permohonan",
});
const tableData = ref([
{
no: 1,
noSiri: "1234567890",
tarikhMasa: "2024-01-01 12:00:00",
status: "Aktif",
butiran: 1,
},
{
no: 2,
noSiri: "0987654321",
tarikhMasa: "2024-02-01 14:30:00",
status: "Aktif",
butiran: 2,
},
{
no: 3,
noSiri: "1122334455",
tarikhMasa: "2024-03-01 09:15:00",
status: "Aktif",
butiran: 3,
},
{
no: 4,
noSiri: "5566778899",
tarikhMasa: "2024-04-01 16:45:00",
status: "Aktif",
butiran: 4,
},
{
no: 5,
noSiri: "6677889900",
tarikhMasa: "2024-05-01 11:00:00",
status: "Aktif",
butiran: 5,
},
]);
// Reactive variable to store table data
const tableData = ref([]);
// Fetch permohonan list from API
const fetchPermohonan = async () => {
try {
const response = await useFetch("/api/permohonan");
if (response.data.value.statusCode === 200) {
// Populate tableData with the fetched permohonan list
tableData.value = response.data.value.data;
} else {
console.error(response.data.value.message);
}
} catch (error) {
console.error("Error fetching permohonan data:", error);
}
};
const permohonanBaru = () => {
navigateTo("/permohonan-temujanji/baru");
@ -131,29 +110,40 @@ const lihat = (item) => {
navigateTo(`/kemaskini-daftar/maklumat/${item}`);
};
const hapus = (item) => {
$swal
.fire({
title: "Anda pasti?",
text: "Anda tidak akan dapat memulihkan semula data ini!",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "Ya, hapuskan!",
cancelButtonText: "Batal",
})
.then((result) => {
if (result.isConfirmed) {
// Perform deletion logic here
console.log("Deleting item:", item);
// Remove the item from the tableData
const index = tableData.value.findIndex((row) => row.noSiri === item);
if (index !== -1) {
tableData.value.splice(index, 1);
}
$swal.fire("Dihapuskan!", "Data telah dihapuskan.", "success");
const hapus = async (noSiri) => {
const confirmation = await $swal.fire({
title: "Anda pasti?",
text: "Anda tidak akan dapat memulihkan semula data ini!",
icon: "warning",
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
confirmButtonText: "Ya, hapuskan!",
cancelButtonText: "Batal",
});
if (confirmation.isConfirmed) {
try {
const response = await useFetch(`/api/permohonan/${noSiri}`, {
method: "DELETE",
});
if (response.data.value.statusCode === 200) {
// Remove the deleted permohonan from tableData
tableData.value = tableData.value.filter(
(row) => row.noSiri !== noSiri
);
$swal.fire("Dihapuskan!", response.data.value.message, "success");
} else {
$swal.fire("Error!", response.data.value.message, "error");
}
});
} catch (error) {
$swal.fire("Error!", "Failed to delete permohonan.", "error");
}
}
};
// Fetch the permohonan list when the component is mounted
onMounted(() => {
fetchPermohonan();
});
</script>

View File

@ -98,7 +98,11 @@
<tbody>
<tr v-for="(barang, index) in barangList" :key="index">
<td class="border border-gray-300 p-2">
{{ getJenisBarangLabel(barang.jenisBarangDetail) }}
{{
barang.jenisBarangDetailLabel
? barang.jenisBarangDetailLabel
: barang.jenisBarangDetail
}}
</td>
<td class="border border-gray-300 p-2">
{{ barang.kuantitiBarang }}
@ -369,9 +373,19 @@ const cancelBarangModal = () => {
const saveBarangModal = () => {
if (editingBarangIndex.value === null) {
barangList.value.push({ ...currentBarang.value });
barangList.value.push({
...currentBarang.value,
jenisBarangDetailLabel: getJenisBarangLabel(
currentBarang.value.jenisBarangDetail
),
});
} else {
barangList.value[editingBarangIndex.value] = { ...currentBarang.value };
barangList.value[editingBarangIndex.value] = {
...currentBarang.value,
jenisBarangDetailLabel: getJenisBarangLabel(
currentBarang.value.jenisBarangDetail
),
};
}
isBarangModalOpen.value = false;
};
@ -445,10 +459,10 @@ const submitData = async (isDraft) => {
icon: "success",
confirmButtonText: "OK",
});
// Redirect to senarai page after successful submission
if (!isDraft) {
router.push('/permohonan-temujanji/senarai');
router.push("/permohonan-temujanji/senarai");
}
} else {
$swal.fire({

View File

@ -97,7 +97,11 @@
<tbody>
<tr v-for="(barang, index) in barangList" :key="index">
<td class="border border-gray-300 p-2">
{{ getJenisBarangLabel(barang.jenisBarangDetail) }}
{{
barang.jenisBarangDetailLabel
? barang.jenisBarangDetailLabel
: barang.jenisBarangDetail
}}
</td>
<td class="border border-gray-300 p-2">
{{ barang.kuantitiBarang }}
@ -406,9 +410,19 @@ const cancelBarangModal = () => {
const saveBarangModal = () => {
if (editingBarangIndex.value === null) {
barangList.value.push({ ...currentBarang.value });
barangList.value.push({
...currentBarang.value,
jenisBarangDetailLabel: getJenisBarangLabel(
currentBarang.value.jenisBarangDetail
),
});
} else {
barangList.value[editingBarangIndex.value] = { ...currentBarang.value };
barangList.value[editingBarangIndex.value] = {
...currentBarang.value,
jenisBarangDetailLabel: getJenisBarangLabel(
currentBarang.value.jenisBarangDetail
),
};
}
isBarangModalOpen.value = false;
};

View File

@ -20,7 +20,6 @@
}"
:options-advanced="{
sortable: true,
responsive: true,
filterable: false,
}"
advanced
@ -62,10 +61,7 @@
<template v-slot:butiran="data">
<div
class="flex flex-wrap gap-2"
v-if="
data.value.status !== 'Sah' &&
data.value.status !== 'Permohonan Dihantar'
"
v-if="data.value.status === 'Permohonan Draf'"
>
<!-- Button to navigate to the "Kemaskini" page for the selected permohonan -->
<rs-button

View File

@ -106,8 +106,8 @@ model permohonan {
penghantar penghantar? @relation(fields: [penghantarID], references: [id], onDelete: Cascade, onUpdate: Restrict, map: "permohonan_ibfk_1")
permohonan_assign_forensik permohonan_assign_forensik[]
permohonan_jenis_barang permohonan_jenis_barang[]
permohonan_penerimaan permohonan_penerimaan[]
permohonan_semakan permohonan_semakan[]
permohonan_penerimaan permohonan_penerimaan?
permohonan_semakan permohonan_semakan?
report report[]
@@index([pemohonID], map: "idx_pemohon")
@ -129,25 +129,24 @@ model permohonan_assign_forensik {
model permohonan_penerimaan {
penerimaanID Int @id @default(autoincrement())
permohonanID Int
permohonanID Int @unique(map: "permohonanID")
peralatan_keadaan_baik Int
pegawai_berkelayakan Int
kaedah_dpt_dilakukan Int
subkontrak_diperlukan Int
tugasan_diterima Int
ulasan_pegawai Int?
ulasan_pegawai String? @db.Text
create_at DateTime @db.DateTime(0)
diterima_oleh Int
permohonan permohonan @relation(fields: [permohonanID], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "permohonan_penerimaan_ibfk_1")
user user @relation(fields: [diterima_oleh], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "permohonan_penerimaan_ibfk_2")
@@index([diterima_oleh], map: "diterima_oleh")
@@index([permohonanID], map: "permohonanID")
}
model permohonan_penolakan {
penolakanID Int @id @default(autoincrement())
permohonanID Int
permohonanID Int @unique(map: "permohonanID")
sebab_penolakan Int
lain_sebab String? @db.VarChar(255)
create_at DateTime? @db.DateTime(0)
@ -161,20 +160,19 @@ model permohonan_penolakan {
model permohonan_semakan {
semakanID Int @id @default(autoincrement())
permohonanID Int
peralatan_keadaan_baik Int
pegawai_berkelayakan Int
kaedah_dpt_dilakukan Int
subkontrak_diperlukan Int
tugasan_diterima Int
permohonanID Int @unique(map: "permohonanID")
peralatan_keadaan_baik Int?
pegawai_berkelayakan Int?
kaedah_dpt_dilakukan Int?
subkontrak_diperlukan Int?
tugasan_diterima Int?
ulasan_pegawai String? @db.Text
create_at Int
disemak_oleh Int
create_at DateTime? @db.DateTime(0)
disemak_oleh Int?
permohonan permohonan @relation(fields: [permohonanID], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "permohonan_semakan_ibfk_1")
user user @relation(fields: [disemak_oleh], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "permohonan_semakan_ibfk_2")
user user? @relation(fields: [disemak_oleh], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "permohonan_semakan_ibfk_2")
@@index([disemak_oleh], map: "disemak_oleh")
@@index([permohonanID], map: "permohonanID")
}
model role {
@ -275,8 +273,11 @@ model report {
reportID Int @id @default(autoincrement())
permohonanID Int
jenis_barang Int
tanda_barang String? @db.VarChar(255)
keadaan_barang String? @db.VarChar(255)
kuantiti_barang Int?
peralatan String? @db.VarChar(255)
langkah_langkah Int?
langkah_langkah String? @db.VarChar(255)
gambarID Int?
ulasan String? @db.Text
dapatan Int?

View File

@ -0,0 +1,54 @@
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params; // Extract the noSiri from the URL
const body = await readBody(event); // Read the request body
const { ringkasanKenyataanKes, noKertasSiasatan, noLaporanPolis } = body;
// 1. Validate the input fields (all three fields must be provided)
if (!ringkasanKenyataanKes || !noKertasSiasatan || !noLaporanPolis) {
return {
statusCode: 400,
message:
"Setiap medan mandatori yang bertanda * telah diisi. (Ralat CMN-E001)",
};
}
try {
// 2. Check if the permohonan exists by its `no_siri`
const existingPermohonan = await prisma.permohonan.findUnique({
where: { no_siri: noSiri },
});
// If no `permohonan` is found, return a 404 error
if (!existingPermohonan) {
return {
statusCode: 404,
message: `Permohonan with noSiri ${noSiri} not found.`,
};
}
// 3. Proceed to update only the allowed fields (ringkasanKenyataanKes, noKertasSiasatan, noLaporanPolis)
const updatedPermohonan = await prisma.permohonan.update({
where: { no_siri: noSiri },
data: {
ringkasan_kenyataan_kes: ringkasanKenyataanKes,
no_kertas_siasatan: noKertasSiasatan,
no_laporan_polis: noLaporanPolis,
modified_at: new Date(), // Update the modified_at timestamp
},
});
// 4. Return success response
return {
statusCode: 200,
message: "Permohonan telah berjaya dikemaskini.",
data: updatedPermohonan,
};
} catch (error) {
console.error("Error updating permohonan:", error);
return {
statusCode: 500,
message: "Gagal mengemaskini permohonan. Sila cuba lagi.",
};
}
});

View File

@ -0,0 +1,103 @@
// Path: /api/report/[reportID].get.js
export default defineEventHandler(async (event) => {
const { reportID } = event.context.params;
try {
const report = await prisma.report.findUnique({
where: { reportID: parseInt(reportID) },
include: {
permohonan: {
include: {
penghantar: true,
pemohon: {
include: {
user: true,
},
},
},
},
lookup_report_jenis_barangTolookup: true,
lookup_report_dapatanTolookup: {
select: {
lookupID: true,
lookupValue: true,
},
},
report_doc_support: {
include: {
document: true,
},
},
},
});
console.log(report);
if (!report) {
return { statusCode: 404, message: "Report not found" };
}
// Format the data for the frontend
const reportData = {
kesId: report.permohonan.no_siri,
tagNo: report.tanda_barang,
jenisBrg: report.lookup_report_jenis_barangTolookup.lookupValue,
jenisPemeriksaan: "Forensik", // Assuming it's static for now
pegawai: {
PENYIASAT: {
nama: report.permohonan.pemohon?.user?.userFullName || "",
pangkat: report.permohonan.pemohon?.pangkat_pemohon || "",
noPegawai: report.permohonan.pemohon?.no_pegawai_pemohon || "",
},
PENGHANTAR: {
nama: report.permohonan.penghantar_sama_dengan_pemohon
? report.permohonan.pemohon?.user?.userFullName || ""
: report.permohonan.penghantar?.nama_penghantar || "",
pangkat: report.permohonan.penghantar_sama_dengan_pemohon
? report.permohonan.pemohon?.pangkat_pemohon || ""
: report.permohonan.penghantar?.pangkat_penghantar || "",
noPegawai: report.permohonan.penghantar_sama_dengan_pemohon
? report.permohonan.pemohon?.no_pegawai_pemohon || ""
: report.permohonan.penghantar?.no_pegawai_penghantar || "",
},
PEMERIKSA: {
nama: report.permohonan.pemerikasa?.user?.userFullName || "",
pangkat: report.permohonan.pemerikasa?.pangkat_pemerikasa || "",
noPegawai: report.permohonan.pemerikasa?.no_pegawai_pemerikasa || "",
},
PENERIMA: {
nama: report.permohonan.penerima?.user?.userFullName || "",
pangkat: report.permohonan.penerima?.pangkat_penerima || "",
noPegawai: report.permohonan.penerima?.no_pegawai_penerima || "",
},
// Fill in other roles accordingly
},
peralatan: report.peralatan,
langkah2: report.langkah_langkah,
dapatan: {
value: report.lookup_report_dapatanTolookup?.lookupID,
label: report.lookup_report_dapatanTolookup?.lookupValue,
},
documentTambahan: report.report_doc_support
? [
{
nama: report.report_doc_support[0].document.documentName,
file: report.report_doc_support[0].document.documentURL,
},
]
: [
{
nama: "",
file: "",
}
],
};
return { statusCode: 200, data: reportData };
} catch (error) {
console.log(error);
return { statusCode: 500, message: error.message };
}
});

View File

@ -0,0 +1,63 @@
// Path: /api/report/[reportID].post.js
export default defineEventHandler(async (event) => {
const { reportID } = event.context.params;
const body = await readBody(event);
const {
peralatan,
langkah2,
dapatan, // This should correspond to lookupID in the `lookup` table
documentTambahan, // Array of documents
} = body;
console.log(body);
try {
// Update the report in the database
const updatedReport = await prisma.report.update({
where: { reportID: parseInt(reportID) },
data: {
peralatan,
langkah_langkah: langkah2,
dapatan: parseInt(dapatan), // Assuming this is a lookupID from the `lookup` table
},
});
// Handle document uploads (if necessary)
if (documentTambahan && documentTambahan.length > 0) {
// Create documents first
const createdDocuments = await prisma.document.createMany({
data: documentTambahan.map((doc) => ({
documentName: doc.nama,
})),
skipDuplicates: true,
});
// Get the IDs of the newly created documents
const newDocumentIds = await prisma.document.findMany({
where: {
documentName: {
in: documentTambahan.map((doc) => doc.nama),
},
},
select: {
documentID: true,
documentName: true,
},
});
// Update report_doc_support table
await prisma.report_doc_support.createMany({
data: newDocumentIds.map((doc) => ({
reportID: updatedReport.reportID,
documentID: doc.documentID,
})),
});
}
return { statusCode: 200, message: "Report updated successfully" };
} catch (error) {
console.log(error);
return { statusCode: 500, message: "Failed to update report" };
}
});

View File

@ -1,3 +1,4 @@
// path: /api/lookup?type=jenis_barang
export default defineEventHandler(async (event) => {
const { type } = getQuery(event); // Get lookup type from query params, e.g., jenis_barang, dapatan
@ -20,10 +21,22 @@ export default defineEventHandler(async (event) => {
lookupValue: true,
},
});
if (!lookups) {
return {
statusCode: 404,
message: "Lookup data not found",
};
}
// Convert snake_case to Title Case: e.g., jenis_barang_siber -> Jenis Barang Siber
const defaultTitle = type
.split("_")
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
.join(" ");
// Transform the lookups data to the required format
const transformedLookups = [
{ label: "", value: null }, // Add an empty option as the first item
{ label: `Sila Pilih ${defaultTitle}`, value: null }, // Add an empty option as the first item
...lookups.map((lookup) => ({
label: lookup.lookupValue,
value: lookup.lookupID,

View File

@ -22,7 +22,20 @@ export default defineEventHandler(async (event) => {
},
},
penghantar: true,
report: true, // Assuming 'report' is where the `barang` (items) are stored
report: {
select: {
jenis_barang: true,
lookup_report_jenis_barangTolookup: {
select: {
lookupID: true,
lookupValue: true,
},
},
tanda_barang: true,
keadaan_barang: true,
kuantiti_barang: true,
},
},
},
});
@ -47,7 +60,10 @@ export default defineEventHandler(async (event) => {
ringkasanKenyataanKes: permohonan.ringkasan_kenyataan_kes || "",
bilangan: permohonan.bilangan || 0,
barangList: permohonan.report.map((barang) => ({
jenisBarangDetail: barang.jenis_barang || "",
jenisBarangDetail:
barang.lookup_report_jenis_barangTolookup.lookupID || "",
jenisBarangDetailLabel:
barang.lookup_report_jenis_barangTolookup.lookupValue || "",
tandaBarang: barang.tanda_barang || "",
keadaanBarang: barang.keadaan_barang || "",
kuantitiBarang: barang.kuantiti_barang || 0,

View File

@ -127,21 +127,13 @@ export default defineEventHandler(async (event) => {
});
for (const barang of barangList) {
// await prisma.report.create({
// data: {
// permohonanID: updatedPermohonan.id,
// jenis_barang: barang.jenisBarangDetail,
// kuantiti_barang: barang.kuantitiBarang,
// tanda_barang: barang.tandaBarang,
// keadaan_barang: barang.keadaanBarang,
// create_by: userID,
// create_at: new Date(),
// },
// });
await prisma.report.create({
data: {
permohonanID: updatedPermohonan.id,
jenis_barang: barang.jenisBarangDetail,
kuantiti_barang: parseInt(barang.kuantitiBarang),
tanda_barang: barang.tandaBarang,
keadaan_barang: barang.keadaanBarang,
create_by: userID,
create_at: new Date(),
},

View File

@ -0,0 +1,42 @@
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params;
const body = await readBody(event);
const { pegawaiID } = body;
try {
// Ensure that the permohonan exists
const permohonan = await prisma.permohonan.findUnique({
where: { no_siri: noSiri },
});
if (!permohonan) {
return { statusCode: 404, message: "Permohonan tidak dijumpai." };
}
// Ensure that the pegawai is not already assigned
const existingAssignment =
await prisma.permohonan_assign_forensik.findFirst({
where: {
permohonanID: permohonan.id,
pegawai_forensikID: pegawaiID,
},
});
if (existingAssignment) {
return { statusCode: 400, message: "Pegawai sudah ditugaskan." };
}
// Assign the pegawai to this permohonan
await prisma.permohonan_assign_forensik.create({
data: {
permohonanID: permohonan.id,
pegawai_forensikID: pegawaiID,
},
});
return { statusCode: 200, message: "Pegawai berjaya ditambah." };
} catch (error) {
console.error(error);
return { statusCode: 500, message: "Error adding forensic officer." };
}
});

View File

@ -0,0 +1,51 @@
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params;
try {
// Fetch the list of assigned officers
const assignedOfficers = await prisma.permohonan_assign_forensik.findMany({
where: { permohonan: { no_siri: noSiri } },
select: { pegawai_forensikID: true },
});
const assignedOfficerIDs = assignedOfficers.map(
(officer) => officer.pegawai_forensikID
);
// Fetch all pegawai forensik that are not assigned to this permohonan
const availablePegawai = await prisma.user.findMany({
where: {
userID: { notIn: assignedOfficerIDs },
userStatus: "ACTIVE",
userrole: {
some: {
role: {
roleName: "Pegawai Forensik",
},
},
},
},
select: {
userID: true,
userFullName: true,
userUsername: true,
},
});
return {
statusCode: 200,
data: [
{ value: "", label: "Sila Pilih Pegawai" },
...availablePegawai.map((pegawai) => ({
value: pegawai.userID,
label: `${pegawai.userFullName}`,
})),
],
};
} catch (error) {
return {
statusCode: 500,
message: "Error fetching available forensic officers.",
};
}
});

View File

@ -0,0 +1,27 @@
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params;
const body = await readBody(event);
const { assignID } = body;
try {
// Fetch the existing permohonan
const permohonan = await prisma.permohonan.findUnique({
where: { no_siri: noSiri },
});
if (!permohonan) {
return { statusCode: 404, message: "Permohonan tidak dijumpai." };
}
// Delete the pegawai assignment
await prisma.permohonan_assign_forensik.delete({
where: {
assignID: assignID,
},
});
return { statusCode: 200, message: "Pegawai berjaya dipadamkan." };
} catch (error) {
return { statusCode: 500, message: "Error deleting forensic officer." };
}
});

View File

@ -0,0 +1,46 @@
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params;
const body = await readBody(event);
const { oldPegawaiID, newPegawaiID, assignID } = body;
try {
// Fetch the existing permohonan
const permohonan = await prisma.permohonan.findUnique({
where: { no_siri: noSiri },
});
if (!permohonan) {
return { statusCode: 404, message: "Permohonan tidak dijumpai." };
}
// Check if the new pegawai is already assigned
const existingAssignment =
await prisma.permohonan_assign_forensik.findFirst({
where: {
permohonanID: permohonan.id,
pegawai_forensikID: newPegawaiID,
},
});
console.log("existingAssignment", existingAssignment);
if (existingAssignment) {
return { statusCode: 400, message: "Pegawai baru sudah ditugaskan." };
}
// Update the old pegawai with the new pegawai
await prisma.permohonan_assign_forensik.update({
where: {
assignID: assignID,
},
data: {
pegawai_forensikID: newPegawaiID,
},
});
return { statusCode: 200, message: "Pegawai berjaya dikemaskini." };
} catch (error) {
console.log(error);
return { statusCode: 500, message: "Error updating forensic officer." };
}
});

View File

@ -0,0 +1,45 @@
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params;
try {
// Fetch the permohonan by noSiri
const permohonan = await prisma.permohonan.findUnique({
where: { no_siri: noSiri },
select: {
permohonan_assign_forensik: {
include: {
user: {
select: {
userID: true,
userFullName: true,
userUsername: true,
},
},
},
},
},
});
if (!permohonan) {
return { statusCode: 404, message: "Permohonan tidak dijumpai." };
}
// Return the list of assigned forensic officers
const forensicOfficers = permohonan.permohonan_assign_forensik.map(
(assignment) => ({
nama: assignment.user.userFullName,
tindakan: {
userID: assignment.user.userID,
assignID: assignment.assignID,
},
})
);
return {
statusCode: 200,
data: forensicOfficers,
};
} catch (error) {
return { statusCode: 500, message: "Error fetching forensic officers." };
}
});

View File

@ -0,0 +1,38 @@
// File: /api/permohonan/[noSiri]/reports.get.js
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params;
try {
const permohonan = await prisma.permohonan.findUnique({
where: { no_siri: noSiri },
select: {
report: {
include: {
lookup_report_jenis_barangTolookup: true, // To get the jenis barang lookup data
},
},
},
});
if (!permohonan) {
return { statusCode: 404, message: "Permohonan tidak dijumpai." };
}
// Map reports to the frontend format
const reports = permohonan.report.map((report) => ({
jenisBarang: report.lookup_report_jenis_barangTolookup.lookupValue,
tagNo: report.tanda_barang,
keadaan: report.keadaan_barang,
kuantiti: report.kuantiti_barang,
tindakan: report.reportID,
}));
return {
statusCode: 200,
data: reports,
};
} catch (error) {
return { statusCode: 500, message: "Error fetching reports." };
}
});

View File

@ -0,0 +1,61 @@
// File: /api/permohonan/[noSiri]/semak.put.js
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params;
const body = await readBody(event); // Get form data from frontend
try {
// Get the current user (assuming user authentication is handled)
const user = event.context.user;
// Find the permohonan by its noSiri
const permohonan = await prisma.permohonan.findUnique({
where: { no_siri: noSiri },
});
if (!permohonan) {
return { statusCode: 404, message: "Permohonan tidak dijumpai." };
}
// Update or create the permohonan semakan entry
await prisma.permohonan_semakan.upsert({
where: {
permohonanID: permohonan.id,
},
update: {
peralatan_keadaan_baik: body.peralatanBaik === "Ya" ? 1 : 0,
pegawai_berkelayakan: body.pegawaiBerkelayakan === "Ya" ? 1 : 0,
kaedah_dpt_dilakukan: body.kaedahDapatDilakukan === "Ya" ? 1 : 0,
subkontrak_diperlukan: body.subkontrakDiperlukan === "Ya" ? 1 : 0,
tugasan_diterima: body.tugasanDiterima === "Ya" ? 1 : 0,
ulasan_pegawai: body.ulasanPegawaiKaunter,
disemak_oleh: user.userID, // Use the authenticated user ID
create_at: new Date(),
},
create: {
permohonanID: permohonan.id,
peralatan_keadaan_baik: body.peralatanBaik === "Ya" ? 1 : 0,
pegawai_berkelayakan: body.pegawaiBerkelayakan === "Ya" ? 1 : 0,
kaedah_dpt_dilakukan: body.kaedahDapatDilakukan === "Ya" ? 1 : 0,
subkontrak_diperlukan: body.subkontrakDiperlukan === "Ya" ? 1 : 0,
tugasan_diterima: body.tugasanDiterima === "Ya" ? 1 : 0,
ulasan_pegawai: body.ulasanPegawaiKaunter,
disemak_oleh: user.userID,
create_at: new Date(),
},
});
// Update the status of the permohonan to "Permohonan Disemak"
await prisma.permohonan.update({
where: { no_siri: noSiri },
data: { status_permohonan: "Permohonan Disemak" },
});
return {
statusCode: 200,
message: "Maklumat semakan berjaya dikemaskini.",
};
} catch (error) {
console.error(error);
return { statusCode: 500, message: "Gagal mengemaskini maklumat semakan." };
}
});

View File

@ -0,0 +1,49 @@
export default defineEventHandler(async (event) => {
// Extract the `noSiri` from the URL params
const { noSiri } = event.context.params;
try {
// Fetch the Semakan status
const semakan = await prisma.permohonan_semakan.findFirst({
where: {
permohonan: {
no_siri: noSiri,
},
},
select: {
semakanID: true, // Checking if semakan exists
},
});
// Fetch the Penerimaan status
const penerimaan = await prisma.permohonan_penerimaan.findFirst({
where: {
permohonan: {
no_siri: noSiri,
},
},
select: {
penerimaanID: true, // Checking if penerimaan exists
},
});
// Determine statuses based on existence
const statusSemakan = semakan ? "Selesai" : "Belum Disemak";
const statusPenerimaan = penerimaan ? "Diterima" : "Belum Diterima";
// Return the statuses
return {
statusCode: 200,
data: {
statusSemakan,
statusPenerimaan,
},
};
} catch (error) {
// Return an error if something goes wrong
return {
statusCode: 500,
message: "Gagal mendapatkan status",
};
}
});

View File

@ -0,0 +1,64 @@
// File: /api/permohonan/[noSiri]/terima.put.js
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params;
const body = await readBody(event); // Get form data from frontend
try {
// Get the current user (assuming user authentication is handled)
const user = event.context.user;
// Find the permohonan by its noSiri
const permohonan = await prisma.permohonan.findUnique({
where: { no_siri: noSiri },
});
if (!permohonan) {
return { statusCode: 404, message: "Permohonan tidak dijumpai." };
}
// Create or update the permohonan penerimaan entry
await prisma.permohonan_penerimaan.upsert({
where: {
permohonanID: permohonan.id,
},
update: {
peralatan_keadaan_baik: body.peralatanBaik === "Ya" ? 1 : 0,
pegawai_berkelayakan: body.pegawaiBerkelayakan === "Ya" ? 1 : 0,
kaedah_dpt_dilakukan: body.kaedahDapatDilakukan === "Ya" ? 1 : 0,
subkontrak_diperlukan: body.subkontrakDiperlukan === "Ya" ? 1 : 0,
tugasan_diterima: body.tugasanDiterima === "Ya" ? 1 : 0,
ulasan_pegawai: body.ulasanPegawaiKaunter,
diterima_oleh: user.userID,
create_at: new Date(), // Store current date
},
create: {
permohonanID: permohonan.id,
peralatan_keadaan_baik: body.peralatanBaik === "Ya" ? 1 : 0,
pegawai_berkelayakan: body.pegawaiBerkelayakan === "Ya" ? 1 : 0,
kaedah_dpt_dilakukan: body.kaedahDapatDilakukan === "Ya" ? 1 : 0,
subkontrak_diperlukan: body.subkontrakDiperlukan === "Ya" ? 1 : 0,
tugasan_diterima: body.tugasanDiterima === "Ya" ? 1 : 0,
ulasan_pegawai: body.ulasanPegawaiKaunter,
diterima_oleh: user.userID,
create_at: new Date(),
},
});
// Update the status of the permohonan to "Diterima"
await prisma.permohonan.update({
where: { no_siri: noSiri },
data: { status_permohonan: "Permohonan Diterima" },
});
return {
statusCode: 200,
message: "Maklumat penerimaan berjaya dikemaskini.",
};
} catch (error) {
console.error(error);
return {
statusCode: 500,
message: "Gagal mengemaskini maklumat penerimaan.",
};
}
});

View File

@ -0,0 +1,56 @@
// File: /api/permohonan/[noSiri]/tolak.put.js
export default defineEventHandler(async (event) => {
const { noSiri } = event.context.params;
const body = await readBody(event); // Get form data from frontend
try {
// Get the current user (assuming user authentication is handled)
const user = event.context.user;
// Find the permohonan by its noSiri
const permohonan = await prisma.permohonan.findUnique({
where: { no_siri: noSiri },
});
if (!permohonan) {
return { statusCode: 404, message: "Permohonan tidak dijumpai." };
}
// Create or update the permohonan penolakan entry
await prisma.permohonan_penolakan.upsert({
where: {
permohonanID: permohonan.id,
},
update: {
sebab_penolakan: parseInt(body.sebabPenolakan), // Assuming lookupID is passed
lain_sebab: body.lainLainSebab || null,
ditolak_oleh: user.userID,
create_at: new Date(),
},
create: {
permohonanID: permohonan.id,
sebab_penolakan: parseInt(body.sebabPenolakan),
lain_sebab: body.lainLainSebab || null,
ditolak_oleh: user.userID,
create_at: new Date(),
},
});
// Update the status of the permohonan to "Permohonan Ditolak"
await prisma.permohonan.update({
where: { no_siri: noSiri },
data: { status_permohonan: "Permohonan Ditolak" },
});
return {
statusCode: 200,
message: "Maklumat penolakan berjaya dikemaskini.",
};
} catch (error) {
console.error(error);
return {
statusCode: 500,
message: "Gagal mengemaskini maklumat penolakan.",
};
}
});

View File

@ -119,22 +119,13 @@ export default defineEventHandler(async (event) => {
// Insert related `report` and `document` data
for (const barang of barangList) {
// await prisma.report.create({
// data: {
// permohonanID: newPermohonan.id,
// jenis_barang: barang.jenisBarangDetail,
// kuantiti_barang: barang.kuantitiBarang,
// tanda_barang: barang.tandaBarang,
// keadaan_barang: barang.keadaanBarang,
// create_by: userID,
// create_at: new Date(),
// },
// });
await prisma.report.create({
data: {
permohonanID: newPermohonan.id,
jenis_barang: barang.jenisBarangDetail,
kuantiti_barang: parseInt(barang.kuantitiBarang),
tanda_barang: barang.tandaBarang,
keadaan_barang: barang.keadaanBarang,
create_by: userID,
create_at: new Date(),
},

View File

@ -2,24 +2,38 @@
export default defineEventHandler(async () => {
try {
const permohonan = await prisma.permohonan.findMany({
where: {
status_permohonan: {
notIn: ["Permohonan Ditolak"],
},
},
select: {
id: true,
no_siri: true,
create_at: true,
status_permohonan: true,
},
orderBy: {
create_at: "desc",
},
});
return {
statusCode: 200,
message: "Success",
data: permohonan.map((item, index) => ({
no: index + 1,
noSiri: item.no_siri,
tarikhMasa: item.create_at.toISOString().replace("T", " ").slice(0, 19),
status: item.status_permohonan,
butiran: item.id,
})),
data: permohonan.map((item, index) => {
// Convert UTC to GMT+8
const gmt8Date = new Date(
item.create_at.getTime() + 8 * 60 * 60 * 1000
);
return {
no: index + 1,
noSiri: item.no_siri,
tarikhMasa: gmt8Date.toISOString().replace("T", " ").slice(0, 19),
status: item.status_permohonan,
butiran: item.id,
};
}),
};
} catch (error) {
return {