update: change position on pagination when device is responsive
This commit is contained in:
parent
dab3423cec
commit
830ea9f635
|
|
@ -5,14 +5,11 @@ import {
|
||||||
Text,
|
Text,
|
||||||
Loader,
|
Loader,
|
||||||
ActionIcon,
|
ActionIcon,
|
||||||
CloseButton,
|
|
||||||
Group,
|
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
CardContent,
|
CardContent,
|
||||||
CardDescription,
|
CardDescription,
|
||||||
CardTitle,
|
|
||||||
} from "@/shadcn/components/ui/card";
|
} from "@/shadcn/components/ui/card";
|
||||||
import { Button } from "@/shadcn/components/ui/button";
|
import { Button } from "@/shadcn/components/ui/button";
|
||||||
import { Textarea } from "@/shadcn/components/ui/textarea";
|
import { Textarea } from "@/shadcn/components/ui/textarea";
|
||||||
|
|
@ -34,30 +31,18 @@ import {
|
||||||
getQuestionsAllQueryOptions,
|
getQuestionsAllQueryOptions,
|
||||||
toggleFlagAnswer,
|
toggleFlagAnswer,
|
||||||
} from "@/modules/assessmentManagement/queries/assessmentQueries";
|
} from "@/modules/assessmentManagement/queries/assessmentQueries";
|
||||||
import { TbFlagFilled, TbUpload, TbChevronRight, TbChevronDown, TbLayoutSidebarLeftCollapseFilled, TbMenu2 } from "react-icons/tb";
|
import { TbFlagFilled, TbChevronRight, TbChevronDown, TbLayoutSidebarLeftCollapseFilled } from "react-icons/tb";
|
||||||
import FinishAssessmentModal from "@/modules/assessmentManagement/modals/ConfirmModal";
|
import FinishAssessmentModal from "@/modules/assessmentManagement/modals/ConfirmModal";
|
||||||
import FileUpload from "@/modules/assessmentManagement/fileUpload/fileUpload";
|
import FileUpload from "@/modules/assessmentManagement/fileUpload/fileUpload";
|
||||||
import ValidationModal from "@/modules/assessmentManagement/modals/ValidationModal";
|
import ValidationModal from "@/modules/assessmentManagement/modals/ValidationModal";
|
||||||
import FileSizeValidationModal from "@/modules/assessmentManagement/modals/FileSizeValidationModal";
|
|
||||||
import {
|
import {
|
||||||
Sheet,
|
Sheet,
|
||||||
SheetClose,
|
|
||||||
SheetContent,
|
SheetContent,
|
||||||
SheetDescription,
|
|
||||||
SheetFooter,
|
|
||||||
SheetHeader,
|
|
||||||
SheetTitle,
|
SheetTitle,
|
||||||
SheetTrigger,
|
|
||||||
} from "@/shadcn/components/ui/sheet";
|
} from "@/shadcn/components/ui/sheet";
|
||||||
import {
|
import {
|
||||||
LeftSheet,
|
LeftSheet,
|
||||||
LeftSheetClose,
|
|
||||||
LeftSheetContent,
|
LeftSheetContent,
|
||||||
LeftSheetDescription,
|
|
||||||
LeftSheetFooter,
|
|
||||||
LeftSheetHeader,
|
|
||||||
LeftSheetTitle,
|
|
||||||
LeftSheetTrigger,
|
|
||||||
} from "@/shadcn/components/ui/leftsheet";
|
} from "@/shadcn/components/ui/leftsheet";
|
||||||
import { useState, useRef, useEffect } from "react";
|
import { useState, useRef, useEffect } from "react";
|
||||||
import AppHeader from "@/components/AppHeader";
|
import AppHeader from "@/components/AppHeader";
|
||||||
|
|
@ -93,12 +78,6 @@ export interface SubmitOptionResponse {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// const [isLeftSidebarOpen, setIsLeftSidebarOpen] = useState(false);
|
|
||||||
|
|
||||||
// export const toggleLeftSidebar = () => setIsLeftSidebarOpen(!isLeftSidebarOpen);
|
|
||||||
|
|
||||||
// import AppHeader from '../../../components/AppHeader';
|
|
||||||
|
|
||||||
export default function AssessmentPage() {
|
export default function AssessmentPage() {
|
||||||
const [page, setPage] = useState(1);
|
const [page, setPage] = useState(1);
|
||||||
const limit = 10;
|
const limit = 10;
|
||||||
|
|
@ -128,15 +107,8 @@ export default function AssessmentPage() {
|
||||||
const [openNavbar, setOpenNavbar] = useState(false);
|
const [openNavbar, setOpenNavbar] = useState(false);
|
||||||
const [isLeftSidebarOpen, setIsLeftSidebarOpen] = useState(false);
|
const [isLeftSidebarOpen, setIsLeftSidebarOpen] = useState(false);
|
||||||
|
|
||||||
// Toggle the sidebar open/close on mobile
|
|
||||||
const toggleSidebar = () => setIsSidebarOpen(!isSidebarOpen);
|
|
||||||
|
|
||||||
const toggleLeftSidebar = () => setIsLeftSidebarOpen(!isLeftSidebarOpen);
|
const toggleLeftSidebar = () => setIsLeftSidebarOpen(!isLeftSidebarOpen);
|
||||||
|
|
||||||
const toggleSidebarLeftSide = () => {
|
|
||||||
setIsSidebarOpen((prevState) => !prevState);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Fungsi toggle untuk membuka/menutup navbar
|
// Fungsi toggle untuk membuka/menutup navbar
|
||||||
const toggle = () => {
|
const toggle = () => {
|
||||||
setOpenNavbar((prevState) => !prevState);
|
setOpenNavbar((prevState) => !prevState);
|
||||||
|
|
@ -648,10 +620,6 @@ export default function AssessmentPage() {
|
||||||
|
|
||||||
{/* LEFT-SIDE */}
|
{/* LEFT-SIDE */}
|
||||||
{/* Aspek dan Sub-Aspek */}
|
{/* Aspek dan Sub-Aspek */}
|
||||||
{/* <TbMenu2
|
|
||||||
onClick={toggleLeftSidebar}
|
|
||||||
className="ml-4 w-6 h-fit pb-4 mb-4 cursor-pointer"
|
|
||||||
/> */}
|
|
||||||
<AppHeader
|
<AppHeader
|
||||||
openNavbar={isLeftSidebarOpen}
|
openNavbar={isLeftSidebarOpen}
|
||||||
toggle={toggleLeftSidebar}
|
toggle={toggleLeftSidebar}
|
||||||
|
|
@ -662,6 +630,7 @@ export default function AssessmentPage() {
|
||||||
{isMobile && (
|
{isMobile && (
|
||||||
<LeftSheet open={isLeftSidebarOpen} onOpenChange={(open) => setIsLeftSidebarOpen(open)}>
|
<LeftSheet open={isLeftSidebarOpen} onOpenChange={(open) => setIsLeftSidebarOpen(open)}>
|
||||||
<LeftSheetContent className="h-full w-75 overflow-auto">
|
<LeftSheetContent className="h-full w-75 overflow-auto">
|
||||||
|
<Label className="text-gray-800 p-5 text-sm font-normal">Aspek Menu</Label>
|
||||||
<Flex direction="column" gap="xs" className="w-64">
|
<Flex direction="column" gap="xs" className="w-64">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{/* Aspek */}
|
{/* Aspek */}
|
||||||
|
|
@ -672,7 +641,7 @@ export default function AssessmentPage() {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.map((aspect) => (
|
.map((aspect) => (
|
||||||
<div key={aspect.id} className="p-2 ">
|
<div key={aspect.id} className="p-2 mt-4">
|
||||||
<div
|
<div
|
||||||
className="flex justify-between cursor-pointer"
|
className="flex justify-between cursor-pointer"
|
||||||
onClick={() => toggleAspect(aspect.id)}
|
onClick={() => toggleAspect(aspect.id)}
|
||||||
|
|
@ -715,6 +684,7 @@ export default function AssessmentPage() {
|
||||||
|
|
||||||
{/* Sidebar for Desktop (Always Visible) */}
|
{/* Sidebar for Desktop (Always Visible) */}
|
||||||
<div className="hidden md:block fixed h-screen w-64 overflow-auto">
|
<div className="hidden md:block fixed h-screen w-64 overflow-auto">
|
||||||
|
<Label className="text-gray-800 p-5 text-sm font-normal">Aspek Menu</Label>
|
||||||
<Flex direction="column" gap="xs" className="w-64">
|
<Flex direction="column" gap="xs" className="w-64">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
{/* Aspek */}
|
{/* Aspek */}
|
||||||
|
|
@ -790,10 +760,10 @@ export default function AssessmentPage() {
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<div className="grid grid-cols-[auto_1fr_auto] gap-2 w-full items-start">
|
<div className="grid grid-cols-[auto_1fr_auto] gap-2 w-full items-start">
|
||||||
{/* Question Number */}
|
{/* Question Number */}
|
||||||
<Text className="font-bold p-1 text-sm">{startIndex + index + 1}.</Text>
|
<Text className="font-bold p-2 text-sm">{startIndex + index + 1}.</Text>
|
||||||
|
|
||||||
{/* Question Text */}
|
{/* Question Text */}
|
||||||
<Text className="font-bold break-words text-sm p-1">{question.questionText}</Text>
|
<Text className="font-bold break-words text-sm p-2">{question.questionText}</Text>
|
||||||
|
|
||||||
{/* Action Icon/Flag */}
|
{/* Action Icon/Flag */}
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
|
|
@ -810,7 +780,7 @@ export default function AssessmentPage() {
|
||||||
|
|
||||||
{/* Radio Button Options */}
|
{/* Radio Button Options */}
|
||||||
{question.options?.length > 0 ? (
|
{question.options?.length > 0 ? (
|
||||||
<div className="mx-8">
|
<div className="mx-11">
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
value={answers[question.questionId] || ""}
|
value={answers[question.questionId] || ""}
|
||||||
onValueChange={(value) => handleAnswerChange(question.questionId, value)}
|
onValueChange={(value) => handleAnswerChange(question.questionId, value)}
|
||||||
|
|
@ -880,6 +850,20 @@ export default function AssessmentPage() {
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
|
{/* Pagination for mobile */}
|
||||||
|
<div className="md:hidden mb-4 flex justify-center">
|
||||||
|
<Pagination
|
||||||
|
page={currentPage}
|
||||||
|
totalPages={totalPages}
|
||||||
|
onPageChange={(newPage) => {
|
||||||
|
if (selectedSubAspectId) {
|
||||||
|
handlePageChange(selectedSubAspectId, newPage);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text className="text-sm m-0">Halaman {currentPage} dari {totalPages}</Text>
|
||||||
|
</Pagination>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* RIGHT-SIDE */}
|
{/* RIGHT-SIDE */}
|
||||||
|
|
@ -887,7 +871,7 @@ export default function AssessmentPage() {
|
||||||
{isMobile && (
|
{isMobile && (
|
||||||
<button
|
<button
|
||||||
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
onClick={() => setIsSidebarOpen(!isSidebarOpen)}
|
||||||
className="fixed bottom-4 right-4 bg-[--primary-color] text-white p-3 rounded-full shadow-md z-50"
|
className="fixed bottom-4 right-4 bg-black text-white p-3 rounded-xl shadow-md z-50"
|
||||||
>
|
>
|
||||||
<TbLayoutSidebarLeftCollapseFilled size={30} />
|
<TbLayoutSidebarLeftCollapseFilled size={30} />
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -896,14 +880,13 @@ export default function AssessmentPage() {
|
||||||
{/* Sidebar for mobile (only when toggled) */}
|
{/* Sidebar for mobile (only when toggled) */}
|
||||||
<div className="hidden md:block">
|
<div className="hidden md:block">
|
||||||
<Sheet open={isSidebarOpen} onOpenChange={(open) => setIsSidebarOpen(open)}>
|
<Sheet open={isSidebarOpen} onOpenChange={(open) => setIsSidebarOpen(open)}>
|
||||||
<SheetContent className="h-full w-70 overflow-auto">
|
<SheetContent className="h-full w-30 overflow-auto">
|
||||||
<SheetTitle className="font-medium text-lg text-gray-800 mb-2">
|
<SheetTitle className="font-medium text-lg text-gray-800 mb-2">
|
||||||
Nomor Soal
|
Nomor Soal
|
||||||
</SheetTitle>
|
</SheetTitle>
|
||||||
{/* <Text className="font-medium text-lg text-gray-800 mb-2">Nomor Soal</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 pb-3">
|
||||||
{Array.from({ length: totalQuestionsInSubAspect }).map((_, i) => {
|
{Array.from({ length: totalQuestionsInSubAspect }).map((_, i) => {
|
||||||
const questionNumber = startIndex + i + 1;
|
const questionNumber = startIndex + i + 1;
|
||||||
const questionId = filteredQuestions[i]?.questionId;
|
const questionId = filteredQuestions[i]?.questionId;
|
||||||
|
|
@ -930,64 +913,50 @@ export default function AssessmentPage() {
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-4 flex justify-center">
|
{/* Divider */}
|
||||||
<Pagination
|
<div className="border-t-2 border-gray-300 my-4" />
|
||||||
page={currentPage}
|
|
||||||
totalPages={totalPages}
|
|
||||||
onPageChange={(newPage) => {
|
|
||||||
if (selectedSubAspectId) {
|
|
||||||
handlePageChange(selectedSubAspectId, newPage);
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text className="text-xs m-0">Halaman {currentPage} dari {totalPages}</Text>
|
|
||||||
</Pagination>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Skor Aspek dan Sub-Aspek */}
|
{/* Skor Aspek dan Sub-Aspek */}
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<Card>
|
<h2 className="text-lg font-extrabold mt-4 mb-2">Nilai Sementara</h2>
|
||||||
<CardTitle className="text-lg font-extrabold text-center mt-4 mb-2">
|
<div className="max-h-full overflow-hidden">
|
||||||
Nilai Sementara
|
<div>
|
||||||
</CardTitle>
|
{filteredAspects.length > 0 ? (
|
||||||
<CardContent className="max-h-full overflow-hidden">
|
filteredAspects.map((aspect) => {
|
||||||
<ScrollArea className="h-[200px] w-full rounded-md p-2">
|
const aspectScore = parseFloat(aspect.averageScore).toFixed(2);
|
||||||
<CardDescription>
|
const aspectScoreValue = parseFloat(aspectScore);
|
||||||
{filteredAspects.length > 0 ? (
|
|
||||||
filteredAspects.map((aspect) => {
|
|
||||||
const aspectScore = parseFloat(aspect.averageScore).toFixed(2);
|
|
||||||
const aspectScoreValue = parseFloat(aspectScore);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={aspect.aspectId} className="flex justify-between items-center">
|
<div key={aspect.aspectId} className="flex justify-between items-center">
|
||||||
<Text className="text-lg text-gray-700">{aspect.aspectName}</Text>
|
<Text className="text-lg text-gray-700 break-words whitespace-normal">{aspect.aspectName}</Text>
|
||||||
<Text
|
<Text
|
||||||
className={`text-xl font-bold ${
|
className={`text-xl font-bold ${
|
||||||
aspectScoreValue >= 4.5
|
aspectScoreValue >= 4.5
|
||||||
? "text-green-700"
|
? "text-green-700"
|
||||||
: aspectScoreValue >= 3.5
|
: aspectScoreValue >= 3.5
|
||||||
? "text-green-400"
|
? "text-green-400"
|
||||||
: aspectScoreValue >= 2.5
|
: aspectScoreValue >= 2.5
|
||||||
? "text-yellow-400"
|
? "text-yellow-400"
|
||||||
: aspectScoreValue >= 1.5
|
: aspectScoreValue >= 1.5
|
||||||
? "text-orange-500"
|
? "text-orange-500"
|
||||||
: "text-red-500"
|
: "text-red-500"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{aspectScore}
|
{aspectScore}
|
||||||
</Text>
|
</Text>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
) : (
|
) : (
|
||||||
<Text className="text-base text-gray-700">Data aspek ini kosong</Text>
|
<Text className="text-base text-gray-700">Data aspek ini kosong</Text>
|
||||||
)}
|
)}
|
||||||
</CardDescription>
|
</div>
|
||||||
|
|
||||||
{/* Divider */}
|
{/* Divider */}
|
||||||
<div className="border-t-2 border-gray-300 my-4" />
|
<div className="border-t-2 border-gray-300 my-4" />
|
||||||
|
|
||||||
{/* 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);
|
||||||
|
|
@ -995,7 +964,7 @@ export default function AssessmentPage() {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div key={subAspect.subAspectId} className="flex justify-between items-center my-2">
|
<div key={subAspect.subAspectId} className="flex justify-between items-center my-2">
|
||||||
<Text className="text-sm text-gray-700">{subAspect.subAspectName}</Text>
|
<Text className="text-sm text-gray-700 break-words whitespace-normal">{subAspect.subAspectName}</Text>
|
||||||
<Text
|
<Text
|
||||||
className={`text-sm font-bold ${
|
className={`text-sm font-bold ${
|
||||||
subAspectScoreValue >= 4.5
|
subAspectScoreValue >= 4.5
|
||||||
|
|
@ -1017,18 +986,17 @@ export default function AssessmentPage() {
|
||||||
) : (
|
) : (
|
||||||
<Text className="text-sm text-gray-700">Data sub-aspek ini kosong</Text>
|
<Text className="text-sm text-gray-700">Data sub-aspek ini kosong</Text>
|
||||||
)}
|
)}
|
||||||
</ScrollArea>
|
|
||||||
|
|
||||||
{/* Finish Button */}
|
|
||||||
<div>
|
|
||||||
<Button
|
|
||||||
onClick={handleFinishClick}
|
|
||||||
className="bg-[--primary-color] text-white font-bold rounded-md w-full text-sm"
|
|
||||||
>
|
|
||||||
Selesai
|
|
||||||
</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</CardContent>
|
|
||||||
|
{/* Finish Button */}
|
||||||
|
<div className="mt-4">
|
||||||
|
<Button
|
||||||
|
onClick={handleFinishClick}
|
||||||
|
className="bg-[--primary-color] text-white font-bold rounded-md w-full text-sm"
|
||||||
|
>
|
||||||
|
Selesai
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
{/* Finish Assessment Modal */}
|
{/* Finish Assessment Modal */}
|
||||||
<FinishAssessmentModal
|
<FinishAssessmentModal
|
||||||
|
|
@ -1044,7 +1012,7 @@ export default function AssessmentPage() {
|
||||||
onClose={() => setValidationModalOpen(false)}
|
onClose={() => setValidationModalOpen(false)}
|
||||||
unansweredQuestions={unansweredQuestions}
|
unansweredQuestions={unansweredQuestions}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</SheetContent>
|
</SheetContent>
|
||||||
</Sheet>
|
</Sheet>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user