Pull Request branch dev-clone to main #1
|
|
@ -23,7 +23,7 @@ import {
|
|||
getQuestionsAllQueryOptions,
|
||||
toggleFlagAnswer,
|
||||
} from "@/modules/assessmentManagement/queries/assessmentQueries";
|
||||
import { TbFlagFilled, TbUpload, TbChevronRight, TbChevronUp } from "react-icons/tb";
|
||||
import { TbFlagFilled, TbUpload, TbChevronRight, TbChevronDown } from "react-icons/tb";
|
||||
import FinishAssessmentModal from "@/modules/assessmentManagement/modals/ConfirmModal";
|
||||
import ValidationModal from "@/modules/assessmentManagement/modals/ValidationModal";
|
||||
import { useState, useRef, useEffect } from "react";
|
||||
|
|
@ -505,58 +505,63 @@ export default function AssessmentPage() {
|
|||
|
||||
{/* LEFT-SIDE */}
|
||||
{/* Aspek dan Sub-Aspek */}
|
||||
<Flex direction="column" gap="xs" className="w-64">
|
||||
<div className="space-y-2">
|
||||
{/* Aspek */}
|
||||
{aspectsQuery.data?.data
|
||||
.filter((aspect) =>
|
||||
aspect.subAspects.some((subAspect) =>
|
||||
data?.data.some((question) => question.subAspectId === subAspect.id)
|
||||
<div className="fixed h-screen w-64 overflow-auto">
|
||||
<Flex direction="column" gap="xs" className="w-64">
|
||||
<div className="space-y-2">
|
||||
{/* Aspek */}
|
||||
{aspectsQuery.data?.data
|
||||
.filter((aspect) =>
|
||||
aspect.subAspects.some((subAspect) =>
|
||||
data?.data.some((question) => question.subAspectId === subAspect.id)
|
||||
)
|
||||
)
|
||||
)
|
||||
.map((aspect) => (
|
||||
<div
|
||||
key={aspect.id}
|
||||
className="p-2 "
|
||||
>
|
||||
.map((aspect) => (
|
||||
<div
|
||||
className="flex justify-between cursor-pointer"
|
||||
onClick={() => toggleAspect(aspect.id)}
|
||||
key={aspect.id}
|
||||
className="p-2 "
|
||||
>
|
||||
<div className="text-sm font-bold px-3">{aspect.name}</div>
|
||||
<div>
|
||||
{openAspects[aspect.id] ? (
|
||||
<TbChevronUp size={25} />
|
||||
) : (
|
||||
<TbChevronRight size={25} />
|
||||
)}
|
||||
<div
|
||||
className="flex justify-between cursor-pointer"
|
||||
onClick={() => toggleAspect(aspect.id)}
|
||||
>
|
||||
<div className="text-sm font-bold px-3">{aspect.name}</div>
|
||||
<div>
|
||||
{openAspects[aspect.id] ? (
|
||||
<TbChevronDown size={25} />
|
||||
) : (
|
||||
<TbChevronRight size={25} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Sub-Aspek */}
|
||||
{openAspects[aspect.id] && (
|
||||
<div className="mt-2 space-y-2">
|
||||
{aspect.subAspects
|
||||
.filter((subAspect) =>
|
||||
data?.data.some((question) => question.subAspectId === subAspect.id)
|
||||
)
|
||||
.map((subAspect) => (
|
||||
<div
|
||||
key={subAspect.id}
|
||||
className={`flex justify-between cursor-pointer p-2 px-6 rounded-sm transition-colors duration-150 ${selectedSubAspectId === subAspect.id ? 'text-black font-medium bg-gray-200' : 'text-gray-500'}`}
|
||||
onClick={() => setSelectedSubAspectId(subAspect.id)}
|
||||
>
|
||||
<div className="text-xs">{subAspect.name}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Flex>
|
||||
</div>
|
||||
|
||||
{/* Sub-Aspek */}
|
||||
{openAspects[aspect.id] && (
|
||||
<div className="mt-2 space-y-2">
|
||||
{aspect.subAspects
|
||||
.filter((subAspect) =>
|
||||
data?.data.some((question) => question.subAspectId === subAspect.id)
|
||||
)
|
||||
.map((subAspect) => (
|
||||
<div
|
||||
key={subAspect.id}
|
||||
className={`flex justify-between cursor-pointer p-2 px-6 rounded-sm transition-colors duration-150 ${selectedSubAspectId === subAspect.id ? 'text-black font-medium bg-gray-200' : 'text-gray-500'}`}
|
||||
onClick={() => setSelectedSubAspectId(subAspect.id)}
|
||||
>
|
||||
<div className="text-xs">{subAspect.name}</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Flex>
|
||||
|
||||
{/* MIDDLE */}
|
||||
{/* Pertanyaan */}
|
||||
{/* <div className="w-full ml-64"></div> */}
|
||||
<div className="ml-64 mr-72 flex-1 overflow-y-auto h-full">
|
||||
<Stack gap="sm" style={{ flex: 1 }}>
|
||||
<Text className="text-2xl font-bold ml-6">
|
||||
Harap menjawab semua pertanyaan yang tersedia
|
||||
|
|
@ -580,9 +585,9 @@ export default function AssessmentPage() {
|
|||
<Stack gap="sm">
|
||||
<Flex justify="space-between" align="flex-start" style={{ width: "100%" }}>
|
||||
{/* Question */}
|
||||
<Text className="font-bold mx-3 p-1">{startIndex + index + 1}.</Text>
|
||||
<Text className="font-bold mx-3 p-1 text-sm">{startIndex + index + 1}.</Text>
|
||||
<div className="flex-grow">
|
||||
<Text className="font-bold break-words text-sm">
|
||||
<Text className="font-bold break-words text-sm p-1">
|
||||
{question.questionText}
|
||||
</Text>
|
||||
</div>
|
||||
|
|
@ -703,7 +708,7 @@ export default function AssessmentPage() {
|
|||
)}
|
||||
</div>
|
||||
|
||||
<div className="ml-6">
|
||||
<div className="mx-11 px-1">
|
||||
{uploadedFiles[question.questionId] && (
|
||||
<Stack gap="sm" mt="sm">
|
||||
<Text className="font-bold">File yang diunggah:</Text>
|
||||
|
|
@ -728,93 +733,96 @@ export default function AssessmentPage() {
|
|||
})
|
||||
)}
|
||||
</Stack>
|
||||
</div>
|
||||
|
||||
{/* RIGHT-SIDE */}
|
||||
{/* Navigasi dan Pagination */}
|
||||
<Flex direction="column" gap="xs" className="mx-4">
|
||||
<div className="fixed h-screen right-0 w-72 overflow-auto mr-4">
|
||||
<Flex direction="column" gap="xs" className="mx-4">
|
||||
|
||||
{/* Navigasi (Number of Questions) */}
|
||||
<div className="grid grid-cols-5 gap-2">
|
||||
{filteredQuestions.map((question, index) => {
|
||||
const questionId = question.questionId;
|
||||
if (!questionId) return null;
|
||||
{/* Navigasi (Number of Questions) */}
|
||||
<div className="grid grid-cols-5 gap-2">
|
||||
{filteredQuestions.map((question, index) => {
|
||||
const questionId = question.questionId;
|
||||
if (!questionId) return null;
|
||||
|
||||
// Menentukan nomor soal berdasarkan indeks pertanyaan yang difilter
|
||||
const questionNumber = index + 1; // Nomor pertanyaan dimulai dari 1
|
||||
// Menentukan nomor soal berdasarkan indeks pertanyaan yang difilter
|
||||
const questionNumber = index + 1; // Nomor pertanyaan dimulai dari 1
|
||||
|
||||
return (
|
||||
<div key={questionId} className="flex justify-center relative">
|
||||
<button
|
||||
className={`w-9 h-9 border rounded-sm flex items-center justify-center relative text-md
|
||||
${flaggedQuestions[questionId] ? "text-black" : "bg-transparent text-black"}`}
|
||||
onClick={() => scrollToQuestion(questionId)}
|
||||
>
|
||||
{questionNumber} {/* Menampilkan nomor pertanyaan yang sudah difilter */}
|
||||
return (
|
||||
<div key={questionId} className="flex justify-center relative">
|
||||
<button
|
||||
className={`w-9 h-9 border rounded-sm flex items-center justify-center relative text-md
|
||||
${flaggedQuestions[questionId] ? "text-black" : "bg-transparent text-black"}`}
|
||||
onClick={() => scrollToQuestion(questionId)}
|
||||
>
|
||||
{questionNumber} {/* Menampilkan nomor pertanyaan yang sudah difilter */}
|
||||
</button>
|
||||
|
||||
{flaggedQuestions[questionId] && (
|
||||
<div className="absolute top-0 right-0 w-0 h-0 border-b-[20px] border-b-transparent border-r-[20px] border-r-black rounded-e-md" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex justify-center">
|
||||
<Pagination
|
||||
value={page}
|
||||
total={Math.ceil(totalQuestions / limit)}
|
||||
onChange={handlePageChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Skor Aspek dan Sub-Aspek */}
|
||||
<div className="mt-4">
|
||||
<Card shadow="sm" p="md" radius="md" withBorder>
|
||||
<Stack>
|
||||
{/* Skor Aspek */}
|
||||
<div>
|
||||
{filteredAspects.length > 0 ? (
|
||||
filteredAspects.map((aspect) => (
|
||||
<div key={aspect.aspectId} className="flex justify-between items-center">
|
||||
<Text className="text-base text-gray-400">{aspect.aspectName}</Text>
|
||||
<Text className="text-base font-bold">
|
||||
{parseFloat(aspect.averageScore).toFixed(2)}
|
||||
</Text>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<Text className="text-lg text-gray-400">Data aspek kosong</Text>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Garis pembatas */}
|
||||
<div>
|
||||
<hr className="border-t-2 border-gray-300 w-full mx-auto" />
|
||||
</div>
|
||||
|
||||
{/* Skor Sub-Aspek */}
|
||||
<div>
|
||||
{filteredSubAspects.length > 0 ? (
|
||||
filteredSubAspects.map((subAspect) => (
|
||||
<div key={subAspect.subAspectId} className="flex justify-between items-center"> {/* Change key to 'id' */}
|
||||
<Text className="text-sm text-gray-400">{subAspect.subAspectName}</Text> {/* Change to 'name' */}
|
||||
<Text className="text-sm font-bold">
|
||||
{parseFloat(subAspect.averageScore).toFixed(2)}
|
||||
</Text>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<Text className="text-lg text-gray-400">Data sub-aspek kosong</Text>
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
|
||||
{/* Tombol Selesai */}
|
||||
<div className="mt-6">
|
||||
<button onClick={handleFinishClick} className="bg-blue-500 text-white font-bold rounded-md py-2 w-full text-sm">
|
||||
Selesai
|
||||
</button>
|
||||
|
||||
{flaggedQuestions[questionId] && (
|
||||
<div className="absolute top-0 right-0 w-0 h-0 border-b-[20px] border-b-transparent border-r-[20px] border-r-black rounded-e-md" />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex justify-center">
|
||||
<Pagination
|
||||
value={page}
|
||||
total={Math.ceil(totalQuestions / limit)}
|
||||
onChange={handlePageChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Skor Aspek dan Sub-Aspek */}
|
||||
<div className="mt-4">
|
||||
<Card shadow="sm" p="md" radius="md" withBorder>
|
||||
<Stack>
|
||||
{/* Skor Aspek */}
|
||||
<div>
|
||||
{filteredAspects.length > 0 ? (
|
||||
filteredAspects.map((aspect) => (
|
||||
<div key={aspect.aspectId} className="flex justify-between items-center">
|
||||
<Text className="text-base text-gray-400">{aspect.aspectName}</Text>
|
||||
<Text className="text-base font-bold">
|
||||
{parseFloat(aspect.averageScore).toFixed(2)}
|
||||
</Text>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<Text className="text-lg text-gray-400">Data aspek kosong</Text>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Garis pembatas */}
|
||||
<div>
|
||||
<hr className="border-t-2 border-gray-300 w-full mx-auto" />
|
||||
</div>
|
||||
|
||||
{/* Skor Sub-Aspek */}
|
||||
<div>
|
||||
{filteredSubAspects.length > 0 ? (
|
||||
filteredSubAspects.map((subAspect) => (
|
||||
<div key={subAspect.subAspectId} className="flex justify-between items-center"> {/* Change key to 'id' */}
|
||||
<Text className="text-sm text-gray-400">{subAspect.subAspectName}</Text> {/* Change to 'name' */}
|
||||
<Text className="text-sm font-bold">
|
||||
{parseFloat(subAspect.averageScore).toFixed(2)}
|
||||
</Text>
|
||||
</div>
|
||||
))
|
||||
) : (
|
||||
<Text className="text-lg text-gray-400">Data sub-aspek kosong</Text>
|
||||
)}
|
||||
</div>
|
||||
</Stack>
|
||||
|
||||
{/* Tombol Selesai */}
|
||||
<div className="mt-6">
|
||||
<button onClick={handleFinishClick} className="bg-blue-500 text-white font-bold rounded-md py-2 w-full text-sm">
|
||||
Selesai
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Modal untuk konfirmasi selesai asesmen */}
|
||||
<FinishAssessmentModal
|
||||
|
|
@ -833,6 +841,7 @@ export default function AssessmentPage() {
|
|||
</Card>
|
||||
</div>
|
||||
</Flex>
|
||||
</div>
|
||||
</Flex>
|
||||
</Stack>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user