Fix api and menu name
This commit is contained in:
parent
a37bba93fe
commit
8f4c7ad0b6
@ -1,82 +1,84 @@
|
|||||||
export default [
|
export default [
|
||||||
{
|
{
|
||||||
header: "Utama",
|
"header": "Utama",
|
||||||
description: "",
|
"description": "",
|
||||||
child: [
|
"child": [
|
||||||
{
|
{
|
||||||
title: "Dashboard",
|
"title": "Dashboard",
|
||||||
path: "/dashboard",
|
"path": "/dashboard",
|
||||||
icon: "ic:outline-dashboard",
|
"icon": "ic:outline-dashboard",
|
||||||
child: [],
|
"child": [],
|
||||||
meta: {},
|
"meta": {}
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
meta: {},
|
"meta": {}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
header: "Pentadbiran",
|
"header": "Pentadbiran",
|
||||||
description: "Urus aplikasi anda",
|
"description": "Urus aplikasi anda",
|
||||||
child: [
|
"child": [
|
||||||
{
|
{
|
||||||
title: "Konfigurasi",
|
"title": "Konfigurasi",
|
||||||
icon: "ic:outline-settings",
|
"icon": "ic:outline-settings",
|
||||||
child: [
|
"child": [
|
||||||
{
|
{
|
||||||
title: "Persekitaran",
|
"title": "Persekitaran",
|
||||||
path: "/devtool/config/environment",
|
"path": "/devtool/config/environment"
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Penyunting Menu",
|
"title": "Penyunting Menu",
|
||||||
icon: "ci:menu-alt-03",
|
"icon": "ci:menu-alt-03",
|
||||||
path: "/devtool/menu-editor",
|
"path": "/devtool/menu-editor",
|
||||||
child: [],
|
"child": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Urus Pengguna",
|
"title": "Urus Pengguna",
|
||||||
path: "/devtool/user-management",
|
"path": "/devtool/user-management",
|
||||||
icon: "ph:user-circle-gear",
|
"icon": "ph:user-circle-gear",
|
||||||
child: [
|
"child": [
|
||||||
{
|
{
|
||||||
title: "Senarai Pengguna",
|
"title": "Senarai Pengguna",
|
||||||
path: "/devtool/user-management/user",
|
"path": "/devtool/user-management/user",
|
||||||
icon: "",
|
"icon": "",
|
||||||
child: [],
|
"child": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Senarai Peranan",
|
"title": "Senarai Peranan",
|
||||||
path: "/devtool/user-management/role",
|
"path": "/devtool/user-management/role",
|
||||||
icon: "",
|
"icon": "",
|
||||||
child: [],
|
"child": []
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Kandungan",
|
"title": "Kandungan",
|
||||||
icon: "mdi:pencil-ruler",
|
"icon": "mdi:pencil-ruler",
|
||||||
child: [
|
"child": [
|
||||||
{
|
{
|
||||||
title: "Penyunting",
|
"title": "Penyunting",
|
||||||
path: "/devtool/content-editor",
|
"path": "/devtool/content-editor"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Templat",
|
"title": "Templat",
|
||||||
path: "/devtool/content-editor/template",
|
"path": "/devtool/content-editor/template"
|
||||||
},
|
}
|
||||||
],
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: "Penyunting API",
|
"title": "Penyunting API",
|
||||||
path: "/devtool/api-editor",
|
"path": "/devtool/api-editor",
|
||||||
icon: "material-symbols:api-rounded",
|
"icon": "material-symbols:api-rounded",
|
||||||
child: [],
|
"child": []
|
||||||
},
|
}
|
||||||
],
|
],
|
||||||
meta: {
|
"meta": {
|
||||||
auth: {
|
"auth": {
|
||||||
role: ["Developer"],
|
"role": [
|
||||||
},
|
"Developer"
|
||||||
},
|
]
|
||||||
},
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
@ -126,6 +126,16 @@ const openModalEdit = (menu) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const saveEditMenu = async () => {
|
const saveEditMenu = async () => {
|
||||||
|
// Check title regex to ensure no weird symbol only letters, numbers, spaces, underscores and dashes
|
||||||
|
if (!/^[a-zA-Z0-9\s_-]+$/.test(showModalEditForm.value.title)) {
|
||||||
|
nuxtApp.$swal.fire({
|
||||||
|
title: "Error",
|
||||||
|
text: "Title contains invalid characters. Only letters, numbers, spaces, underscores and dashes are allowed.",
|
||||||
|
icon: "error",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Clean the name and title ensure not spacing at the beginning or end
|
// Clean the name and title ensure not spacing at the beginning or end
|
||||||
showModalEditForm.value.title = showModalEditForm.value.title.trim();
|
showModalEditForm.value.title = showModalEditForm.value.title.trim();
|
||||||
showModalEditForm.value.name = showModalEditForm.value.name.trim();
|
showModalEditForm.value.name = showModalEditForm.value.name.trim();
|
||||||
@ -170,6 +180,16 @@ const openModalAdd = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const saveAddMenu = async () => {
|
const saveAddMenu = async () => {
|
||||||
|
// Check title regex to ensure no weird symbol only letters, numbers, spaces, underscores and dashes
|
||||||
|
if (!/^[a-zA-Z0-9\s_-]+$/.test(showModalAddForm.value.title)) {
|
||||||
|
nuxtApp.$swal.fire({
|
||||||
|
title: "Error",
|
||||||
|
text: "Title contains invalid characters. Only letters, numbers, spaces, underscores and dashes are allowed.",
|
||||||
|
icon: "error",
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Clean the name and title ensure not spacing at the beginning or end
|
// Clean the name and title ensure not spacing at the beginning or end
|
||||||
showModalAddForm.value.title = showModalAddForm.value.title.trim();
|
showModalAddForm.value.title = showModalAddForm.value.title.trim();
|
||||||
showModalAddForm.value.name = showModalAddForm.value.name.trim();
|
showModalAddForm.value.name = showModalAddForm.value.name.trim();
|
||||||
@ -642,11 +662,9 @@ watch(
|
|||||||
<FormKit
|
<FormKit
|
||||||
type="text"
|
type="text"
|
||||||
label="Title"
|
label="Title"
|
||||||
:validation="[['required'], ['matches', '/^[a-zA-Z0-9]+$/']]"
|
:validation="[['required']]"
|
||||||
:validation-messages="{
|
:validation-messages="{
|
||||||
required: 'Title is required',
|
required: 'Title is required',
|
||||||
matches:
|
|
||||||
'Title contains invalid characters. Only letters and numbers are allowed.',
|
|
||||||
}"
|
}"
|
||||||
v-model="showModalEditForm.title"
|
v-model="showModalEditForm.title"
|
||||||
/>
|
/>
|
||||||
@ -695,11 +713,9 @@ watch(
|
|||||||
<FormKit
|
<FormKit
|
||||||
type="text"
|
type="text"
|
||||||
label="Title"
|
label="Title"
|
||||||
:validation="[['required'], ['matches', '/^[a-zA-Z0-9]+$/']]"
|
:validation="[['required']]"
|
||||||
:validation-messages="{
|
:validation-messages="{
|
||||||
required: 'Title is required',
|
required: 'Title is required',
|
||||||
matches:
|
|
||||||
'Title contains invalid characters. Only letters and numbers are allowed.',
|
|
||||||
}"
|
}"
|
||||||
v-model="showModalAddForm.title"
|
v-model="showModalAddForm.title"
|
||||||
/>
|
/>
|
||||||
|
@ -43,6 +43,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
"textarea",
|
"textarea",
|
||||||
"submit",
|
"submit",
|
||||||
"button",
|
"button",
|
||||||
|
"mask",
|
||||||
|
"form",
|
||||||
];
|
];
|
||||||
|
|
||||||
// Find all FormKit components
|
// Find all FormKit components
|
||||||
@ -259,6 +261,28 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
// Validate template structure
|
// Validate template structure
|
||||||
const validateTemplateStructure = (code) => {
|
const validateTemplateStructure = (code) => {
|
||||||
|
// Add new validation for script tags inside template
|
||||||
|
const templateContent1 = code.match(
|
||||||
|
/<template>([\s\S]*)<\/template>/
|
||||||
|
)?.[1];
|
||||||
|
if (templateContent1) {
|
||||||
|
const scriptInTemplate = templateContent1.match(/<script\b[^>]*>/i);
|
||||||
|
if (scriptInTemplate) {
|
||||||
|
const lineNumber = templateContent1
|
||||||
|
.slice(0, scriptInTemplate.index)
|
||||||
|
.split("\n").length;
|
||||||
|
const column =
|
||||||
|
scriptInTemplate.index -
|
||||||
|
templateContent1.lastIndexOf("\n", scriptInTemplate.index);
|
||||||
|
|
||||||
|
throw {
|
||||||
|
message: "Script tags are not allowed inside template section",
|
||||||
|
line: lineNumber,
|
||||||
|
column: column,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Check for root level template and script tags
|
// Check for root level template and script tags
|
||||||
const rootTemplateCount = (
|
const rootTemplateCount = (
|
||||||
code.match(/^[\s\S]*<template>[\s\S]*<\/template>/g) || []
|
code.match(/^[\s\S]*<template>[\s\S]*<\/template>/g) || []
|
||||||
@ -274,28 +298,28 @@ export default defineEventHandler(async (event) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Extract template content for further validation
|
// Extract template content for further validation
|
||||||
const templateContent = code.match(
|
const templateContent2 = code.match(
|
||||||
/<template>([\s\S]*)<\/template>/
|
/<template>([\s\S]*)<\/template>/
|
||||||
)?.[1];
|
)?.[1];
|
||||||
if (templateContent) {
|
if (templateContent2) {
|
||||||
const tagStack = [];
|
const tagStack = [];
|
||||||
const tagRegex = /<\/?([a-zA-Z][a-zA-Z0-9:-]*)\s*([^>]*?)(\/?)>/g;
|
const tagRegex = /<\/?([a-zA-Z][a-zA-Z0-9:-]*)\s*([^>]*?)(\/?)>/g;
|
||||||
let match;
|
let match;
|
||||||
let lineNumber = 1;
|
let lineNumber = 1;
|
||||||
let lastIndex = 0;
|
let lastIndex = 0;
|
||||||
|
|
||||||
while ((match = tagRegex.exec(templateContent)) !== null) {
|
while ((match = tagRegex.exec(templateContent2)) !== null) {
|
||||||
const [fullTag, tagName, attributes, selfClosing] = match;
|
const [fullTag, tagName, attributes, selfClosing] = match;
|
||||||
|
|
||||||
// Calculate line number
|
// Calculate line number
|
||||||
lineNumber += (
|
lineNumber += (
|
||||||
templateContent.slice(lastIndex, match.index).match(/\n/g) || []
|
templateContent2.slice(lastIndex, match.index).match(/\n/g) || []
|
||||||
).length;
|
).length;
|
||||||
lastIndex = match.index;
|
lastIndex = match.index;
|
||||||
|
|
||||||
// Skip comments
|
// Skip comments
|
||||||
if (templateContent.slice(match.index).startsWith("<!--")) {
|
if (templateContent2.slice(match.index).startsWith("<!--")) {
|
||||||
const commentEnd = templateContent.indexOf("-->", match.index);
|
const commentEnd = templateContent2.indexOf("-->", match.index);
|
||||||
if (commentEnd !== -1) {
|
if (commentEnd !== -1) {
|
||||||
tagRegex.lastIndex = commentEnd + 3;
|
tagRegex.lastIndex = commentEnd + 3;
|
||||||
continue;
|
continue;
|
||||||
@ -307,7 +331,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
message: `Malformed tag found: ${fullTag}`,
|
message: `Malformed tag found: ${fullTag}`,
|
||||||
line: lineNumber,
|
line: lineNumber,
|
||||||
column:
|
column:
|
||||||
match.index - templateContent.lastIndexOf("\n", match.index),
|
match.index - templateContent2.lastIndexOf("\n", match.index),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -318,7 +342,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
name: tagName,
|
name: tagName,
|
||||||
line: lineNumber,
|
line: lineNumber,
|
||||||
column:
|
column:
|
||||||
match.index - templateContent.lastIndexOf("\n", match.index),
|
match.index - templateContent2.lastIndexOf("\n", match.index),
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (tagStack.length === 0) {
|
if (tagStack.length === 0) {
|
||||||
@ -326,7 +350,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
message: `Unexpected closing tag </${tagName}> found without matching opening tag`,
|
message: `Unexpected closing tag </${tagName}> found without matching opening tag`,
|
||||||
line: lineNumber,
|
line: lineNumber,
|
||||||
column:
|
column:
|
||||||
match.index - templateContent.lastIndexOf("\n", match.index),
|
match.index - templateContent2.lastIndexOf("\n", match.index),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +360,7 @@ export default defineEventHandler(async (event) => {
|
|||||||
message: `Mismatched tags: expected closing tag for "${lastTag.name}" but found "${tagName}"`,
|
message: `Mismatched tags: expected closing tag for "${lastTag.name}" but found "${tagName}"`,
|
||||||
line: lineNumber,
|
line: lineNumber,
|
||||||
column:
|
column:
|
||||||
match.index - templateContent.lastIndexOf("\n", match.index),
|
match.index - templateContent2.lastIndexOf("\n", match.index),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
tagStack.pop();
|
tagStack.pop();
|
||||||
|
@ -1,91 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
// Get the `noSiri` from the request parameters
|
|
||||||
const { noSiri } = event.context.params;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Fetch the permohonan by `no_siri` from the Prisma database
|
|
||||||
const permohonan = await prisma.permohonan.findUnique({
|
|
||||||
where: {
|
|
||||||
no_siri: noSiri, // Unique identifier for permohonan
|
|
||||||
},
|
|
||||||
include: {
|
|
||||||
// Include related fields if necessary
|
|
||||||
pemohon: {
|
|
||||||
select: {
|
|
||||||
user: {
|
|
||||||
select: {
|
|
||||||
userFullName: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pangkat_pemohon: true,
|
|
||||||
no_pegawai_pemohon: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
penghantar: true,
|
|
||||||
report: {
|
|
||||||
select: {
|
|
||||||
jenis_barang: true,
|
|
||||||
lookup_report_jenis_barangTolookup: {
|
|
||||||
select: {
|
|
||||||
lookupID: true,
|
|
||||||
lookupValue: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tanda_barang: true,
|
|
||||||
keadaan_barang: true,
|
|
||||||
kuantiti_barang: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// If no permohonan found, return a 404 response
|
|
||||||
if (!permohonan) {
|
|
||||||
return {
|
|
||||||
statusCode: 404,
|
|
||||||
message: `Permohonan with noSiri ${noSiri} not found`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
// Map and return the data as expected by the frontend
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
data: {
|
|
||||||
namaPemohon: permohonan.pemohon?.user?.userFullName || "", // Get namaPemohon from userID
|
|
||||||
pangkatPemohon: permohonan.pemohon?.pangkat_pemohon || "",
|
|
||||||
noPegawaiPemohon: permohonan.pemohon?.no_pegawai_pemohon || "",
|
|
||||||
namaPenghantar: permohonan.penghantar?.nama_penghantar || "",
|
|
||||||
pangkatPenghantar: permohonan.penghantar?.pangkat_penghantar || "",
|
|
||||||
noPegawaiPenghantar: permohonan.penghantar?.no_pegawai_penghantar || "",
|
|
||||||
ringkasanKenyataanKes: permohonan.ringkasan_kenyataan_kes || "",
|
|
||||||
bilangan: permohonan.bilangan || 0,
|
|
||||||
barangList: permohonan.report.map((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,
|
|
||||||
})),
|
|
||||||
noKertasSiasatan: permohonan.no_kertas_siasatan || "",
|
|
||||||
noLaporanPolis: permohonan.no_laporan_polis || "",
|
|
||||||
tarikhTemujanji:
|
|
||||||
permohonan.tarikh_temujanji?.toISOString().split("T")[0] || "",
|
|
||||||
slotMasa: permohonan.slot_masa
|
|
||||||
? new Date(permohonan.slot_masa).toLocaleTimeString("en-US", {
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit",
|
|
||||||
hour12: false,
|
|
||||||
})
|
|
||||||
: "",
|
|
||||||
isPenghantarSameAsPemohon: !permohonan.penghantar,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching permohonan:", error);
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "An error occurred while fetching the permohonan data.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,54 +0,0 @@
|
|||||||
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.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,103 +0,0 @@
|
|||||||
// 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 };
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,63 +0,0 @@
|
|||||||
// 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" };
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,57 +0,0 @@
|
|||||||
// 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
|
|
||||||
|
|
||||||
if (!type) {
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
message: "Lookup type is required",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
const lookups = await prisma.lookup.findMany({
|
|
||||||
where: {
|
|
||||||
lookupTitle: type,
|
|
||||||
lookupStatus: "ACTIVE",
|
|
||||||
},
|
|
||||||
select: {
|
|
||||||
lookupID: true,
|
|
||||||
lookupTitle: true,
|
|
||||||
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: `Sila Pilih ${defaultTitle}`, value: null }, // Add an empty option as the first item
|
|
||||||
...lookups.map((lookup) => ({
|
|
||||||
label: lookup.lookupValue,
|
|
||||||
value: lookup.lookupID,
|
|
||||||
})),
|
|
||||||
];
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
data: transformedLookups,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Error fetching lookup data",
|
|
||||||
error: error.message,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,56 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const { noSiri } = event.context.params; // Get the noSiri from the request parameters
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Find the permohonan by its `no_siri`
|
|
||||||
const permohonan = await prisma.permohonan.findUnique({
|
|
||||||
where: { no_siri: noSiri },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!permohonan) {
|
|
||||||
return {
|
|
||||||
statusCode: 404,
|
|
||||||
message: `Permohonan with noSiri ${noSiri} not found.`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Delete pemohonan
|
|
||||||
await prisma.pemohon.delete({
|
|
||||||
where: {
|
|
||||||
id: permohonan.pemohonID,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete penghantar
|
|
||||||
await prisma.penghantar.delete({
|
|
||||||
where: {
|
|
||||||
id: permohonan.penghantarID,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete report
|
|
||||||
await prisma.report.deleteMany({
|
|
||||||
where: {
|
|
||||||
permohonanID: permohonan.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete permohonan
|
|
||||||
await prisma.permohonan.delete({
|
|
||||||
where: {
|
|
||||||
id: permohonan.id,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
message: "Permohonan and related data successfully deleted.",
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error deleting permohonan:", error);
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Failed to delete permohonan. Please try again.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,93 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
// Get the `noSiri` from the request parameters
|
|
||||||
const { noSiri } = event.context.params;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Fetch the permohonan by `no_siri` from the Prisma database
|
|
||||||
const permohonan = await prisma.permohonan.findUnique({
|
|
||||||
where: {
|
|
||||||
no_siri: noSiri, // Unique identifier for permohonan
|
|
||||||
},
|
|
||||||
include: {
|
|
||||||
// Include related fields if necessary
|
|
||||||
pemohon: {
|
|
||||||
select: {
|
|
||||||
user: {
|
|
||||||
select: {
|
|
||||||
userFullName: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
pangkat_pemohon: true,
|
|
||||||
no_pegawai_pemohon: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
penghantar: true,
|
|
||||||
report: {
|
|
||||||
select: {
|
|
||||||
jenis_barang: true,
|
|
||||||
lookup_report_jenis_barangTolookup: {
|
|
||||||
select: {
|
|
||||||
lookupID: true,
|
|
||||||
lookupValue: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tanda_barang: true,
|
|
||||||
keadaan_barang: true,
|
|
||||||
kuantiti_barang: true,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// If no permohonan found, return a 404 response
|
|
||||||
if (!permohonan) {
|
|
||||||
return {
|
|
||||||
statusCode: 404,
|
|
||||||
message: `Permohonan with noSiri ${noSiri} not found`,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map and return the data as expected by the frontend
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
data: {
|
|
||||||
namaPemohon: permohonan.pemohon?.user?.userFullName || "", // Get namaPemohon from userID
|
|
||||||
pangkatPemohon: permohonan.pemohon?.pangkat_pemohon || "",
|
|
||||||
noPegawaiPemohon: permohonan.pemohon?.no_pegawai_pemohon || "",
|
|
||||||
namaPenghantar: permohonan.penghantar?.nama_penghantar || "",
|
|
||||||
pangkatPenghantar: permohonan.penghantar?.pangkat_penghantar || "",
|
|
||||||
noPegawaiPenghantar: permohonan.penghantar?.no_pegawai_penghantar || "",
|
|
||||||
ringkasanKenyataanKes: permohonan.ringkasan_kenyataan_kes || "",
|
|
||||||
bilangan: permohonan.bilangan || 0,
|
|
||||||
barangList: permohonan.report.map((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,
|
|
||||||
})),
|
|
||||||
noKertasSiasatan: permohonan.no_kertas_siasatan || "",
|
|
||||||
noLaporanPolis: permohonan.no_laporan_polis || "",
|
|
||||||
tarikhTemujanji:
|
|
||||||
permohonan.tarikh_temujanji?.toISOString().split("T")[0] || "",
|
|
||||||
slotMasa: permohonan.slot_masa
|
|
||||||
? new Date(permohonan.slot_masa).toLocaleTimeString("en-US", {
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit",
|
|
||||||
hour12: false,
|
|
||||||
})
|
|
||||||
: "",
|
|
||||||
isPenghantarSameAsPemohon: !permohonan.penghantar,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
// Handle any unexpected errors
|
|
||||||
console.error("Error fetching permohonan:", error);
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Something went wrong while fetching permohonan data",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,202 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const body = await readBody(event);
|
|
||||||
const { userID } = event.context.user;
|
|
||||||
const { noSiri } = event.context.params; // Permohonan identifier from URL
|
|
||||||
|
|
||||||
const {
|
|
||||||
namaPemohon,
|
|
||||||
pangkatPemohon,
|
|
||||||
noPegawaiPemohon,
|
|
||||||
namaPenghantar,
|
|
||||||
pangkatPenghantar,
|
|
||||||
noPegawaiPenghantar,
|
|
||||||
ringkasanKenyataanKes,
|
|
||||||
isPenghantarSameAsPemohon,
|
|
||||||
bilangan,
|
|
||||||
barangList,
|
|
||||||
noKertasSiasatan,
|
|
||||||
noLaporanPolis,
|
|
||||||
tarikhTemujanji,
|
|
||||||
slotMasa,
|
|
||||||
isDraft,
|
|
||||||
} = body;
|
|
||||||
|
|
||||||
// 1. Mandatory fields validation
|
|
||||||
const mandatoryFields = [
|
|
||||||
namaPemohon,
|
|
||||||
pangkatPemohon,
|
|
||||||
noPegawaiPemohon,
|
|
||||||
ringkasanKenyataanKes,
|
|
||||||
bilangan,
|
|
||||||
noKertasSiasatan,
|
|
||||||
noLaporanPolis,
|
|
||||||
tarikhTemujanji,
|
|
||||||
slotMasa,
|
|
||||||
...barangList,
|
|
||||||
];
|
|
||||||
|
|
||||||
if (mandatoryFields.some((field) => !field || field === "")) {
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
message:
|
|
||||||
"Setiap medan mandatori yang bertanda * telah diisi. (Ralat CMN-E001)",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Validate date for the appointment
|
|
||||||
const appointmentDate = new Date(tarikhTemujanji);
|
|
||||||
const currentDate = new Date();
|
|
||||||
|
|
||||||
if (appointmentDate <= currentDate) {
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
message:
|
|
||||||
"Perlu memastikan tarikh janji temu yang dimasukkan adalah tarikh selepas tarikh semasa. (Ralat CMN-E002)",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Check if the session is expired
|
|
||||||
const sessionExpired = false; // Implement session logic here
|
|
||||||
if (sessionExpired) {
|
|
||||||
return {
|
|
||||||
statusCode: 401,
|
|
||||||
message:
|
|
||||||
"Sesi aktif pengguna berada dalam sistem telah tamat. (Ralat CMN-E005)",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Check for invalid symbols in text fields
|
|
||||||
const hasInvalidSymbols = (text) => /[^a-zA-Z0-9\s]/.test(text); // Allow alphanumeric and spaces
|
|
||||||
|
|
||||||
const fieldsToCheck = [
|
|
||||||
namaPemohon,
|
|
||||||
pangkatPemohon,
|
|
||||||
noPegawaiPemohon,
|
|
||||||
...barangList.map((barang) => barang.tandaBarang),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (fieldsToCheck.some((field) => hasInvalidSymbols(field))) {
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
message:
|
|
||||||
"Perlu memastikan tiada penggunaan simbol dalam medan yang ditetapkan. (Ralat CMN-E011)",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Update the permohonan in the database
|
|
||||||
let permohonanStatus = isDraft ? "Permohonan Draf" : "Permohonan Dihantar";
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Update the existing `permohonan` record
|
|
||||||
const updatedPermohonan = await prisma.permohonan.update({
|
|
||||||
where: {
|
|
||||||
no_siri: noSiri,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
status_permohonan: permohonanStatus,
|
|
||||||
pemohon: {
|
|
||||||
update: {
|
|
||||||
userID: userID,
|
|
||||||
pangkat_pemohon: pangkatPemohon,
|
|
||||||
no_pegawai_pemohon: noPegawaiPemohon,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
penghantar: isPenghantarSameAsPemohon
|
|
||||||
? null
|
|
||||||
: {
|
|
||||||
update: {
|
|
||||||
nama_penghantar: namaPenghantar,
|
|
||||||
pangkat_penghantar: pangkatPenghantar,
|
|
||||||
no_pegawai_penghantar: noPegawaiPenghantar,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ringkasan_kenyataan_kes: ringkasanKenyataanKes,
|
|
||||||
bilangan: parseInt(bilangan),
|
|
||||||
penghantar_sama_dengan_pemohon: isPenghantarSameAsPemohon ? 1 : 0,
|
|
||||||
no_kertas_siasatan: noKertasSiasatan,
|
|
||||||
no_laporan_polis: noLaporanPolis,
|
|
||||||
tarikh_temujanji: new Date(tarikhTemujanji),
|
|
||||||
slot_masa: new Date(`1970-01-01T${slotMasa}`),
|
|
||||||
modified_at: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete old barang and create new ones
|
|
||||||
await prisma.report.deleteMany({
|
|
||||||
where: { permohonanID: updatedPermohonan.id },
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const barang of barangList) {
|
|
||||||
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(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Send confirmation email if not a draft
|
|
||||||
if (!isDraft) {
|
|
||||||
await sendEmail({
|
|
||||||
to: [
|
|
||||||
/* pemohon, pegawai_kaunter, ketua_bahagian */
|
|
||||||
],
|
|
||||||
subject: `Kemaskini Permohonan: ${noSiri}`,
|
|
||||||
body: `
|
|
||||||
Case ID: ${noSiri}
|
|
||||||
Appointment Date: ${tarikhTemujanji}
|
|
||||||
Time Slot: ${slotMasa}
|
|
||||||
Barang: ${barangList
|
|
||||||
.map(
|
|
||||||
(barang) =>
|
|
||||||
`${barang.tandaBarang} - ${barang.kuantitiBarang} units`
|
|
||||||
)
|
|
||||||
.join(", ")}
|
|
||||||
Pemohon Details: ${namaPemohon} (${pangkatPemohon})
|
|
||||||
${
|
|
||||||
isPenghantarSameAsPemohon
|
|
||||||
? ""
|
|
||||||
: `Penghantar Details: ${namaPenghantar} (${pangkatPenghantar})`
|
|
||||||
}
|
|
||||||
Ringkasan Kenyataan Kes: ${ringkasanKenyataanKes}
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
message: isDraft
|
|
||||||
? "Rekod telah berjaya disimpan. (Status CMN-S001)"
|
|
||||||
: "Permohonan pemeriksaan forensik telah dikemaskini. (Status FOR-S001)",
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Terdapat masalah. Silakan cuba lagi.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Helper function to generate case reference number
|
|
||||||
const generateCaseReferenceID = () => {
|
|
||||||
const now = new Date();
|
|
||||||
const year = now.getFullYear().toString();
|
|
||||||
const month = String(now.getMonth() + 1).padStart(2, "0"); // JS month is zero-indexed
|
|
||||||
const day = String(now.getDate()).padStart(2, "0");
|
|
||||||
const uniqueSerial = String(Math.floor(Math.random() * 1000000)).padStart(
|
|
||||||
6,
|
|
||||||
"0"
|
|
||||||
);
|
|
||||||
return `${year}${month}${day}-${uniqueSerial}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendEmail = async ({ to, subject, body }) => {
|
|
||||||
console.log("Sending email to", to);
|
|
||||||
return true;
|
|
||||||
};
|
|
@ -1,42 +0,0 @@
|
|||||||
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." };
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,51 +0,0 @@
|
|||||||
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.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,27 +0,0 @@
|
|||||||
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." };
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,46 +0,0 @@
|
|||||||
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." };
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,45 +0,0 @@
|
|||||||
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." };
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,38 +0,0 @@
|
|||||||
// 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." };
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,61 +0,0 @@
|
|||||||
// 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." };
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,49 +0,0 @@
|
|||||||
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",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,64 +0,0 @@
|
|||||||
// 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.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,56 +0,0 @@
|
|||||||
// 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.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,194 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const body = await readBody(event);
|
|
||||||
const { userID } = event.context.user;
|
|
||||||
|
|
||||||
const {
|
|
||||||
namaPemohon,
|
|
||||||
pangkatPemohon,
|
|
||||||
noPegawaiPemohon,
|
|
||||||
namaPenghantar,
|
|
||||||
pangkatPenghantar,
|
|
||||||
noPegawaiPenghantar,
|
|
||||||
ringkasanKenyataanKes,
|
|
||||||
isPenghantarSameAsPemohon,
|
|
||||||
bilangan,
|
|
||||||
barangList,
|
|
||||||
noKertasSiasatan,
|
|
||||||
noLaporanPolis,
|
|
||||||
tarikhTemujanji,
|
|
||||||
slotMasa,
|
|
||||||
isDraft,
|
|
||||||
} = body;
|
|
||||||
|
|
||||||
// 1. Mandatory fields validation
|
|
||||||
const mandatoryFields = [
|
|
||||||
namaPemohon,
|
|
||||||
pangkatPemohon,
|
|
||||||
noPegawaiPemohon,
|
|
||||||
ringkasanKenyataanKes,
|
|
||||||
bilangan,
|
|
||||||
noKertasSiasatan,
|
|
||||||
noLaporanPolis,
|
|
||||||
tarikhTemujanji,
|
|
||||||
slotMasa,
|
|
||||||
...barangList,
|
|
||||||
];
|
|
||||||
|
|
||||||
if (mandatoryFields.some((field) => !field || field === "")) {
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
message:
|
|
||||||
"Setiap medan mandatori yang bertanda * telah diisi. (Ralat CMN-E001)",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Validate date for the appointment
|
|
||||||
const appointmentDate = new Date(tarikhTemujanji);
|
|
||||||
const currentDate = new Date();
|
|
||||||
|
|
||||||
if (appointmentDate <= currentDate) {
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
message:
|
|
||||||
"Perlu memastikan tarikh janji temu yang dimasukkan adalah tarikh selepas tarikh semasa. (Ralat CMN-E002)",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Check if the session is expired
|
|
||||||
const sessionExpired = false; // Implement session logic here
|
|
||||||
if (sessionExpired) {
|
|
||||||
return {
|
|
||||||
statusCode: 401,
|
|
||||||
message:
|
|
||||||
"Sesi aktif pengguna berada dalam sistem telah tamat. (Ralat CMN-E005)",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Check for invalid symbols in text fields
|
|
||||||
const hasInvalidSymbols = (text) => /[^a-zA-Z0-9\s]/.test(text); // Allow alphanumeric and spaces
|
|
||||||
|
|
||||||
const fieldsToCheck = [
|
|
||||||
namaPemohon,
|
|
||||||
pangkatPemohon,
|
|
||||||
noPegawaiPemohon,
|
|
||||||
...barangList.map((barang) => barang.tandaBarang),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (fieldsToCheck.some((field) => hasInvalidSymbols(field))) {
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
message:
|
|
||||||
"Perlu memastikan tiada penggunaan simbol dalam medan yang ditetapkan. (Ralat CMN-E011)",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// 5. Insert data into the database
|
|
||||||
const caseReferenceID = generateCaseReferenceID();
|
|
||||||
let permohonanStatus = isDraft ? "Permohonan Draf" : "Permohonan Dihantar";
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Insert into `permohonan` table
|
|
||||||
const newPermohonan = await prisma.permohonan.create({
|
|
||||||
data: {
|
|
||||||
no_siri: caseReferenceID,
|
|
||||||
status_permohonan: permohonanStatus,
|
|
||||||
pemohon: {
|
|
||||||
create: {
|
|
||||||
userID: userID, // Assuming the user is authenticated, replace with actual user ID
|
|
||||||
pangkat_pemohon: pangkatPemohon,
|
|
||||||
no_pegawai_pemohon: noPegawaiPemohon,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
penghantar: {
|
|
||||||
create: {
|
|
||||||
nama_penghantar: namaPenghantar,
|
|
||||||
pangkat_penghantar: pangkatPenghantar,
|
|
||||||
no_pegawai_penghantar: noPegawaiPenghantar,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
ringkasan_kenyataan_kes: ringkasanKenyataanKes,
|
|
||||||
bilangan: parseInt(bilangan),
|
|
||||||
penghantar_sama_dengan_pemohon: isPenghantarSameAsPemohon ? 1 : 0,
|
|
||||||
no_kertas_siasatan: noKertasSiasatan,
|
|
||||||
no_laporan_polis: noLaporanPolis,
|
|
||||||
tarikh_temujanji: new Date(tarikhTemujanji),
|
|
||||||
slot_masa: new Date(`1970-01-01T${slotMasa}`), // Convert slotMasa string to Time
|
|
||||||
create_at: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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: parseInt(barang.kuantitiBarang),
|
|
||||||
tanda_barang: barang.tandaBarang,
|
|
||||||
keadaan_barang: barang.keadaanBarang,
|
|
||||||
create_by: userID,
|
|
||||||
create_at: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 6. Send confirmation email
|
|
||||||
if (!isDraft) {
|
|
||||||
await sendEmail({
|
|
||||||
to: [
|
|
||||||
/* pemohon, pegawai_kaunter, ketua_bahagian */
|
|
||||||
],
|
|
||||||
subject: `Permohonan Baru: ${caseReferenceID}`,
|
|
||||||
body: `
|
|
||||||
Case ID: ${caseReferenceID}
|
|
||||||
Appointment Date: ${tarikhTemujanji}
|
|
||||||
Time Slot: ${slotMasa}
|
|
||||||
Barang: ${barangList
|
|
||||||
.map(
|
|
||||||
(barang) =>
|
|
||||||
`${barang.tandaBarang} - ${barang.kuantitiBarang} units`
|
|
||||||
)
|
|
||||||
.join(", ")}
|
|
||||||
Pemohon Details: ${namaPemohon} (${pangkatPemohon})
|
|
||||||
${
|
|
||||||
isPenghantarSameAsPemohon
|
|
||||||
? ""
|
|
||||||
: `Penghantar Details: ${namaPenghantar} (${pangkatPenghantar})`
|
|
||||||
}
|
|
||||||
Ringkasan Kenyataan Kes: ${ringkasanKenyataanKes}
|
|
||||||
`,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
message: isDraft
|
|
||||||
? "Rekod telah berjaya disimpan. (Status CMN-S001)"
|
|
||||||
: "Permohonan pemeriksaan forensik telah dihantar. (Status FOR-S001)",
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Terdapat masalah. Silakan cuba lagi.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Helper function to generate case reference number
|
|
||||||
const generateCaseReferenceID = () => {
|
|
||||||
const now = new Date();
|
|
||||||
const year = now.getFullYear().toString();
|
|
||||||
const month = String(now.getMonth() + 1).padStart(2, "0"); // JS month is zero-indexed
|
|
||||||
const day = String(now.getDate()).padStart(2, "0");
|
|
||||||
const uniqueSerial = String(Math.floor(Math.random() * 1000000)).padStart(
|
|
||||||
6,
|
|
||||||
"0"
|
|
||||||
);
|
|
||||||
return `${year}${month}${day}-${uniqueSerial}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const sendEmail = async ({ to, subject, body }) => {
|
|
||||||
console.log("Sending email to", to);
|
|
||||||
return true;
|
|
||||||
};
|
|
@ -1,44 +0,0 @@
|
|||||||
// File: server/api/permohonan/index.get.js
|
|
||||||
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) => {
|
|
||||||
// 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 {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Failed to fetch permohonan data.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,34 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const { temujanjiID } = event.context.params;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Check if temujanji_detail exists before deleting
|
|
||||||
const detailExists = await prisma.temujanji_detail.findFirst({
|
|
||||||
where: { temujanjiID: parseInt(temujanjiID) },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (detailExists) {
|
|
||||||
await prisma.temujanji_detail.deleteMany({
|
|
||||||
where: { temujanjiID: parseInt(temujanjiID) },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const pemohonExists = await prisma.pemohon.findFirst({
|
|
||||||
where: { temujanjiID: parseInt(temujanjiID) },
|
|
||||||
});
|
|
||||||
|
|
||||||
if (pemohonExists) {
|
|
||||||
await prisma.pemohon.delete({
|
|
||||||
where: { temujanjiID: parseInt(temujanjiID) },
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
await prisma.temujanji.delete({
|
|
||||||
where: { temujanjiID: parseInt(temujanjiID) },
|
|
||||||
});
|
|
||||||
|
|
||||||
return { statusCode: 200, message: "Berjaya" };
|
|
||||||
} catch (error) {
|
|
||||||
return { statusCode: 500, message: error.message };
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,64 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const { temujanjiID } = event.context.params;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Fetch the appointment data and related details from temujanji_detail
|
|
||||||
const appointment = await prisma.temujanji.findUnique({
|
|
||||||
where: { temujanjiID: parseInt(temujanjiID) },
|
|
||||||
include: {
|
|
||||||
pemohon: true, // Include pemohon (applicant) details
|
|
||||||
temujanji_detail: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(appointment);
|
|
||||||
|
|
||||||
if (!appointment) {
|
|
||||||
return {
|
|
||||||
statusCode: 404,
|
|
||||||
message: "Temujanji tidak dijumpai.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format the data to fit the front-end expectations
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
data: {
|
|
||||||
temujanjiID: appointment.temujanjiID,
|
|
||||||
jenisDokumen: appointment.temujanji_detail.jenisDokumen,
|
|
||||||
negara: appointment.temujanji_detail.negara,
|
|
||||||
namaPemilik: appointment.temujanji_detail.namaPemilik,
|
|
||||||
noDokumen: appointment.temujanji_detail.noDokumen,
|
|
||||||
kewarganegaraan: appointment.temujanji_detail.kewarganegaraan,
|
|
||||||
tarikhLahir: appointment.temujanji_detail.tarikhLahir,
|
|
||||||
jantina: appointment.temujanji_detail.jantina,
|
|
||||||
tarikhLuputDokumen: appointment.temujanji_detail.tarikhLuputDokumen,
|
|
||||||
skorPersamaanMuka: appointment.temujanji_detail.skorPersamaanMuka,
|
|
||||||
skorPersamaanCapJari: appointment.temujanji_detail.skorPersamaanCapJari,
|
|
||||||
umur: appointment.temujanji_detail.umur,
|
|
||||||
tinggi: appointment.temujanji_detail.tinggi,
|
|
||||||
warnaRambut: appointment.temujanji_detail.warnaRambut,
|
|
||||||
bangsa: appointment.temujanji_detail.bangsa,
|
|
||||||
etnik: appointment.temujanji_detail.etnik,
|
|
||||||
bentukKepala: appointment.temujanji_detail.bentukKepala,
|
|
||||||
mata: appointment.temujanji_detail.mata,
|
|
||||||
telinga: appointment.temujanji_detail.telinga,
|
|
||||||
hidung: appointment.temujanji_detail.hidung,
|
|
||||||
mulut: appointment.temujanji_detail.mulut,
|
|
||||||
parut: appointment.temujanji_detail.parut,
|
|
||||||
sejarahPerjalanan: appointment.temujanji_detail.sejarahPerjalanan,
|
|
||||||
persamaanTandaTangan: appointment.temujanji_detail.persamaanTandaTangan,
|
|
||||||
pemeriksaanLain: appointment.temujanji_detail.pemeriksaanLain,
|
|
||||||
dapatan: appointment.temujanji_detail.dapatan,
|
|
||||||
laporanSystemTdb:
|
|
||||||
appointment.temujanji_detail?.document?.documentURL || null,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error fetching temujanji:", error);
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Error fetching appointment data.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,101 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const { temujanjiID } = event.context.params;
|
|
||||||
const body = await readBody(event);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Get temujanji details ID
|
|
||||||
const temujanjiDetailsID = await prisma.temujanji.findFirst({
|
|
||||||
where: { temujanjiID: parseInt(temujanjiID) },
|
|
||||||
select: {
|
|
||||||
temujanjiID: true,
|
|
||||||
temujanjiDetailID: true,
|
|
||||||
noSiri: true,
|
|
||||||
jenisSemakan: true,
|
|
||||||
tarikh: true,
|
|
||||||
masa: true,
|
|
||||||
status: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(temujanjiDetailsID);
|
|
||||||
|
|
||||||
// Update the main `temujanji` table and related details in `temujanji_detail`
|
|
||||||
await prisma.temujanji_detail.update({
|
|
||||||
where: {
|
|
||||||
temujanjiDetailID: temujanjiDetailsID.temujanjiDetailID,
|
|
||||||
},
|
|
||||||
data: {
|
|
||||||
negara: body.negara,
|
|
||||||
namaPemilik: body.namaPemilik,
|
|
||||||
noDokumen: body.noDokumen,
|
|
||||||
kewarganegaraan: body.kewarganegaraan,
|
|
||||||
tarikhLahir: new Date(body.tarikhLahir),
|
|
||||||
jantina: body.jantina,
|
|
||||||
tarikhLuputDokumen: new Date(body.tarikhLuputDokumen),
|
|
||||||
skorPersamaanMuka: parseFloat(body.skorPersamaanMuka),
|
|
||||||
skorPersamaanCapJari: parseFloat(body.skorPersamaanCapJari),
|
|
||||||
umur: body.umur ? parseInt(body.umur) : null,
|
|
||||||
tinggi: body.tinggi ? parseFloat(body.tinggi) : null,
|
|
||||||
warnaRambut: body.warnaRambut || null,
|
|
||||||
bangsa: body.bangsa || null,
|
|
||||||
etnik: body.etnik || null,
|
|
||||||
bentukKepala: body.bentukKepala || null,
|
|
||||||
mata: body.mata || null,
|
|
||||||
telinga: body.telinga || null,
|
|
||||||
hidung: body.hidung || null,
|
|
||||||
mulut: body.mulut || null,
|
|
||||||
parut: body.parut || null,
|
|
||||||
sejarahPerjalanan: body.sejarahPerjalanan || null,
|
|
||||||
persamaanTandaTangan: body.persamaanTandaTangan || null,
|
|
||||||
pemeriksaanLain: body.pemeriksaanLain || null,
|
|
||||||
dapatan: body.dapatan,
|
|
||||||
modified_at: new Date(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// insert temujanji_log
|
|
||||||
await prisma.temujanji_log.create({
|
|
||||||
data: {
|
|
||||||
temujanjiID: parseInt(temujanjiID),
|
|
||||||
jenisSemakan: temujanjiDetailsID.jenisSemakan,
|
|
||||||
tarikh: temujanjiDetailsID.tarikh,
|
|
||||||
masa: temujanjiDetailsID.masa,
|
|
||||||
negara: body.negara,
|
|
||||||
namaPemilik: body.namaPemilik,
|
|
||||||
noDokumen: body.noDokumen,
|
|
||||||
kewarganegaraan: body.kewarganegaraan,
|
|
||||||
tarikhLahir: new Date(body.tarikhLahir),
|
|
||||||
jantina: body.jantina,
|
|
||||||
tarikhLuputDokumen: new Date(body.tarikhLuputDokumen),
|
|
||||||
skorPersamaanMuka: parseFloat(body.skorPersamaanMuka),
|
|
||||||
skorPersamaanCapJari: parseFloat(body.skorPersamaanCapJari),
|
|
||||||
umur: body.umur ? parseInt(body.umur) : null,
|
|
||||||
tinggi: body.tinggi ? parseFloat(body.tinggi) : null,
|
|
||||||
warnaRambut: body.warnaRambut || null,
|
|
||||||
bangsa: body.bangsa || null,
|
|
||||||
etnik: body.etnik || null,
|
|
||||||
bentukKepala: body.bentukKepala || null,
|
|
||||||
mata: body.mata || null,
|
|
||||||
telinga: body.telinga || null,
|
|
||||||
hidung: body.hidung || null,
|
|
||||||
mulut: body.mulut || null,
|
|
||||||
parut: body.parut || null,
|
|
||||||
sejarahPerjalanan: body.sejarahPerjalanan || null,
|
|
||||||
persamaanTandaTangan: body.persamaanTandaTangan || null,
|
|
||||||
pemeriksaanLain: body.pemeriksaanLain || null,
|
|
||||||
dapatan: body.dapatan,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
message: "Temujanji berjaya dikemaskini.",
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error updating temujanji:", error);
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Gagal mengemaskini temujanji.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,31 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
try {
|
|
||||||
const appointments = await prisma.temujanji.findMany({
|
|
||||||
include: {
|
|
||||||
pemohon: {
|
|
||||||
include: {
|
|
||||||
user: true,
|
|
||||||
},
|
|
||||||
}, // Join with pemohon table to get applicant details
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
data: appointments.map((appointment, index) => ({
|
|
||||||
no: index + 1,
|
|
||||||
kesId: appointment.temujanjiID,
|
|
||||||
namaPemohon: appointment.pemohon.user.userFullName,
|
|
||||||
caraSemakan: appointment.jenisSemakan,
|
|
||||||
status: appointment.status || "Pending",
|
|
||||||
tindakan: appointment.temujanjiID,
|
|
||||||
})),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.log(error);
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Failed to fetch appointments.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
@ -1,82 +0,0 @@
|
|||||||
export default defineEventHandler(async (event) => {
|
|
||||||
const body = await readBody(event);
|
|
||||||
const { userID } = event.context.user;
|
|
||||||
|
|
||||||
const { pemohon, jenisSemakan, tarikh, masa, gambarSubjek, gambarCapJari } =
|
|
||||||
body;
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Validate required fields
|
|
||||||
if (
|
|
||||||
!pemohon.nama ||
|
|
||||||
!pemohon.jawatan ||
|
|
||||||
!pemohon.noPegawai ||
|
|
||||||
!jenisSemakan ||
|
|
||||||
!tarikh ||
|
|
||||||
!masa
|
|
||||||
) {
|
|
||||||
return {
|
|
||||||
statusCode: 400,
|
|
||||||
message: "Sila isi semua medan yang diperlukan.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the appointment (temujanji) into the database using Prisma
|
|
||||||
const temujanjiBaru = await prisma.temujanji.create({
|
|
||||||
data: {
|
|
||||||
jenisSemakan: jenisSemakan,
|
|
||||||
tarikh: new Date(tarikh),
|
|
||||||
masa: new Date(`${tarikh}T${masa}:00`) ?? new Date(),
|
|
||||||
status: "Temujanji Diterima",
|
|
||||||
gambarSubjek: gambarSubjek
|
|
||||||
? await saveDocument(gambarSubjek, "Subjek")
|
|
||||||
: undefined,
|
|
||||||
gambarCapJari: gambarCapJari
|
|
||||||
? await saveDocument(gambarCapJari, "Cap Jari")
|
|
||||||
: undefined,
|
|
||||||
pemohon: {
|
|
||||||
create: {
|
|
||||||
userID: userID,
|
|
||||||
pangkat_pemohon: pemohon.jawatan,
|
|
||||||
no_pegawai_pemohon: pemohon.noPegawai,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
temujanji_detail: {
|
|
||||||
create: {
|
|
||||||
create_at: new Date(),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
statusCode: 200,
|
|
||||||
message: "Temujanji berjaya ditambah.",
|
|
||||||
data: temujanjiBaru,
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error adding appointment:", error);
|
|
||||||
return {
|
|
||||||
statusCode: 500,
|
|
||||||
message: "Terdapat ralat semasa menambah temujanji.",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Helper function to save uploaded documents to the database
|
|
||||||
async function saveDocument(file, fileType) {
|
|
||||||
try {
|
|
||||||
const savedDocument = await prisma.document.create({
|
|
||||||
data: {
|
|
||||||
name: file.name,
|
|
||||||
url: `/uploads/${file.name}`,
|
|
||||||
type: fileType,
|
|
||||||
size: file.size,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
return savedDocument.id;
|
|
||||||
} catch (error) {
|
|
||||||
console.error("Error saving document:", error);
|
|
||||||
throw new Error("Gagal menyimpan dokumen.");
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user