Done for 2
This commit is contained in:
parent
efdd28afbd
commit
654020e8a8
@ -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>
|
||||
|
@ -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: {},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
|
116
pages/pengesanan-penyamaran/baru/index.vue
Normal file
116
pages/pengesanan-penyamaran/baru/index.vue
Normal 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>
|
293
pages/pengesanan-penyamaran/kemaskini/[kesID]/index.vue
Normal file
293
pages/pengesanan-penyamaran/kemaskini/[kesID]/index.vue
Normal 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>
|
152
pages/pengesanan-penyamaran/senarai/index.vue
Normal file
152
pages/pengesanan-penyamaran/senarai/index.vue
Normal 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>
|
@ -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")
|
||||
}
|
||||
|
34
server/api/temujanji/[temujanjiID].delete.js
Normal file
34
server/api/temujanji/[temujanjiID].delete.js
Normal 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 };
|
||||
}
|
||||
});
|
64
server/api/temujanji/[temujanjiID].get.js
Normal file
64
server/api/temujanji/[temujanjiID].get.js
Normal 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.",
|
||||
};
|
||||
}
|
||||
});
|
58
server/api/temujanji/[temujanjiID].put.js
Normal file
58
server/api/temujanji/[temujanjiID].put.js
Normal 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.",
|
||||
};
|
||||
}
|
||||
});
|
31
server/api/temujanji/index.get.js
Normal file
31
server/api/temujanji/index.get.js
Normal 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.",
|
||||
};
|
||||
}
|
||||
});
|
82
server/api/temujanji/tambah.js
Normal file
82
server/api/temujanji/tambah.js
Normal 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.");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user