update: pagination for assessment when choose aspect on sidebar, and update card using shadcn

This commit is contained in:
abiyasa05 2024-10-31 11:30:07 +07:00
parent c7e9a7e9af
commit a9d8fed683

View File

@ -1,8 +1,6 @@
import { createLazyFileRoute } from "@tanstack/react-router"; import { createLazyFileRoute } from "@tanstack/react-router";
import { import {
Card,
Flex, Flex,
// Pagination,
Stack, Stack,
Text, Text,
Loader, Loader,
@ -10,6 +8,12 @@ import {
CloseButton, CloseButton,
Group, Group,
} from "@mantine/core"; } from "@mantine/core";
import {
Card,
CardContent,
CardDescription,
CardHeader,
} from "@/shadcn/components/ui/card";
import { Textarea } from "@/shadcn/components/ui/textarea"; import { Textarea } from "@/shadcn/components/ui/textarea";
import { Label } from "@/shadcn/components/ui/label"; import { Label } from "@/shadcn/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/shadcn/components/ui/radio-group"; import { RadioGroup, RadioGroupItem } from "@/shadcn/components/ui/radio-group";
@ -77,6 +81,9 @@ export default function AssessmentPage() {
const [unansweredQuestions, setUnansweredQuestions] = useState(0); const [unansweredQuestions, setUnansweredQuestions] = useState(0);
const [validationModalOpen, setValidationModalOpen] = useState(false); const [validationModalOpen, setValidationModalOpen] = useState(false);
const [exceededFileName, setExceededFileName] = useState(""); const [exceededFileName, setExceededFileName] = useState("");
const [currentPagePerSubAspect, setCurrentPagePerSubAspect] = useState<{ [subAspectId: string]: number }>({});
const currentPage = currentPagePerSubAspect[selectedSubAspectId || ""] || 1;
const questionsPerPage = 10;
// Fetch aspects and sub-aspects // Fetch aspects and sub-aspects
const aspectsQuery = useQuery({ const aspectsQuery = useQuery({
@ -511,11 +518,6 @@ export default function AssessmentPage() {
} }
}; };
// Handle pagination
const handlePageChange = (newPage: number) => {
setPage(newPage);
};
// Render conditions // Render conditions
if (isLoading) { if (isLoading) {
return <Loader />; return <Loader />;
@ -529,26 +531,43 @@ export default function AssessmentPage() {
); );
} }
const totalQuestions = data?.data?.length || 0;
const totalPages = Math.ceil(totalQuestions / limit);
if (!assessmentId) { if (!assessmentId) {
return ( return (
<Card shadow="sm" p="lg" radius="md" withBorder> <Card>
<Text color="red" className="text-center"> <CardContent>
Error: Data Asesmen tidak ditemukan. Harap akses halaman melalui link yang valid. <Text color="red" className="text-center">
</Text> Error: Data Asesmen tidak ditemukan. Harap akses halaman melalui link yang valid.
</Text>
</CardContent>
</Card> </Card>
); );
} }
const startIndex = (page - 1) * limit; const startIndex = (page - 1) * limit;
const endIndex = startIndex + limit;
const paginatedQuestions = data?.data.slice(startIndex, endIndex) || [];
const filteredQuestions = paginatedQuestions.filter((question) => { // Fungsi untuk mengubah halaman pada sub-aspek
return question.subAspectId === selectedSubAspectId; // Misalnya, jika `question` memiliki `subAspectId` const handlePageChange = (subAspectId: string, newPage: number) => {
}); setCurrentPagePerSubAspect((prev) => ({
...prev,
[subAspectId]: newPage,
}));
};
// Filter pertanyaan berdasarkan halaman saat ini
const filteredQuestions = data?.data?.filter((question) => {
// Filter berdasarkan sub-aspek yang dipilih
return question.subAspectId === selectedSubAspectId;
})?.slice(
(currentPage - 1) * questionsPerPage,
currentPage * questionsPerPage
) || [];
// Perbarui jumlah halaman untuk sub-aspek saat ini
const totalQuestionsInSubAspect = data?.data?.filter(
(question) => question.subAspectId === selectedSubAspectId
)?.length || 0;
const totalPages = Math.ceil(totalQuestionsInSubAspect / questionsPerPage);
return ( return (
<div> <div>
@ -793,9 +812,9 @@ export default function AssessmentPage() {
{/* Navigasi dan Pagination */} {/* Navigasi dan Pagination */}
<div className="fixed h-screen right-0 w-60 overflow-auto mr-4"> <div className="fixed h-screen right-0 w-60 overflow-auto mr-4">
<Flex direction="column" gap="xs" className="mx-4"> <Flex direction="column" gap="xs" className="mx-4">
<Text className="font-medium text-lg text-gray-800 mb-2"> <Text className="font-medium text-lg text-gray-800 mb-2">
Nomor Soal Nomor Soal
</Text> </Text>
{/* Navigasi (Number of Questions) */} {/* Navigasi (Number of Questions) */}
<div className="grid grid-cols-5 gap-2"> <div className="grid grid-cols-5 gap-2">
@ -828,17 +847,28 @@ export default function AssessmentPage() {
</div> </div>
<div className="mt-4 flex justify-center"> <div className="mt-4 flex justify-center">
<Pagination page={page} totalPages={totalPages} onPageChange={handlePageChange}> <Pagination
<Text className="text-xs m-0">Halaman {page} dari {totalPages}</Text> page={currentPage}
totalPages={totalPages}
onPageChange={(newPage) => {
if (selectedSubAspectId) {
handlePageChange(selectedSubAspectId, newPage);
}
}}
>
<Text className="text-xs m-0">Halaman {currentPage} dari {totalPages}</Text>
</Pagination> </Pagination>
</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>
<Stack> <CardHeader>
{/* Skor Aspek */} <Text className="font-extrabold text-center">Nilai Sementara</Text>
<div> </CardHeader>
<CardContent>
<CardDescription>
{filteredAspects.length > 0 ? ( {filteredAspects.length > 0 ? (
filteredAspects.map((aspect) => { filteredAspects.map((aspect) => {
const aspectScore = parseFloat(aspect.averageScore).toFixed(2); const aspectScore = parseFloat(aspect.averageScore).toFixed(2);
@ -868,71 +898,70 @@ export default function AssessmentPage() {
) : ( ) : (
<Text className="text-base text-gray-400">Data aspek ini kosong</Text> <Text className="text-base text-gray-400">Data aspek ini kosong</Text>
)} )}
</div> </CardDescription>
{/* Garis pembatas */} {/* Garis pembatas */}
<div> <div className="border-t-2 border-gray-300 my-4" />
<hr className="border-t-2 border-gray-300 w-full mx-auto" />
</div>
{/* Skor Sub-Aspek */} {/* Skor Sub-Aspek */}
<div> {filteredSubAspects.length > 0 ? (
{filteredSubAspects.length > 0 ? ( filteredSubAspects.map((subAspect) => {
filteredSubAspects.map((subAspect) => { const subAspectScore = parseFloat(subAspect.averageScore).toFixed(2);
const subAspectScore = parseFloat(subAspect.averageScore).toFixed(2); const subAspectScoreValue = parseFloat(subAspectScore);
const subAspectScoreValue = parseFloat(subAspectScore);
return ( return (
<div key={subAspect.subAspectId} className="flex justify-between items-center"> <div key={subAspect.subAspectId} className="flex justify-between items-center">
<Text className="text-sm text-gray-400">{subAspect.subAspectName}</Text> <Text className="text-sm text-gray-400">{subAspect.subAspectName}</Text>
<Text <Text
className={`text-sm font-bold ${ className={`text-sm font-bold ${
subAspectScoreValue >= 4.01 subAspectScoreValue >= 4.01
? "text-green-700" ? "text-green-700"
: subAspectScoreValue >= 3.01 : subAspectScoreValue >= 3.01
? "text-green-400" ? "text-green-400"
: subAspectScoreValue >= 2.01 : subAspectScoreValue >= 2.01
? "text-yellow-400" ? "text-yellow-400"
: subAspectScoreValue >= 1.01 : subAspectScoreValue >= 1.01
? "text-orange-500" ? "text-orange-500"
: "text-red-500" : "text-red-500"
}`} }`}
> >
{subAspectScore} {subAspectScore}
</Text> </Text>
</div> </div>
); );
}) })
) : ( ) : (
<Text className="text-sm text-gray-400">Data sub-aspek ini kosong</Text> <Text className="text-sm text-gray-400">Data sub-aspek ini kosong</Text>
)} )}
</div> </CardContent>
</Stack>
{/* Tombol Selesai */} {/* Tombol Selesai */}
<div className="mt-6"> <div className="mt-4 mb-4 ml-4 mr-4">
<button onClick={handleFinishClick} className="bg-blue-500 text-white font-bold rounded-md py-2 w-full text-sm"> <button
onClick={handleFinishClick}
className="bg-blue-500 text-white font-bold rounded-md py-2 w-full text-sm"
>
Selesai Selesai
</button> </button>
</div> </div>
{/* Modal untuk konfirmasi selesai asesmen */} {/* Modal untuk konfirmasi selesai asesmen */}
<FinishAssessmentModal <FinishAssessmentModal
opened={modalOpen} opened={modalOpen}
onClose={() => setModalOpen(false)} onClose={() => setModalOpen(false)}
onConfirm={handleConfirmFinish} onConfirm={handleConfirmFinish}
assessmentId={assessmentId} assessmentId={assessmentId}
/>
{/* Modal untuk peringatan jika ada pertanyaan yang belum dijawab */}
<ValidationModal
opened={validationModalOpen}
onClose={() => setValidationModalOpen(false)}
unansweredQuestions={unansweredQuestions}
/> />
</Card>
</div> {/* Modal untuk peringatan jika ada pertanyaan yang belum dijawab */}
</Flex> <ValidationModal
opened={validationModalOpen}
onClose={() => setValidationModalOpen(false)}
unansweredQuestions={unansweredQuestions}
/>
</Card>
</div>
</Flex>
</div> </div>
</Flex> </Flex>
</Stack> </Stack>