Update : fixed position on the left and right sides, can only scroll for the middle
This commit is contained in:
parent
d4c8e90670
commit
54e496355b
|
|
@ -23,7 +23,7 @@ import {
|
||||||
getQuestionsAllQueryOptions,
|
getQuestionsAllQueryOptions,
|
||||||
toggleFlagAnswer,
|
toggleFlagAnswer,
|
||||||
} from "@/modules/assessmentManagement/queries/assessmentQueries";
|
} 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 FinishAssessmentModal from "@/modules/assessmentManagement/modals/ConfirmModal";
|
||||||
import ValidationModal from "@/modules/assessmentManagement/modals/ValidationModal";
|
import ValidationModal from "@/modules/assessmentManagement/modals/ValidationModal";
|
||||||
import { useState, useRef, useEffect } from "react";
|
import { useState, useRef, useEffect } from "react";
|
||||||
|
|
@ -505,58 +505,63 @@ export default function AssessmentPage() {
|
||||||
|
|
||||||
{/* LEFT-SIDE */}
|
{/* LEFT-SIDE */}
|
||||||
{/* Aspek dan Sub-Aspek */}
|
{/* Aspek dan Sub-Aspek */}
|
||||||
<Flex direction="column" gap="xs" className="w-64">
|
<div className="fixed h-screen w-64 overflow-auto">
|
||||||
<div className="space-y-2">
|
<Flex direction="column" gap="xs" className="w-64">
|
||||||
{/* Aspek */}
|
<div className="space-y-2">
|
||||||
{aspectsQuery.data?.data
|
{/* Aspek */}
|
||||||
.filter((aspect) =>
|
{aspectsQuery.data?.data
|
||||||
aspect.subAspects.some((subAspect) =>
|
.filter((aspect) =>
|
||||||
data?.data.some((question) => question.subAspectId === subAspect.id)
|
aspect.subAspects.some((subAspect) =>
|
||||||
|
data?.data.some((question) => question.subAspectId === subAspect.id)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
.map((aspect) => (
|
||||||
.map((aspect) => (
|
|
||||||
<div
|
|
||||||
key={aspect.id}
|
|
||||||
className="p-2 "
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
className="flex justify-between cursor-pointer"
|
key={aspect.id}
|
||||||
onClick={() => toggleAspect(aspect.id)}
|
className="p-2 "
|
||||||
>
|
>
|
||||||
<div className="text-sm font-bold px-3">{aspect.name}</div>
|
<div
|
||||||
<div>
|
className="flex justify-between cursor-pointer"
|
||||||
{openAspects[aspect.id] ? (
|
onClick={() => toggleAspect(aspect.id)}
|
||||||
<TbChevronUp size={25} />
|
>
|
||||||
) : (
|
<div className="text-sm font-bold px-3">{aspect.name}</div>
|
||||||
<TbChevronRight size={25} />
|
<div>
|
||||||
)}
|
{openAspects[aspect.id] ? (
|
||||||
|
<TbChevronDown size={25} />
|
||||||
|
) : (
|
||||||
|
<TbChevronRight size={25} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</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>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Sub-Aspek */}
|
{/* MIDDLE */}
|
||||||
{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>
|
|
||||||
|
|
||||||
{/* Pertanyaan */}
|
{/* 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 }}>
|
<Stack gap="sm" style={{ flex: 1 }}>
|
||||||
<Text className="text-2xl font-bold ml-6">
|
<Text className="text-2xl font-bold ml-6">
|
||||||
Harap menjawab semua pertanyaan yang tersedia
|
Harap menjawab semua pertanyaan yang tersedia
|
||||||
|
|
@ -580,9 +585,9 @@ export default function AssessmentPage() {
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Flex justify="space-between" align="flex-start" style={{ width: "100%" }}>
|
<Flex justify="space-between" align="flex-start" style={{ width: "100%" }}>
|
||||||
{/* Question */}
|
{/* 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">
|
<div className="flex-grow">
|
||||||
<Text className="font-bold break-words text-sm">
|
<Text className="font-bold break-words text-sm p-1">
|
||||||
{question.questionText}
|
{question.questionText}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -703,7 +708,7 @@ export default function AssessmentPage() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="ml-6">
|
<div className="mx-11 px-1">
|
||||||
{uploadedFiles[question.questionId] && (
|
{uploadedFiles[question.questionId] && (
|
||||||
<Stack gap="sm" mt="sm">
|
<Stack gap="sm" mt="sm">
|
||||||
<Text className="font-bold">File yang diunggah:</Text>
|
<Text className="font-bold">File yang diunggah:</Text>
|
||||||
|
|
@ -728,93 +733,96 @@ export default function AssessmentPage() {
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* RIGHT-SIDE */}
|
||||||
{/* Navigasi dan Pagination */}
|
{/* 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) */}
|
{/* Navigasi (Number of Questions) */}
|
||||||
<div className="grid grid-cols-5 gap-2">
|
<div className="grid grid-cols-5 gap-2">
|
||||||
{filteredQuestions.map((question, index) => {
|
{filteredQuestions.map((question, index) => {
|
||||||
const questionId = question.questionId;
|
const questionId = question.questionId;
|
||||||
if (!questionId) return null;
|
if (!questionId) return null;
|
||||||
|
|
||||||
// Menentukan nomor soal berdasarkan indeks pertanyaan yang difilter
|
// Menentukan nomor soal berdasarkan indeks pertanyaan yang difilter
|
||||||
const questionNumber = index + 1; // Nomor pertanyaan dimulai dari 1
|
const questionNumber = index + 1; // Nomor pertanyaan dimulai dari 1
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={questionId} className="flex justify-center relative">
|
<div key={questionId} className="flex justify-center relative">
|
||||||
<button
|
<button
|
||||||
className={`w-9 h-9 border rounded-sm flex items-center justify-center relative text-md
|
className={`w-9 h-9 border rounded-sm flex items-center justify-center relative text-md
|
||||||
${flaggedQuestions[questionId] ? "text-black" : "bg-transparent text-black"}`}
|
${flaggedQuestions[questionId] ? "text-black" : "bg-transparent text-black"}`}
|
||||||
onClick={() => scrollToQuestion(questionId)}
|
onClick={() => scrollToQuestion(questionId)}
|
||||||
>
|
>
|
||||||
{questionNumber} {/* Menampilkan nomor pertanyaan yang sudah difilter */}
|
{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>
|
</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>
|
|
||||||
|
|
||||||
<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 */}
|
{/* Modal untuk konfirmasi selesai asesmen */}
|
||||||
<FinishAssessmentModal
|
<FinishAssessmentModal
|
||||||
|
|
@ -833,6 +841,7 @@ export default function AssessmentPage() {
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
</div>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Stack>
|
</Stack>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user