From 812ad20bf01a19f0003d21c1b46807cdc31a21ea Mon Sep 17 00:00:00 2001 From: Atharva Sharma Date: Fri, 17 Oct 2025 22:44:43 +0530 Subject: [PATCH 01/12] Fix: Conditional rendering for select buttons --- src/components/CatalogueContent.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/CatalogueContent.tsx b/src/components/CatalogueContent.tsx index ce9c290..419937c 100644 --- a/src/components/CatalogueContent.tsx +++ b/src/components/CatalogueContent.tsx @@ -421,7 +421,7 @@ const CatalogueContent = () => { {/* Select/Deselect/Download All Buttons */} - + {papers.length > 0 && (
Select All @@ -429,10 +429,11 @@ const CatalogueContent = () => { Deselect All + Download Selected -
+ )} {relatedSubjects.length > 0 && (
From 080a1a4df9babd661ef649fd3b1b95ec438104e3 Mon Sep 17 00:00:00 2001 From: Atharva Sharma Date: Mon, 20 Apr 2026 01:21:42 +0530 Subject: [PATCH 02/12] fix : eh why ?? --- src/components/CatalogueContent.tsx | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/components/CatalogueContent.tsx b/src/components/CatalogueContent.tsx index 340cc51..df84ff6 100644 --- a/src/components/CatalogueContent.tsx +++ b/src/components/CatalogueContent.tsx @@ -177,31 +177,6 @@ const CatalogueContentInner = ({ subject }: { subject: string | null }) => { void fetchPapers(); }, [subject, isMounted, setPapers, setFilterOptions]); - useEffect(() => { - if (!papers.length) return; - - const filtered = [...papers]; - - if (sortOption === "asc") { - filtered.sort((a, b) => a.year.localeCompare(b.year)); - } else if (sortOption === "desc") { - filtered.sort((a, b) => b.year.localeCompare(a.year)); - } - - setFilteredPapers(filtered); - }, [ - papers, - selectedExams, - selectedSlots, - selectedYears, - selectedSemesters, - selectedCampuses, - selectedAnswerKeyIncluded, - sortOption, - setFilteredPapers, - setAppliedFilters, - ]); - useEffect(() => { if (!papers.length) return; @@ -255,6 +230,7 @@ const CatalogueContentInner = ({ subject }: { subject: string | null }) => { selectedSemesters, selectedCampuses, selectedAnswerKeyIncluded, + sortOption, setFilteredPapers, setAppliedFilters, ]); From b06d58be5b6824d5c6af0b8065c11ec2a8932313 Mon Sep 17 00:00:00 2001 From: Atharva Sharma Date: Mon, 20 Apr 2026 01:26:58 +0530 Subject: [PATCH 03/12] fix: hehe --- src/components/SideBar.tsx | 5 +++-- src/components/multi-select.tsx | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/components/SideBar.tsx b/src/components/SideBar.tsx index f5dc1cf..a3b535b 100644 --- a/src/components/SideBar.tsx +++ b/src/components/SideBar.tsx @@ -19,8 +19,9 @@ function SideBar() { handleApplyFilters, } = useFilters(); const exams = - filterOptions?.unique_exams.map((exam) => ({ label: exam, value: exam })) ?? - []; + filterOptions?.unique_exams + .sort((a, b) => a.localeCompare(b)) + .map((exam) => ({ label: exam, value: exam })) ?? []; const slots = filterOptions?.unique_slots .sort((a, b) => a.localeCompare(b, undefined, { numeric: true })) diff --git a/src/components/multi-select.tsx b/src/components/multi-select.tsx index 1e5a78a..ae11f1b 100644 --- a/src/components/multi-select.tsx +++ b/src/components/multi-select.tsx @@ -307,7 +307,9 @@ export const MultiSelect = React.forwardRef<
(Select All) - {options.map((option) => { + {options + .sort((a, b) => a.label.localeCompare(b.label)) + .map((option) => { const isSelected = selectedValues.includes(option.value); return ( Date: Mon, 20 Apr 2026 01:58:56 +0530 Subject: [PATCH 04/12] fix: my ocd --- src/components/UpcomingPaper.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/UpcomingPaper.tsx b/src/components/UpcomingPaper.tsx index 4da6923..275fb0b 100644 --- a/src/components/UpcomingPaper.tsx +++ b/src/components/UpcomingPaper.tsx @@ -105,7 +105,7 @@ export default function PaperCard({ subject, slots }: PaperCardProps) { {
- {slots?.map((slotValue, index) => ( + {[...slots].sort().map((slotValue, index) => ( {slotValue} ))}
From 9649fb55aa9f3a52fecb2148e3308af19a2fce88 Mon Sep 17 00:00:00 2001 From: Atharva Sharma Date: Mon, 20 Apr 2026 02:12:08 +0530 Subject: [PATCH 05/12] fix: add titles to buttons for better accessibility --- src/components/ReportButton.tsx | 4 +++- src/components/ShareButton.tsx | 3 ++- src/components/newPdfViewer.tsx | 4 ++++ 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/components/ReportButton.tsx b/src/components/ReportButton.tsx index 80cd7f8..8453351 100644 --- a/src/components/ReportButton.tsx +++ b/src/components/ReportButton.tsx @@ -10,10 +10,12 @@ export default function ReportButton(){ const { paperId, subject, exam, slot, year } = usePaper(); const [open, setOpen] = useState(false); return ( - <> + <> diff --git a/src/components/ShareButton.tsx b/src/components/ShareButton.tsx index 60fc3c1..e06c7a6 100644 --- a/src/components/ShareButton.tsx +++ b/src/components/ShareButton.tsx @@ -30,7 +30,7 @@ export default function ShareButton() { return ( - @@ -47,6 +47,7 @@ export default function ShareButton() { type="submit" size="sm" className="flex w-fit items-center justify-between gap-5 px-3" + title="Copy link to clipboard" onClick={async () => { await toast.promise( navigator.clipboard.writeText(paperPath), // This is a promise diff --git a/src/components/newPdfViewer.tsx b/src/components/newPdfViewer.tsx index 5948f91..a2c47ab 100644 --- a/src/components/newPdfViewer.tsx +++ b/src/components/newPdfViewer.tsx @@ -114,6 +114,7 @@ const Controls = memo(function Controls({documentId, toggleFullscreen, isFullscr @@ -121,6 +122,7 @@ const Controls = memo(function Controls({documentId, toggleFullscreen, isFullscr @@ -131,6 +133,7 @@ const Controls = memo(function Controls({documentId, toggleFullscreen, isFullscr onClick={zoomOut} disabled={typeof zoomLevel === "number" && zoomLevel <= 0.25} className="h-10 w-10 rounded p-0 text-white bg-[#6536c1] transition hover:bg-[#7d4fc7] disabled:bg-gray-400" + title="Zoom out" > @@ -143,6 +146,7 @@ const Controls = memo(function Controls({documentId, toggleFullscreen, isFullscr onClick={zoomIn} disabled={typeof zoomLevel === "number" && zoomLevel >= 3} className="h-10 w-10 rounded p-0 text-white bg-[#6536c1] transition hover:bg-[#7d4fc7] disabled:bg-gray-400" + title="Zoom in" > From e4c0a63ae67d12ce5b3ae77d2bfd28ffd50f06da Mon Sep 17 00:00:00 2001 From: Atharva Sharma Date: Mon, 20 Apr 2026 02:51:47 +0530 Subject: [PATCH 06/12] fix carousel grid --- src/components/PinnedPapersCarousel.tsx | 267 ------------------------ 1 file changed, 267 deletions(-) diff --git a/src/components/PinnedPapersCarousel.tsx b/src/components/PinnedPapersCarousel.tsx index 3ee010a..e69de29 100644 --- a/src/components/PinnedPapersCarousel.tsx +++ b/src/components/PinnedPapersCarousel.tsx @@ -1,267 +0,0 @@ -"use client"; - -import { useEffect, useState } from "react"; -import axios from "axios"; -import { type IUpcomingPaper } from "@/interface"; -import UpcomingPaper from "./UpcomingPaper"; -import { - Carousel, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel"; -import Autoplay from "embla-carousel-autoplay"; -import { chunkArray } from "@/lib/utils/array"; -import { type StoredSubjects } from "@/interface"; -import SkeletonPaperCard from "./SkeletonPaperCard"; -import PinnedModal from "./ui/PinnedModal"; - -function PinnedPapersCarousel() { - const [isLoading, setIsLoading] = useState(true); - const [chunkSize, setChunkSize] = useState(4); - const [displayPapers, setDisplayPapers] = useState([]); - useEffect(() => { - const handleResize = () => { - if (window.innerWidth <= 540) { - setChunkSize(2); - } else if (window.innerWidth <= 920) { - setChunkSize(4); - } else { - setChunkSize(8); - } - }; - - handleResize(); // initialize - window.addEventListener("resize", handleResize); - return () => window.removeEventListener("resize", handleResize); - }, []); - - const chunkedPapers = chunkArray(displayPapers, chunkSize); - - if (chunkedPapers.length > 0) { - const lastChunkIndex = chunkedPapers.length - 1; - if ((chunkedPapers[lastChunkIndex]?.length ?? 0) < chunkSize) { - chunkedPapers[lastChunkIndex] = [ - ...(chunkedPapers[lastChunkIndex] ?? []), - { subject: "add_subject_button", slots: [] } as IUpcomingPaper, - ]; - } else { - chunkedPapers.push([ - { subject: "add_subject_button", slots: [] } as IUpcomingPaper, - ]); - } - } - - const fetchPapers = async () => { - try { - setIsLoading(true); - - const storedSubjects = JSON.parse( - localStorage.getItem("userSubjects") ?? "[]", - ) as StoredSubjects; - - const response = await axios.post<{ subject: string; slots: string[] }[]>( - "/api/user-papers", - storedSubjects, - ); - - const fetchedPapers = response.data; - - const fetchedSubjectsSet = new Set( - fetchedPapers.map((paper) => paper.subject), - ); - - const storedSubjectsArray = Array.isArray(storedSubjects) - ? storedSubjects - : []; - const missingSubjects = storedSubjectsArray - .filter((subject: string) => !fetchedSubjectsSet.has(subject)) - .map((subject: string) => ({ - subject, - slots: [], - })) as { subject: string; slots: string[] }[]; - - const allDisplayPapers = [...fetchedPapers, ...missingSubjects]; - - allDisplayPapers.sort((a, b) => { - const aIndex = storedSubjects.indexOf(a.subject); - const bIndex = storedSubjects.indexOf(b.subject); - - return ( - (aIndex === -1 ? Number.MAX_SAFE_INTEGER : aIndex) - - (bIndex === -1 ? Number.MAX_SAFE_INTEGER : bIndex) - ); - }); - - setDisplayPapers(allDisplayPapers); - } catch (error) { - console.error("Failed to fetch papers:", error); - } finally { - setIsLoading(false); - } - }; - - useEffect(() => { - void fetchPapers(); - }, []); - - useEffect(() => { - const handleSubjectsChange = () => { - void (async () => { - try { - const storedSubjects = JSON.parse( - localStorage.getItem("userSubjects") ?? "[]", - ) as StoredSubjects; - - const response = await axios.post< - { subject: string; slots: string[] }[] - >("/api/user-papers", storedSubjects); - - const fetchedPapers = response.data; - - const fetchedSubjectsSet = new Set( - fetchedPapers.map((paper) => paper.subject), - ); - - const storedSubjectsArray = Array.isArray(storedSubjects) - ? storedSubjects - : []; - const missingSubjects = storedSubjectsArray - .filter((subject: string) => !fetchedSubjectsSet.has(subject)) - .map((subject: string) => ({ - subject, - slots: [], - })) as { subject: string; slots: string[] }[]; - - const allDisplayPapers = [...fetchedPapers, ...missingSubjects]; - - allDisplayPapers.sort((a, b) => { - const aIndex = storedSubjects.indexOf(a.subject); - const bIndex = storedSubjects.indexOf(b.subject); - - return ( - (aIndex === -1 ? Number.MAX_SAFE_INTEGER : aIndex) - - (bIndex === -1 ? Number.MAX_SAFE_INTEGER : bIndex) - ); - }); - - setDisplayPapers(allDisplayPapers); - } catch (error) { - console.error("Failed to fetch papers:", error); - } - })(); - }; - - window.addEventListener("userSubjectsChanged", handleSubjectsChange); - - return () => { - window.removeEventListener("userSubjectsChanged", handleSubjectsChange); - }; - }, []); - - const plugins = [Autoplay({ delay: 8000, stopOnInteraction: true })]; - - return ( -
-
- {displayPapers.length > 0 ? ( - - {(() => { - const totalItems = displayPapers.length + 1; - const needsNav = totalItems > chunkSize; - return needsNav ? ( -
- - -
- ) : null; - })()} - - {isLoading ? ( - - - - ) : ( - chunkedPapers.map((paperGroup, index) => { - const placeholdersNeeded = - (chunkSize - paperGroup.length) % chunkSize; - return ( - - {paperGroup.map((paper, subIndex) => - paper.subject === "add_subject_button" ? ( -
- -
- ) : ( -
- -
- ), - )} - - {Array.from({ length: placeholdersNeeded }).map( - (_, placeholderIndex) => ( -
- ), - )} -
- ); - }) - )} -
-
- ) : ( -
- Start pinning subjects for quick and easy access. -
- - - -
-
- )} -
-
- ); -} - -export default PinnedPapersCarousel; From 1209a7112ee68f6218371f51db772866ad9123b7 Mon Sep 17 00:00:00 2001 From: Atharva Sharma Date: Mon, 20 Apr 2026 02:56:18 +0530 Subject: [PATCH 07/12] merge --- src/components/PinnedPapersCarousel.tsx | 268 ++++++++++++++++++++++++ 1 file changed, 268 insertions(+) diff --git a/src/components/PinnedPapersCarousel.tsx b/src/components/PinnedPapersCarousel.tsx index e69de29..ec90d28 100644 --- a/src/components/PinnedPapersCarousel.tsx +++ b/src/components/PinnedPapersCarousel.tsx @@ -0,0 +1,268 @@ +"use client"; + +import { useEffect, useState } from "react"; +import axios from "axios"; +import { type IUpcomingPaper } from "@/interface"; +import UpcomingPaper from "./UpcomingPaper"; +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from "@/components/ui/carousel"; +import Autoplay from "embla-carousel-autoplay"; +import { chunkArray } from "@/lib/utils/array"; +import { type StoredSubjects } from "@/interface"; +import SkeletonPaperCard from "./SkeletonPaperCard"; +import PinnedModal from "./ui/PinnedModal"; + +function PinnedPapersCarousel() { + const [isLoading, setIsLoading] = useState(true); + const [chunkSize, setChunkSize] = useState(4); + const [displayPapers, setDisplayPapers] = useState([]); + useEffect(() => { + const handleResize = () => { + if (window.innerWidth <= 540) { + setChunkSize(2); + } else if (window.innerWidth <= 920) { + setChunkSize(4); + } else { + setChunkSize(8); + } + }; + + handleResize(); // initialize + window.addEventListener("resize", handleResize); + return () => window.removeEventListener("resize", handleResize); + }, []); + + const chunkedPapers = chunkArray(displayPapers, chunkSize); + + if (chunkedPapers.length > 0) { + const lastChunkIndex = chunkedPapers.length - 1; + if ((chunkedPapers[lastChunkIndex]?.length ?? 0) < chunkSize) { + chunkedPapers[lastChunkIndex] = [ + ...(chunkedPapers[lastChunkIndex] ?? []), + { subject: "add_subject_button", slots: [] } as IUpcomingPaper, + ]; + } else { + chunkedPapers.push([ + { subject: "add_subject_button", slots: [] } as IUpcomingPaper, + ]); + } + } + + const fetchPapers = async () => { + try { + setIsLoading(true); + + const storedSubjects = JSON.parse( + localStorage.getItem("userSubjects") ?? "[]", + ) as StoredSubjects; + + const response = await axios.post<{ subject: string; slots: string[] }[]>( + "/api/user-papers", + storedSubjects, + ); + + const fetchedPapers = response.data; + + const fetchedSubjectsSet = new Set( + fetchedPapers.map((paper) => paper.subject), + ); + + const storedSubjectsArray = Array.isArray(storedSubjects) + ? storedSubjects + : []; + const missingSubjects = storedSubjectsArray + .filter((subject: string) => !fetchedSubjectsSet.has(subject)) + .map((subject: string) => ({ + subject, + slots: [], + })) as { subject: string; slots: string[] }[]; + + const allDisplayPapers = [...fetchedPapers, ...missingSubjects]; + + allDisplayPapers.sort((a, b) => { + const aIndex = storedSubjects.indexOf(a.subject); + const bIndex = storedSubjects.indexOf(b.subject); + + return ( + (aIndex === -1 ? Number.MAX_SAFE_INTEGER : aIndex) - + (bIndex === -1 ? Number.MAX_SAFE_INTEGER : bIndex) + ); + }); + + setDisplayPapers(allDisplayPapers); + } catch (error) { + console.error("Failed to fetch papers:", error); + } finally { + setIsLoading(false); + } + }; + + useEffect(() => { + void fetchPapers(); + }, []); + + useEffect(() => { + const handleSubjectsChange = () => { + void (async () => { + try { + const storedSubjects = JSON.parse( + localStorage.getItem("userSubjects") ?? "[]", + ) as StoredSubjects; + + const response = await axios.post< + { subject: string; slots: string[] }[] + >("/api/user-papers", storedSubjects); + + const fetchedPapers = response.data; + + const fetchedSubjectsSet = new Set( + fetchedPapers.map((paper) => paper.subject), + ); + + const storedSubjectsArray = Array.isArray(storedSubjects) + ? storedSubjects + : []; + const missingSubjects = storedSubjectsArray + .filter((subject: string) => !fetchedSubjectsSet.has(subject)) + .map((subject: string) => ({ + subject, + slots: [], + })) as { subject: string; slots: string[] }[]; + + const allDisplayPapers = [...fetchedPapers, ...missingSubjects]; + + allDisplayPapers.sort((a, b) => { + const aIndex = storedSubjects.indexOf(a.subject); + const bIndex = storedSubjects.indexOf(b.subject); + + return ( + (aIndex === -1 ? Number.MAX_SAFE_INTEGER : aIndex) - + (bIndex === -1 ? Number.MAX_SAFE_INTEGER : bIndex) + ); + }); + + setDisplayPapers(allDisplayPapers); + } catch (error) { + console.error("Failed to fetch papers:", error); + } + })(); + }; + + window.addEventListener("userSubjectsChanged", handleSubjectsChange); + + return () => { + window.removeEventListener("userSubjectsChanged", handleSubjectsChange); + }; + }, []); + + const plugins = [Autoplay({ delay: 8000, stopOnInteraction: true })]; + + return ( +
+
+ {displayPapers.length > 0 ? ( + + {(() => { + const totalItems = displayPapers.length + 1; + const needsNav = totalItems > chunkSize; + return needsNav ? ( +
+ + +
+ ) : null; + })()} + + {isLoading ? ( + + + + ) : ( + chunkedPapers.map((paperGroup, index) => { + const columns = chunkSize === 2 ? 1 : chunkSize === 4 ? 2 : 4; + const rows = Math.max(1, Math.ceil(paperGroup.length / columns)); + const placeholdersNeeded = columns * rows - paperGroup.length; + return ( + + {paperGroup.map((paper, subIndex) => + paper.subject === "add_subject_button" ? ( +
+ +
+ ) : ( +
+ +
+ ), + )} + + {Array.from({ length: placeholdersNeeded }).map( + (_, placeholderIndex) => ( +
+ ), + )} +
+ ); + }) + )} +
+
+ ) : ( +
+ Start pinning subjects for quick and easy access. +
+ + + +
+
+ )} +
+
+ ); +} + +export default PinnedPapersCarousel; \ No newline at end of file From e57ff57d92fdcda759bd728e8955726d3764357e Mon Sep 17 00:00:00 2001 From: Yogesh Date: Tue, 21 Apr 2026 16:27:32 +0530 Subject: [PATCH 08/12] refactor: fetch 16 upcoming papers directly --- src/app/api/upcoming-papers/route.ts | 24 +++++------------------- src/app/request/page.tsx | 6 +----- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/src/app/api/upcoming-papers/route.ts b/src/app/api/upcoming-papers/route.ts index 72d52e9..9c76428 100644 --- a/src/app/api/upcoming-papers/route.ts +++ b/src/app/api/upcoming-papers/route.ts @@ -1,30 +1,16 @@ import { NextResponse } from "next/server"; import { connectToDatabase } from "@/lib/database/mongoose"; -import UpcomingSlot from "@/db/upcoming-slot"; import UpcomingSubject from "@/db/upcoming-paper"; -import { calculateCorrespondingSlots } from "@/lib/utils/slot-calculation"; export const dynamic = "force-dynamic"; export async function GET() { try { await connectToDatabase(); - const upcomingSlot = await UpcomingSlot.find(); - const slot = upcomingSlot[0]?.slot; - - if (!slot) { - return NextResponse.json( - { - message: "No slot found.", - }, - { status: 404 }, - ); - } - - const correspondingSlots = calculateCorrespondingSlots(slot); - const selectedSubjects = await UpcomingSubject.find({ - slots: { $in: correspondingSlots }, - }); + const selectedSubjects = await UpcomingSubject.find() + .sort({ _id: 1 }) + .limit(16) + .lean(); if (selectedSubjects.length === 0) { return NextResponse.json( @@ -47,4 +33,4 @@ export async function GET() { { status: 500 }, ); } -} \ No newline at end of file +} diff --git a/src/app/request/page.tsx b/src/app/request/page.tsx index 2529d90..97367f6 100644 --- a/src/app/request/page.tsx +++ b/src/app/request/page.tsx @@ -52,11 +52,7 @@ export default function PaperRequest() { "/api/upcoming-papers", ); - const randomPapers = [...response.data] - .sort(() => Math.random() - 0.5) - .slice(0, 8); - - setDisplayPapers(randomPapers); + setDisplayPapers(response.data); } catch (error) { console.error("Failed to fetch papers:", error); } finally { From fa88c7a360987c85b3a718212e14a10c8733308d Mon Sep 17 00:00:00 2001 From: Yogesh Date: Tue, 21 Apr 2026 19:06:21 +0530 Subject: [PATCH 09/12] update devsoc url --- src/components/Footer.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 4ec806a..c59b7b4 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -104,7 +104,7 @@ export default function Footer() { {/* Events */}

Events

- DevSOC + DevSOC CookOff Clueminati
From 6696b83fae922f624733abc10ca5e2b6ec6bbdc1 Mon Sep 17 00:00:00 2001 From: Rithish Date: Tue, 21 Apr 2026 15:03:51 +0000 Subject: [PATCH 10/12] fix: correct PDF viewer page count issue (1 of 0 bug) --- src/components/Card.tsx | 276 +++++++++++++++++------------------ src/components/pdfViewer.tsx | 25 +++- 2 files changed, 155 insertions(+), 146 deletions(-) diff --git a/src/components/Card.tsx b/src/components/Card.tsx index f6ee83f..c9f1e07 100644 --- a/src/components/Card.tsx +++ b/src/components/Card.tsx @@ -6,141 +6,141 @@ import Image from "next/image"; import { Eye, Download, Check } from "lucide-react"; import { extractBracketContent, - extractWithoutBracketContent, -} from "@/lib/utils/string"; -import { - getSecureUrl, - generateFileName, - downloadFile, -} from "@/lib/utils/download"; -import { Capsule } from "@/components/ui/capsule"; -import Link from "next/link"; -import { cn } from "@/lib/utils"; - -interface CardProps { - paper: IPaper; - onSelect: (paper: IPaper, isSelected: boolean) => void; - isSelected: boolean; -} - -const Card = ({ paper, onSelect, isSelected }: CardProps) => { - const [previewOpen, setPreviewOpen] = React.useState(false); - - const handleDownload = async (paper: IPaper) => { - await downloadFile(getSecureUrl(paper.file_url), generateFileName(paper)); - }; - - const handleCheckboxChange = () => { - onSelect(paper, !isSelected); - }; - - const paperLink = `/paper/${paper._id}`; - - return ( - <> -
- - {paper.subject} - -
-
-
- {extractBracketContent(paper.subject)} -
-
- -
- -
-
- {extractWithoutBracketContent(paper.subject)} -
-
- {paper.exam} - {paper.slot} - {paper.year} - {paper.semester} -
-
-
- - -
- { - e.preventDefault(); - e.stopPropagation(); - setPreviewOpen(true); - }} - /> - - { - e.stopPropagation(); - void handleDownload(paper); - }} - className="cursor-pointer" - /> -
- -
-
- -

Select

-
- - {paper.answer_key_included && ( -
- - Answer Key -
- )} -
-
- - {previewOpen && ( -
setPreviewOpen(false)} - > -
e.stopPropagation()} - > - -