diff --git a/apps/frontend/src/modules/assessmentRequestManagement/modals/ConfirmModal.tsx b/apps/frontend/src/modules/assessmentRequestManagement/modals/ConfirmModal.tsx new file mode 100644 index 0000000..3ef2248 --- /dev/null +++ b/apps/frontend/src/modules/assessmentRequestManagement/modals/ConfirmModal.tsx @@ -0,0 +1,34 @@ +import { Modal, Text, Flex } from "@mantine/core"; +import { Button } from "@/shadcn/components/ui/button"; + +interface StartAssessmentModalProps { + assessmentId: string; + isOpen: boolean; + onClose: () => void; + onConfirm: (assessmentId: string) => void; +} + +export default function StartAssessmentModal({ + assessmentId, + isOpen, + onClose, + onConfirm, +}: StartAssessmentModalProps) { + return ( + + Apakah Anda yakin ingin memulai asesmen ini? + + + + + + ); +} diff --git a/apps/frontend/src/modules/assessmentRequestManagement/modals/FormModal.tsx b/apps/frontend/src/modules/assessmentRequestManagement/modals/CreateAssessmentRequestModal.tsx similarity index 91% rename from apps/frontend/src/modules/assessmentRequestManagement/modals/FormModal.tsx rename to apps/frontend/src/modules/assessmentRequestManagement/modals/CreateAssessmentRequestModal.tsx index bb2442e..2f50a42 100644 --- a/apps/frontend/src/modules/assessmentRequestManagement/modals/FormModal.tsx +++ b/apps/frontend/src/modules/assessmentRequestManagement/modals/CreateAssessmentRequestModal.tsx @@ -25,9 +25,7 @@ import { assessmentRequestQueryOptions, createAssessmentRequest } from "../queri const routeApi = getRouteApi("/_dashboardLayout/assessmentRequest/"); export default function UserFormModal() { - /** - * DON'T CHANGE FOLLOWING: - */ + const queryClient = useQueryClient(); const navigate = routeApi.useNavigate(); @@ -38,16 +36,9 @@ export default function UserFormModal() { const formType = "create"; - /** - * CHANGE FOLLOWING: - */ - const userQuery = useQuery(assessmentRequestQueryOptions(0, 10)); - const modalTitle = - - Konfirmasi - + const modalTitle = Konfirmasi const form = useForm({ initialValues: { @@ -82,8 +73,9 @@ export default function UserFormModal() { return await createAssessmentRequest(options.data); } }, + // auto refresh after mutation onSuccess: () => { - // Ini akan memaksa react-query untuk mengambil data terbaru + // force a query-reaction to retrieve the latest data queryClient.invalidateQueries({ queryKey: ["assessmentRequest"] }); notifications.show({ @@ -91,7 +83,7 @@ export default function UserFormModal() { color: "green", }); - // Menutup modal + // close modal navigate({ search: {} }); }, onError: (error: unknown) => { @@ -111,6 +103,7 @@ export default function UserFormModal() { }, }); + // Handle submit form, mutate data to server and close modal after success const handleSubmit = async (values: typeof form.values) => { if (formType === "create") { @@ -142,7 +135,7 @@ export default function UserFormModal() { Apakah anda yakin ingin membuat Permohonan Asesmen Baru? - {/* Fields to display data will be sent */} + {/* Fields to display data will be sent but only respondentId */} {createInputComponents({ disableAll: mutation.isPending, readonlyAll: formType === "create", @@ -171,7 +164,7 @@ export default function UserFormModal() { })} {/* Buttons */} - + diff --git a/apps/frontend/src/routes/_dashboardLayout/assessmentRequest/index.lazy.tsx b/apps/frontend/src/routes/_dashboardLayout/assessmentRequest/index.lazy.tsx index 83a6a49..43141a1 100644 --- a/apps/frontend/src/routes/_dashboardLayout/assessmentRequest/index.lazy.tsx +++ b/apps/frontend/src/routes/_dashboardLayout/assessmentRequest/index.lazy.tsx @@ -1,11 +1,14 @@ +import { useState } from "react"; import { assessmentRequestQueryOptions } from "@/modules/assessmentRequestManagement/queries/assessmentRequestQueries"; import PageTemplate from "@/components/PageTemplate"; import { createLazyFileRoute } from "@tanstack/react-router"; -import FormModal from "@/modules/assessmentRequestManagement/modals/FormModal"; +import FormModal from "@/modules/assessmentRequestManagement/modals/CreateAssessmentRequestModal"; import ExtractQueryDataType from "@/types/ExtractQueryDataType"; import { createColumnHelper } from "@tanstack/react-table"; -import { Badge, Flex } from "@mantine/core"; +import { Flex } from "@mantine/core"; +import { Badge } from "@/shadcn/components/ui/badge"; import { Button } from "@/shadcn/components/ui/button"; +import StartAssessmentModal from "@/modules/assessmentRequestManagement/modals/ConfirmModal"; export const Route = createLazyFileRoute("/_dashboardLayout/assessmentRequest/")({ component: UsersPage, @@ -16,101 +19,137 @@ type DataType = ExtractQueryDataType; const columnHelper = createColumnHelper(); export default function UsersPage() { - - const handleStartAssessment = (assessmentId: string) => { - const userConfirmed = window.confirm("Apakah anda yakin untuk memulai asesmen?"); + const [modalOpen, setModalOpen] = useState(false); + const [selectedAssessmentId, setSelectedAssessmentId] = useState(null); + + /** + * Fungsi untuk membuka modal konfirmasi mulai asesmen + * @param {string} assessmentId ID asesmen yang akan di mulai + */ + const handleOpenModal = (assessmentId: string) => { + if (!assessmentId) { + console.error("Assessment ID is missing"); + return; + } - if (userConfirmed) { - // Redirect ke URL baru di tab baru - const assessmentUrl = `/assessment?id=${assessmentId}`; - window.open(assessmentUrl, "_blank"); - } + setSelectedAssessmentId(assessmentId); + setModalOpen(true); }; - + + /** + * Fungsi untuk membuka halaman asesmen di tab baru + * @param {string} assessmentId ID asesmen yang akan di buka + */ + const handleStartAssessment = (assessmentId: string) => { + // Redirect ke URL baru di tab baru + const assessmentUrl = `/assessment?id=${assessmentId}`; + window.open(assessmentUrl, "_blank"); + setModalOpen(false); + }; + + /** + * Fungsi untuk membuka halaman hasil asesmen berdasarkan ID yang valid + * Digunakan ketika tombol "Lihat Hasil" diklik + * @param {string} assessmentId ID asesmen yang akan di buka + */ + const handleViewResult = (assessmentId: string) => { + // Make sure assessmentId is valid and not null + if (!assessmentId) { + console.error("Assessment ID is missing"); + return; + } + const resultUrl = `/assessmentResult/${assessmentId}`; + window.location.href = resultUrl; + }; + + return ( - ]} - columnDefs={[ - columnHelper.display({ - header: "No", - cell: (props) => props.row.index + 1, - }), - columnHelper.display({ - header: "Tanggal", - cell: (props) => - props.row.original.createdAt - ? new Intl.DateTimeFormat("ID", { - year: "numeric", - month: "long", - day: "2-digit", - hour: "2-digit", - minute: "2-digit", - hour12: true, - }).format(new Date(props.row.original.createdAt)) - : 'N/A', - }), + <> + ]} + columnDefs={[ + columnHelper.display({ + header: "No", + cell: (props) => props.row.index + 1, + }), + columnHelper.display({ + header: "Tanggal", + cell: (props) => + props.row.original.createdAt + ? new Intl.DateTimeFormat("ID", { + year: "numeric", + month: "long", + day: "2-digit", + hour: "2-digit", + minute: "2-digit", + hour12: true, + }).format(new Date(props.row.original.createdAt)) + : 'N/A', + }), + columnHelper.display({ + header: "Status", + cell: (props) => { + const status = props.row.original.status; + switch (status) { + case "menunggu konfirmasi": + // return Menunggu Konfirmasi; + return Menunggu Konfirmasi; + case "diterima": + return Diterima; + case "ditolak": + return Ditolak; + case "selesai": + return Selesai; + default: + return Tidak diketahui; + } + }, + }), + columnHelper.display({ + header: "Actions", + cell: (props) => { + const status = props.row.original.status; + const assessmentId = props.row.original.id; // Retrieve the assessmentId from the data row - columnHelper.display({ - header: "Status", - cell: (props) => { - const status = props.row.original.status; - switch (status) { - case "menunggu konfirmasi": - return Menunggu Konfirmasi; - case "diterima": - return Diterima; - case "ditolak": - return Ditolak; - case "selesai": - return Selesai; - default: - return Tidak diketahui; - } - }, - }), - - columnHelper.display({ - header: "Aksi", - cell: (props) => { - const status = props.row.original.status; - const assessmentId = props.row.original.id; - - - return ( - - {status === "selesai" ? ( - <> + return ( + + {/* Button Create Assessment */} + {status === "selesai" ? ( - - - ) : status === "diterima" ? ( - <> + ) : status === "diterima" ? ( - - - ) : status === "menunggu konfirmasi" || status === "ditolak" ? ( - <> + ) : ( + )} + + {/* Button View Result */} + {status === "selesai" ? ( + + ) : ( - - ) : null} - - ); - }, - }), - ]} - /> + )} + + ); + }, + }), + ]} + /> + + {/* Modal Konfirmasi Start Asessment */} + {selectedAssessmentId && ( + setModalOpen(false)} + onConfirm={handleStartAssessment} + /> + )} + ); -} \ No newline at end of file +} diff --git a/apps/frontend/src/shadcn/components/ui/badge.tsx b/apps/frontend/src/shadcn/components/ui/badge.tsx index f000e3e..d6abc25 100644 --- a/apps/frontend/src/shadcn/components/ui/badge.tsx +++ b/apps/frontend/src/shadcn/components/ui/badge.tsx @@ -15,6 +15,12 @@ const badgeVariants = cva( destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80", outline: "text-foreground", + + // Custom variants for status + waiting: "border-transparent bg-yellow-500 text-white hover:bg-yellow-600", + accepted: "border-transparent bg-green-500 text-white hover:bg-green-600", + rejected: "border-transparent bg-red-500 text-white hover:bg-red-600", + completed: "border-transparent bg-blue-500 text-white hover:bg-blue-600", }, }, defaultVariants: { diff --git a/apps/frontend/src/shadcn/components/ui/button.tsx b/apps/frontend/src/shadcn/components/ui/button.tsx index 33ba732..d7a6de3 100644 --- a/apps/frontend/src/shadcn/components/ui/button.tsx +++ b/apps/frontend/src/shadcn/components/ui/button.tsx @@ -52,7 +52,7 @@ const Button = React.forwardRef( {...props} > {isLoading ? ( - // Tampilkan spinner saat loading + // Show spinner when loading ) : ( children )}