Done for 2

This commit is contained in:
Md Afiq Iskandar 2024-09-05 19:37:36 +08:00
parent efdd28afbd
commit 654020e8a8
11 changed files with 922 additions and 18 deletions

View File

@ -31,14 +31,14 @@ const redirectClearError = () => {
<div class="flex-1 text-center md:text-left items-center">
<span class="block mb-2 font-bold text-2xl md:text-3xl">Oops!</span>
<p class="text-lg md:text-xl font-base">
The page you are looking for does not exist.
Halaman yang anda cari tidak ada.
</p>
<button
@click="redirectClearError"
class="mt-5 w-fit rounded-lg flex justify-center items-center h-fit text-sm px-8 py-2.5 text-white bg-[#F3586A] hover:bg-[#F3586A]/90 disabled:bg-[#F3586A]/30 disabled:text-[#F3586A]/50 disabled:border-primary/5 disabled:cursor-default"
class="mt-5 w-fit rounded-lg flex justify-center items-center h-fit text-sm px-8 py-2.5 text-white bg-[#00A59A] hover:bg-[#00A59A]/90 disabled:bg-[#00A59A]/30 disabled:text-[#00A59A]/50 disabled:border-primary/5 disabled:cursor-default"
>
Back to Home
Kembali ke halaman utama
</button>
</div>
</div>

View File

@ -27,6 +27,18 @@ export default [
// },
],
},
{
title: "FOR-02",
icon: "ph:number-circle-two-fill",
child: [
{
title: "Pengesanan Penyamaran",
path: "/pengesanan-penyamaran/senarai",
child: [],
meta: {},
},
],
},
],
},
{

View File

@ -0,0 +1,116 @@
<template>
<div>
<h1>Tambah Temujanji</h1>
<rs-card class="mt-4 p-4">
<FormKit type="form" :actions="false" @submit="submitForm">
<!-- Maklumat Pemohon (Auto-filled) -->
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<FormKit type="text" label="Nama Pemohon" v-model="pemohon.nama" />
<FormKit
type="text"
label="Jawatan Pemohon"
v-model="pemohon.jawatan"
/>
<FormKit
type="text"
label="No Pegawai Pemohon"
v-model="pemohon.noPegawai"
/>
</div>
<!-- Jenis Semakan Dropdown -->
<FormKit
type="select"
label="Jenis Semakan"
v-model="jenisSemakan"
:options="jenisSemakanOptions"
validation="required"
/>
<!-- Conditional fields based on jenisSemakan -->
<template v-if="jenisSemakan === 'Subjek Hadir'">
<FormKit type="file" label="Gambar Subjek" />
<FormKit type="file" label="Gambar Cap Jari" />
</template>
<template v-else-if="jenisSemakan === 'Hantar Gambar'">
<FormKit type="file" label="Gambar Subjek" validation="required" />
<FormKit type="file" label="Gambar Cap Jari" validation="required" />
</template>
<!-- Date field -->
<FormKit
type="date"
label="Tarikh"
v-model="tarikh"
validation="required|date"
/>
<!-- Time field -->
<FormKit
type="time"
label="Masa"
v-model="masa"
validation="required"
/>
<!-- Action Buttons -->
<div class="flex justify-end gap-2 mt-4">
<rs-button @click="goBack" variant="danger">Kembali</rs-button>
<rs-button btn-type="submit" variant="success">Hantar</rs-button>
</div>
</FormKit>
</rs-card>
</div>
</template>
<script setup>
const { $swal } = useNuxtApp();
const router = useRouter();
const pemohon = ref({
nama: "",
jawatan: "",
noPegawai: "",
});
const jenisSemakan = ref("Subjek Hadir");
const jenisSemakanOptions = ref([
{ label: "Subjek Hadir", value: "Subjek Hadir" },
{ label: "Hantar Gambar", value: "Hantar Gambar" },
]);
const tarikh = ref("");
const masa = ref("");
// Navigate back to the listing page
const goBack = () => {
router.back();
};
// Submit form function
const submitForm = async (formData) => {
try {
const response = await $fetch("/api/temujanji/tambah", {
method: "POST",
body: {
pemohon: pemohon.value,
jenisSemakan: jenisSemakan.value,
tarikh: tarikh.value,
masa: masa.value,
...formData,
},
});
if (response.statusCode === 200) {
$swal.fire("Berjaya!", response.message, "success");
router.push("/pengesanan-penyamaran/senarai");
} else {
throw new Error(response.message);
}
} catch (error) {
$swal.fire("Ralat!", error.message, "error");
}
};
</script>

View File

@ -0,0 +1,293 @@
<template>
<div>
<div class="flex justify-between items-center">
<h1>Kemaskini Maklumat Pengesanan Penyamaran</h1>
</div>
<rs-card class="mt-4 p-4">
<FormKit type="form" :actions="false" @submit="submitForm">
<!-- JENIS DOKUMEN -->
<FormKit
type="select"
label="Jenis Dokumen"
v-model="formData.jenisDokumen"
:options="jenisDokumenOptions"
validation="required"
/>
<!-- NEGARA -->
<FormKit
type="select"
label="Negara"
v-model="formData.negara"
:options="negaraOptions"
validation="required"
/>
<!-- NAMA PEMILIK -->
<FormKit
type="text"
label="Nama Pemilik"
v-model="formData.namaPemilik"
validation="required"
/>
<!-- NO DOKUMEN -->
<FormKit
type="text"
label="No Dokumen"
v-model="formData.noDokumen"
validation="required"
/>
<!-- KEWARGANEGARAAN -->
<FormKit
type="select"
label="Kewarganegaraan"
v-model="formData.kewarganegaraan"
:options="kewarganegaraanOptions"
validation="required"
/>
<!-- TARIKH LAHIR -->
<FormKit
type="date"
label="Tarikh Lahir"
v-model="formData.tarikhLahir"
validation="required|date"
/>
<!-- JANTINA -->
<FormKit
type="select"
label="Jantina"
v-model="formData.jantina"
:options="jantinaOptions"
validation="required"
/>
<!-- TARIKH LUPUT DOKUMEN -->
<FormKit
type="date"
label="Tarikh Luput Dokumen"
v-model="formData.tarikhLuputDokumen"
validation="required|date"
/>
<!-- SKOR PERSAMAAN MUKA -->
<FormKit
type="number"
label="Skor Persamaan Muka"
v-model="formData.skorPersamaanMuka"
validation="required|number|min_value:0|max_value:100"
step="0.01"
/>
<!-- SKOR PERSAMAAN CAP JARI -->
<FormKit
type="number"
label="Skor Persamaan Cap Jari"
v-model="formData.skorPersamaanCapJari"
validation="required|number|min_value:0|max_value:100"
step="0.01"
/>
<!-- OPTIONAL FIELDS -->
<FormKit type="number" label="Umur" v-model="formData.umur" />
<FormKit
type="number"
label="Tinggi (cm)"
v-model="formData.tinggi"
step="0.01"
/>
<FormKit
type="text"
label="Warna Rambut"
v-model="formData.warnaRambut"
/>
<FormKit type="text" label="Bangsa" v-model="formData.bangsa" />
<FormKit type="text" label="Etnik" v-model="formData.etnik" />
<FormKit
type="text"
label="Bentuk Kepala"
v-model="formData.bentukKepala"
/>
<FormKit type="text" label="Mata" v-model="formData.mata" />
<FormKit type="text" label="Telinga" v-model="formData.telinga" />
<FormKit type="text" label="Hidung" v-model="formData.hidung" />
<FormKit type="text" label="Mulut" v-model="formData.mulut" />
<FormKit
type="text"
label="Parut, Tahi Lalat, Tatu, dsb."
v-model="formData.parut"
/>
<FormKit
type="text"
label="Sejarah Perjalanan"
v-model="formData.sejarahPerjalanan"
/>
<FormKit
type="text"
label="Persamaan Tanda Tangan"
v-model="formData.persamaanTandaTangan"
/>
<FormKit
type="text"
label="Pemeriksaan Lain"
v-model="formData.pemeriksaanLain"
/>
<!-- DAPATAN -->
<FormKit
type="select"
label="Dapatan"
v-model="formData.dapatan"
:options="dapatanOptions"
validation="required"
/>
<!-- LAPORAN SYSTEM TD&B -->
<FormKit
type="file"
label="Laporan Sistem TD&B (JPG/PDF)"
validation="file|mimes:pdf,jpg"
/>
<!-- Action Buttons -->
<div class="flex justify-end gap-2 mt-4">
<rs-button @click="goBack" variant="danger">Kembali</rs-button>
<rs-button btn-type="submit" variant="success">Kemaskini</rs-button>
</div>
</FormKit>
</rs-card>
</div>
</template>
<script setup>
const { $swal } = useNuxtApp();
const router = useRouter();
const route = useRoute();
const kesID = ref(route.params.kesID);
// Reactive variables for form data
const formData = ref({
jenisDokumen: "Passport",
negara: "Malaysia",
namaPemilik: "",
noDokumen: "",
kewarganegaraan: "Malaysia",
tarikhLahir: "",
jantina: "Lelaki",
tarikhLuputDokumen: "",
skorPersamaanMuka: 0,
skorPersamaanCapJari: 0,
umur: null,
tinggi: null,
warnaRambut: "",
bangsa: "",
etnik: "",
bentukKepala: "",
mata: "",
telinga: "",
hidung: "",
mulut: "",
parut: "",
sejarahPerjalanan: "",
persamaanTandaTangan: "",
pemeriksaanLain: "",
dapatan: "Sama",
});
// Dropdown options
const jenisDokumenOptions = ref([
{ label: "Passport", value: "Passport" },
{ label: "Kad Pengenalan", value: "Kad Pengenalan" },
]);
const negaraOptions = ref([
{ label: "Malaysia", value: "Malaysia" },
{ label: "Singapura", value: "Singapura" },
]);
const kewarganegaraanOptions = ref([
{ label: "Malaysia", value: "Malaysia" },
{ label: "Singapura", value: "Singapura" },
{ label: "Tiada", value: "Tiada" },
]);
const jantinaOptions = ref([
{ label: "Lelaki", value: "Lelaki" },
{ label: "Perempuan", value: "Perempuan" },
{ label: "Lain-lain", value: "Lain-lain" },
]);
const dapatanOptions = ref([
{ label: "Sama", value: "Sama" },
{ label: "Tidak Sama", value: "Tidak Sama" },
{ label: "Tidak Dapat Dikenalpasti", value: "Tidak Dapat Dikenalpasti" },
]);
const fetchAppointment = async (kesID) => {
try {
const response = await $fetch(`/api/temujanji/${kesID}`, {
method: "GET",
});
if (response.statusCode === 200) {
Object.assign(formData.value, response.data);
} else {
throw new Error("Failed to fetch appointment data.");
}
} catch (error) {
$swal.fire("Ralat!", error.message, "error");
}
};
onMounted(() => {
fetchAppointment(kesID.value);
});
// Submit the updated form data
const submitForm = async () => {
try {
const response = await $fetch(`/api/temujanji/${kesID.value}`, {
method: "PUT",
body: formData.value,
});
if (response.statusCode === 200) {
$swal.fire("Berjaya!", response.message, "success");
router.push("/pengesanan-penyamaran/senarai");
} else {
throw new Error(response.message);
}
} catch (error) {
$swal.fire("Ralat!", error.message, "error");
}
};
// Go back to the previous page
const goBack = () => {
router.back();
};
</script>
<style scoped>
form {
display: flex;
flex-direction: column;
gap: 1rem;
}
button {
padding: 0.5rem 1rem;
background-color: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #0056b3;
}
</style>

View File

@ -0,0 +1,152 @@
<template>
<div>
<!-- Header with title and "Add Appointment" button -->
<div class="flex justify-between items-center">
<h1>Senarai Temujanji</h1>
<rs-button @click="addAppointment" variant="primary" class="mt-2">
Tambah Temujanji
</rs-button>
</div>
<!-- Table displaying the list of appointments -->
<rs-card class="mt-4 py-2">
<rs-table
:data="tableData"
:options="{
variant: 'default',
striped: true,
borderless: true,
}"
:options-advanced="{
sortable: true,
filterable: false,
}"
advanced
>
<!-- Table Data Rows -->
<template v-slot:no="data">
{{ data.text }}
</template>
<template v-slot:kesId="data">
{{ data.text || "N/A" }}
</template>
<template v-slot:namaPemohon="data">
{{ data.text || "N/A" }}
</template>
<template v-slot:caraSemakan="data">
{{ data.text || "N/A" }}
</template>
<template v-slot:status="data">
<rs-badge
:variant="
data.text === 'Aktif' || data.text === 'Selesai'
? 'success'
: 'danger'
"
>
{{ data.text || "N/A" }}
</rs-badge>
</template>
<!-- Actions for each appointment -->
<template v-slot:tindakan="data">
<div class="flex gap-2">
<!-- Button to navigate to the "Update" page for the selected appointment -->
<rs-button
@click="updateAppointment(data.value.kesId)"
variant="primary"
size="sm"
class="p-1"
title="Kemaskini"
>
<Icon name="ic:baseline-edit" size="1.2rem" />
</rs-button>
<!-- Button to delete the selected appointment -->
<rs-button
@click="deleteAppointment(data.value.kesId)"
variant="danger"
size="sm"
class="p-1"
title="Hapus"
>
<Icon name="ic:baseline-delete" size="1.2rem" />
</rs-button>
</div>
</template>
</rs-table>
</rs-card>
</div>
</template>
<script setup>
const { $swal } = useNuxtApp();
// Reactive variable to store table data
const tableData = ref([]);
// Fetch appointment list from API
const fetchAppointments = async () => {
try {
const response = await useFetch("/api/temujanji");
if (response.data.value && response.data.value.statusCode === 200) {
tableData.value = response.data.value.data;
} else {
console.error(response.data.value.message);
}
} catch (error) {
console.error("Error fetching appointments:", error);
}
};
// Function to navigate to the "Add Appointment" page
const addAppointment = () => {
navigateTo("/pengesanan-penyamaran/baru");
};
// Function to navigate to the "Update Appointment" page
const updateAppointment = (kesId) => {
navigateTo(`/pengesanan-penyamaran/kemaskini/${kesId}`);
};
// Function to delete an appointment by its kesId
const deleteAppointment = async (kesId) => {
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 { data, error } = await useFetch(`/api/temujanji/${kesId}`, {
method: "DELETE",
});
if (data.value && data.value.statusCode === 200) {
// Remove the deleted appointment from tableData
await fetchAppointments();
$swal.fire("Dihapuskan!", data.value.message, "success");
} else {
$swal.fire(
"Error!",
error.value?.message || "Failed to delete appointment.",
"error"
);
}
} catch (error) {
$swal.fire("Error!", "Failed to delete appointment.", "error");
}
}
};
// Fetch the appointment list when the component is mounted
onMounted(() => {
fetchAppointments();
});
</script>

View File

@ -17,21 +17,24 @@ model audit {
}
model document {
documentID Int @id @default(autoincrement())
userID Int?
documentName String? @db.VarChar(255)
documentURL String? @db.VarChar(255)
documentType String? @db.VarChar(255)
documentExtension String? @db.VarChar(255)
imageMIMEType String? @db.VarChar(255)
documentSize Int?
documentStatus String? @default("ACTIVE") @db.VarChar(255)
documentCreatedDate String? @db.VarChar(255)
documentModifiedDate String? @db.VarChar(255)
user user? @relation(fields: [userID], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "document_ibfk_1")
permohonan_forensik_checking permohonan_forensik_checking[]
report report[]
report_doc_support report_doc_support[]
documentID Int @id @default(autoincrement())
userID Int?
documentName String? @db.VarChar(255)
documentURL String? @db.VarChar(255)
documentType String? @db.VarChar(255)
documentExtension String? @db.VarChar(255)
imageMIMEType String? @db.VarChar(255)
documentSize Int?
documentStatus String? @default("ACTIVE") @db.VarChar(255)
documentCreatedDate String? @db.VarChar(255)
documentModifiedDate String? @db.VarChar(255)
user user? @relation(fields: [userID], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "document_ibfk_1")
permohonan_forensik_checking permohonan_forensik_checking[]
report report[]
report_doc_support report_doc_support[]
temujanji_temujanji_gambarSubjekTodocument temujanji[] @relation("temujanji_gambarSubjekTodocument")
temujanji_temujanji_gambarCapJariTodocument temujanji[] @relation("temujanji_gambarCapJariTodocument")
temujanji_detail temujanji_detail[]
@@index([userID], map: "userID")
}
@ -69,6 +72,7 @@ model pemohon {
no_pegawai_pemohon String @db.VarChar(255)
user user @relation(fields: [userID], references: [userID], onDelete: NoAction, onUpdate: NoAction, map: "pemohon_ibfk_1")
permohonan permohonan[]
temujanji temujanji[]
@@index([userID], map: "userID")
}
@ -305,3 +309,61 @@ model report_doc_support {
@@index([documentID], map: "documentID")
@@index([reportID], map: "reportID")
}
model temujanji {
temujanjiID Int @id @default(autoincrement())
temujanjiDetailID Int?
pemohonID Int
jenisSemakan String @db.VarChar(255)
tarikh DateTime @db.Date
masa DateTime @db.Time(0)
status String? @db.VarChar(255)
gambarSubjek Int?
gambarCapJari Int?
create_at DateTime? @default(now()) @db.DateTime(0)
modified_at DateTime? @db.DateTime(0)
document_temujanji_gambarSubjekTodocument document? @relation("temujanji_gambarSubjekTodocument", fields: [gambarSubjek], references: [documentID], onDelete: NoAction, onUpdate: NoAction, map: "fk_gambarSubjek")
document_temujanji_gambarCapJariTodocument document? @relation("temujanji_gambarCapJariTodocument", fields: [gambarCapJari], references: [documentID], onDelete: NoAction, onUpdate: NoAction, map: "fk_gambarCapJari")
pemohon pemohon @relation(fields: [pemohonID], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "temujanji_ibfk_1")
temujanji_detail temujanji_detail? @relation(fields: [temujanjiDetailID], references: [temujanjiDetailID], onDelete: NoAction, onUpdate: NoAction, map: "temujanji_ibfk_4")
@@index([gambarCapJari], map: "idx_gambarCapJari")
@@index([gambarSubjek], map: "idx_gambarSubjek")
@@index([pemohonID], map: "idx_pemohonID")
@@index([temujanjiDetailID], map: "temujanjiDetailID")
}
model temujanji_detail {
temujanjiDetailID Int @id @default(autoincrement())
negara String? @db.VarChar(255)
namaPemilik String? @db.VarChar(255)
noDokumen String? @db.VarChar(255)
kewarganegaraan String? @db.VarChar(255)
tarikhLahir DateTime? @db.Date
jantina String? @db.VarChar(255)
tarikhLuputDokumen DateTime? @db.Date
skorPersamaanMuka Decimal? @db.Decimal(10, 2)
skorPersamaanCapJari Decimal? @db.Decimal(10, 2)
umur Int?
tinggi Decimal? @db.Decimal(10, 2)
warnaRambut String? @db.VarChar(255)
bangsa String? @db.VarChar(255)
etnik String? @db.VarChar(255)
bentukKepala String? @db.VarChar(255)
mata String? @db.VarChar(255)
telinga String? @db.VarChar(255)
hidung String? @db.VarChar(255)
mulut String? @db.VarChar(255)
parut String? @db.VarChar(255)
sejarahPerjalanan String? @db.VarChar(255)
persamaanTandaTangan String? @db.VarChar(255)
pemeriksaanLain String? @db.VarChar(255)
dapatan String @db.VarChar(255)
laporanSystemTdb Int?
create_at DateTime? @db.DateTime(0)
modified_at DateTime? @db.DateTime(0)
temujanji temujanji[]
document document? @relation(fields: [laporanSystemTdb], references: [documentID], onDelete: NoAction, onUpdate: NoAction, map: "temujanji_detail_ibfk_2")
@@index([laporanSystemTdb], map: "idx_laporanSystemTdb")
}

View File

@ -0,0 +1,34 @@
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 };
}
});

View File

@ -0,0 +1,64 @@
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.",
};
}
});

View File

@ -0,0 +1,58 @@
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_detail.findFirst({
where: { temujanjiID: parseInt(temujanjiID) },
});
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(),
},
});
return {
statusCode: 200,
message: "Temujanji berjaya dikemaskini.",
};
} catch (error) {
console.error("Error updating temujanji:", error);
return {
statusCode: 500,
message: "Gagal mengemaskini temujanji.",
};
}
});

View File

@ -0,0 +1,31 @@
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.",
};
}
});

View File

@ -0,0 +1,82 @@
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`),
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.");
}
}