update: revision index.lazy for assessment
This commit is contained in:
parent
68a3bbd3cc
commit
086c1576b6
|
|
@ -22,7 +22,12 @@ import {
|
||||||
toggleFlagAnswer,
|
toggleFlagAnswer,
|
||||||
} from "@/modules/assessmentManagement/queries/assessmentQueries";
|
} from "@/modules/assessmentManagement/queries/assessmentQueries";
|
||||||
import { TbFlag, TbUpload, TbChevronRight, TbChevronUp } from "react-icons/tb";
|
import { TbFlag, TbUpload, TbChevronRight, TbChevronUp } from "react-icons/tb";
|
||||||
import { useState, useRef } from "react";
|
import { useState, useRef, useEffect } from "react";
|
||||||
|
|
||||||
|
const getQueryParam = (param: string) => {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
return urlParams.get(param);
|
||||||
|
};
|
||||||
|
|
||||||
export const Route = createLazyFileRoute("/_dashboardLayout/assessment/")({
|
export const Route = createLazyFileRoute("/_dashboardLayout/assessment/")({
|
||||||
component: AssessmentPage,
|
component: AssessmentPage,
|
||||||
|
|
@ -44,7 +49,7 @@ interface ToggleFlagResponse {
|
||||||
|
|
||||||
export default function AssessmentPage() {
|
export default function AssessmentPage() {
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const limit = 2;
|
const limit = 10;
|
||||||
const questionRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
|
const questionRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
|
||||||
const [files, setFiles] = useState<File[]>([]);
|
const [files, setFiles] = useState<File[]>([]);
|
||||||
const [dragActive, setDragActive] = useState(false);
|
const [dragActive, setDragActive] = useState(false);
|
||||||
|
|
@ -53,6 +58,20 @@ export default function AssessmentPage() {
|
||||||
}>({});
|
}>({});
|
||||||
const fileInputRef = useRef<HTMLInputElement>(null);
|
const fileInputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const [selectedSubAspectId, setSelectedSubAspectId] = useState<string | null>(null);
|
||||||
|
const [assessmentId, setAssessmentId] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const id = getQueryParam("id");
|
||||||
|
|
||||||
|
if (!id) {
|
||||||
|
// Handle if no ID found
|
||||||
|
setAssessmentId(null);
|
||||||
|
} else {
|
||||||
|
setAssessmentId(id);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
// Fetching questions data using useQuery
|
// Fetching questions data using useQuery
|
||||||
const { data, isLoading, isError, error } = useQuery(
|
const { data, isLoading, isError, error } = useQuery(
|
||||||
getQuestionsAllQueryOptions(page, limit)
|
getQuestionsAllQueryOptions(page, limit)
|
||||||
|
|
@ -74,15 +93,14 @@ export default function AssessmentPage() {
|
||||||
queryFn: fetchAspects,
|
queryFn: fetchAspects,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Fetch average scores
|
// Fetch average scores berdasarkan assessmentId yang diambil dari URL
|
||||||
const assessmentId = "aqduqcdc1mhnbz8zrpnmx9oj"; // Replace with actual assessment ID
|
|
||||||
const averageScoreQuery = useQuery(
|
const averageScoreQuery = useQuery(
|
||||||
getAverageScoreQueryOptions(assessmentId)
|
getAverageScoreQueryOptions(assessmentId || "")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Fetch average scores for sub-aspects
|
// Fetch average scores for sub-aspects
|
||||||
const averageScoreSubAspectQuery = useQuery(
|
const averageScoreSubAspectQuery = useQuery(
|
||||||
getAverageScoreSubAspectQueryOptions(assessmentId)
|
getAverageScoreSubAspectQueryOptions(assessmentId || "")
|
||||||
);
|
);
|
||||||
|
|
||||||
// Mutation function to toggle flag
|
// Mutation function to toggle flag
|
||||||
|
|
@ -106,6 +124,14 @@ export default function AssessmentPage() {
|
||||||
// Inside the AssessmentPage function:
|
// Inside the AssessmentPage function:
|
||||||
const submitAnswerMutation = useMutation(submitAnswerMutationOptions());
|
const submitAnswerMutation = useMutation(submitAnswerMutationOptions());
|
||||||
|
|
||||||
|
const handleAnswerChange = (optionId: string) => {
|
||||||
|
submitAnswerMutation.mutate({
|
||||||
|
optionId: optionId,
|
||||||
|
assessmentId: assessmentId || "",
|
||||||
|
validationInformation: "someValidationInfo", // Sesuaikan validasi yang relevan
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// Drag and Drop handlers
|
// Drag and Drop handlers
|
||||||
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
|
const handleDragOver = (event: React.DragEvent<HTMLDivElement>) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
@ -169,9 +195,24 @@ export default function AssessmentPage() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const totalQuestions = data?.data?.length || 0;
|
const totalQuestions = data?.data?.length || 0;
|
||||||
|
const totalPages = Math.ceil(totalQuestions / limit);
|
||||||
const averageScores = averageScoreQuery.data?.aspects;
|
const averageScores = averageScoreQuery.data?.aspects;
|
||||||
const averageScoresSubAspect = averageScoreSubAspectQuery.data?.subAspects;
|
const averageScoresSubAspect = averageScoreSubAspectQuery.data?.subAspects;
|
||||||
|
|
||||||
|
if (!assessmentId) {
|
||||||
|
return (
|
||||||
|
<Card shadow="sm" p="lg" radius="md" withBorder>
|
||||||
|
<Text color="red" className="text-center">
|
||||||
|
Error: Data Asesmen tidak ditemukan. Harap akses halaman melalui link yang valid.
|
||||||
|
</Text>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const startIndex = (page - 1) * limit;
|
||||||
|
const endIndex = startIndex + limit;
|
||||||
|
const paginatedQuestions = data?.data.slice(startIndex, endIndex) || [];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card shadow="sm" p="lg" radius="md" withBorder>
|
<Card shadow="sm" p="lg" radius="md" withBorder>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
|
|
@ -181,9 +222,49 @@ export default function AssessmentPage() {
|
||||||
<Text className="text-gray-400">Semua jawaban Anda akan ditinjau</Text>
|
<Text className="text-gray-400">Semua jawaban Anda akan ditinjau</Text>
|
||||||
|
|
||||||
<Flex justify="space-between" align="flex-start" mt="lg">
|
<Flex justify="space-between" align="flex-start" mt="lg">
|
||||||
|
|
||||||
|
{/* LEFT-SIDE */}
|
||||||
|
{/* Aspek dan Sub-Aspek */}
|
||||||
|
<Flex direction="column" gap="xs" className="mr-4">
|
||||||
|
<div className="space-y-4">
|
||||||
|
{aspectsQuery.data?.data.map((aspect) => (
|
||||||
|
<div
|
||||||
|
key={aspect.id}
|
||||||
|
className="p-4 bg-gray-50 rounded-lg shadow-md"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
className="flex justify-between cursor-pointer"
|
||||||
|
onClick={() => toggleAspect(aspect.id)}
|
||||||
|
>
|
||||||
|
<div className="text-lg text-gray-700">{aspect.name}</div>
|
||||||
|
<div>
|
||||||
|
{openAspects[aspect.id] ? (
|
||||||
|
<TbChevronUp size={25} />
|
||||||
|
) : (
|
||||||
|
<TbChevronRight size={25} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{openAspects[aspect.id] && (
|
||||||
|
<div className="mt-2 space-y-2">
|
||||||
|
{aspect.subAspects.map((subAspect) => (
|
||||||
|
<div
|
||||||
|
key={subAspect.id}
|
||||||
|
className="flex justify-between text-gray-600"
|
||||||
|
>
|
||||||
|
<div>{subAspect.name}</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</Flex>
|
||||||
{/* Pertanyaan */}
|
{/* Pertanyaan */}
|
||||||
<Stack gap="sm" style={{ flex: 1 }}>
|
<Stack gap="sm" style={{ flex: 1 }}>
|
||||||
{data?.data?.map((question: any, index: number) => {
|
{paginatedQuestions.map((question: any, index: number) => {
|
||||||
const questionId = question.questionId;
|
const questionId = question.questionId;
|
||||||
if (!questionId) return null;
|
if (!questionId) return null;
|
||||||
|
|
||||||
|
|
@ -211,7 +292,7 @@ export default function AssessmentPage() {
|
||||||
marginRight: "40px",
|
marginRight: "40px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{index + 1}. {question.questionText}
|
{startIndex + index + 1}. {question.questionText}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
|
|
@ -254,8 +335,11 @@ export default function AssessmentPage() {
|
||||||
onChange={() => {
|
onChange={() => {
|
||||||
submitAnswerMutation.mutate({
|
submitAnswerMutation.mutate({
|
||||||
optionId: option.optionId,
|
optionId: option.optionId,
|
||||||
assessmentId: "aqduqcdc1mhnbz8zrpnmx9oj",
|
assessmentId: assessmentId || "",
|
||||||
validationInformation: "jfjforjfocn",
|
validationInformation: JSON.stringify({
|
||||||
|
info: "jfjforjfocn",
|
||||||
|
questionId: question.questionId // Tambahkan questionId dalam validationInformation
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
|
@ -270,6 +354,7 @@ export default function AssessmentPage() {
|
||||||
<Textarea placeholder="Berikan keterangan terkait jawaban di atas" />
|
<Textarea placeholder="Berikan keterangan terkait jawaban di atas" />
|
||||||
|
|
||||||
{/* File Upload */}
|
{/* File Upload */}
|
||||||
|
{question.needFile === true && (
|
||||||
<div
|
<div
|
||||||
className={`pt-5 pb-5 pr-5 pl-2 border-2 border-dashed ${dragActive ? "bg-gray-100" : "bg-transparent"
|
className={`pt-5 pb-5 pr-5 pl-2 border-2 border-dashed ${dragActive ? "bg-gray-100" : "bg-transparent"
|
||||||
} shadow-lg`} // Tambah shadow-lg
|
} shadow-lg`} // Tambah shadow-lg
|
||||||
|
|
@ -301,6 +386,7 @@ export default function AssessmentPage() {
|
||||||
accept="image/png, image/jpeg, application/pdf"
|
accept="image/png, image/jpeg, application/pdf"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{files.length > 0 && (
|
{files.length > 0 && (
|
||||||
<Stack gap="sm" mt="sm">
|
<Stack gap="sm" mt="sm">
|
||||||
|
|
@ -325,10 +411,13 @@ export default function AssessmentPage() {
|
||||||
{/* Navigasi dan Pagination */}
|
{/* Navigasi dan Pagination */}
|
||||||
<Flex direction="column" gap="xs" className="ml-4">
|
<Flex direction="column" gap="xs" className="ml-4">
|
||||||
<div className="grid grid-cols-5 gap-2">
|
<div className="grid grid-cols-5 gap-2">
|
||||||
{Array.from({ length: totalQuestions }, (_, index) => {
|
{paginatedQuestions.map((question, index) => {
|
||||||
const questionId = data?.data[index]?.questionId;
|
const questionId = question.questionId;
|
||||||
if (!questionId) return null;
|
if (!questionId) return null;
|
||||||
|
|
||||||
|
// Menentukan nomor soal berdasarkan pagination
|
||||||
|
const questionNumber = startIndex + index + 1; // Sesuaikan nomor berdasarkan halaman
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={questionId} className="flex justify-center relative">
|
<div key={questionId} className="flex justify-center relative">
|
||||||
<button
|
<button
|
||||||
|
|
@ -336,7 +425,7 @@ export default function AssessmentPage() {
|
||||||
${flaggedQuestions[questionId] ? "text-black" : "bg-transparent text-black"}`}
|
${flaggedQuestions[questionId] ? "text-black" : "bg-transparent text-black"}`}
|
||||||
onClick={() => scrollToQuestion(questionId)}
|
onClick={() => scrollToQuestion(questionId)}
|
||||||
>
|
>
|
||||||
{index + 1}
|
{questionNumber}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{flaggedQuestions[questionId] && (
|
{flaggedQuestions[questionId] && (
|
||||||
|
|
@ -355,43 +444,6 @@ export default function AssessmentPage() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Aspek dan Sub-Aspek */}
|
|
||||||
<div className="space-y-4">
|
|
||||||
{aspectsQuery.data?.data.map((aspect) => (
|
|
||||||
<div
|
|
||||||
key={aspect.id}
|
|
||||||
className="p-4 bg-gray-50 rounded-lg shadow-md"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="flex justify-between cursor-pointer"
|
|
||||||
onClick={() => toggleAspect(aspect.id)}
|
|
||||||
>
|
|
||||||
<div className="text-lg text-gray-700">{aspect.name}</div>
|
|
||||||
<div>
|
|
||||||
{openAspects[aspect.id] ? (
|
|
||||||
<TbChevronUp size={25} />
|
|
||||||
) : (
|
|
||||||
<TbChevronRight size={25} />
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{openAspects[aspect.id] && (
|
|
||||||
<div className="mt-2 space-y-2">
|
|
||||||
{aspect.subAspects.map((subAspect) => (
|
|
||||||
<div
|
|
||||||
key={subAspect.id}
|
|
||||||
className="flex justify-between text-gray-600"
|
|
||||||
>
|
|
||||||
<div>{subAspect.name}</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Skor Aspek dan Sub-Aspek */}
|
{/* Skor Aspek dan Sub-Aspek */}
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<Card shadow="sm" p="md" radius="md" withBorder>
|
<Card shadow="sm" p="md" radius="md" withBorder>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user