diff --git a/src/app/api/papers/count/route.ts b/src/app/api/papers/count/route.ts index bdddfeac..0bb50a57 100644 --- a/src/app/api/papers/count/route.ts +++ b/src/app/api/papers/count/route.ts @@ -3,7 +3,7 @@ import { success, failure } from "@/lib/utils/response"; export const dynamic = "force-dynamic"; -export async function GET(req: Request) { +export async function GET() { try { const courseCount = await getCourseCounts(); diff --git a/src/app/api/report-tag/route.ts b/src/app/api/report-tag/route.ts index d709e18f..23633e7a 100644 --- a/src/app/api/report-tag/route.ts +++ b/src/app/api/report-tag/route.ts @@ -1,4 +1,4 @@ -import { reportTag, ReportTagBody } from "@/lib/services/report"; +import { reportTag, type ReportTagBody } from "@/lib/services/report"; import { rateLimitCheck } from "@/lib/utils/rate-limiter"; import { success, failure } from "@/lib/utils/response"; import { customErrorHandler } from "@/lib/utils/error"; diff --git a/src/app/api/user-papers/route.ts b/src/app/api/user-papers/route.ts index 939d29fd..7a48d7dc 100644 --- a/src/app/api/user-papers/route.ts +++ b/src/app/api/user-papers/route.ts @@ -1,6 +1,6 @@ import { connectToDatabase } from "@/lib/database/mongoose"; import Paper from "@/db/papers"; -import { StoredSubjects } from "@/interface"; +import { type StoredSubjects } from "@/interface"; import { transformPapersToSubjectSlots } from "@/lib/services/paper-transform"; import { success, failure } from "@/lib/utils/response"; diff --git a/src/app/pinned/page.tsx b/src/app/pinned/page.tsx index 59d1eafd..7b0a8f92 100644 --- a/src/app/pinned/page.tsx +++ b/src/app/pinned/page.tsx @@ -1,6 +1,5 @@ import React from "react"; import SearchBar from "@/components/Searchbar/searchbar"; -import PinnedPapersCarousel from "@/components/PinnedPapersCarousel"; const Pinned = () => { return ( diff --git a/src/app/request/page.tsx b/src/app/request/page.tsx index 264370c5..56ee4ee3 100644 --- a/src/app/request/page.tsx +++ b/src/app/request/page.tsx @@ -14,7 +14,6 @@ import { Input } from "@/components/ui/input"; import axios from "axios"; import Fuse from "fuse.js"; import { type IUpcomingPaper } from "@/interface"; -import { Skeleton } from "../../components/ui/skeleton"; import UpcomingPaper from "../../components/UpcomingPaper"; import toast from "react-hot-toast"; import { Search } from "lucide-react"; @@ -22,12 +21,6 @@ import SkeletonPaperCard from "@/components/SkeletonPaperCard"; import { useCourses } from "@/context/courseContext"; import { type ApiResponse } from '@/interface' -type Course = { - name?: string | null; - courseName?: string | null; - title?: string | null; -}; - export default function PaperRequest() { const [subjects, setSubjects] = useState([]); const [searchText, setSearchText] = useState(""); @@ -39,7 +32,7 @@ export default function PaperRequest() { const suggestionsRef = useRef(null); const [displayPapers, setDisplayPapers] = useState([]); const [isLoading, setIsLoading] = useState(true); - const { courses, loading, error, refetch } = useCourses(); + const { courses } = useCourses(); useEffect(() => { setSubjects(courses.map((course) => course.name)); diff --git a/src/app/upload/page.tsx b/src/app/upload/page.tsx index dbabed99..d91d2c57 100644 --- a/src/app/upload/page.tsx +++ b/src/app/upload/page.tsx @@ -433,11 +433,7 @@ export default function Page() { }} multiple={true} > - {({ getRootProps, getInputProps, isDragActive }) => { - const pdfUploaded = files.some( - (f) => f.type === "application/pdf", - ); - + {({ getRootProps, getInputProps }) => { return (
{ useEffect(() => { setCurrentPage(1); - }, [subject]); + }, [subject, setCurrentPage]); // Fetch related subjects when subject changes useEffect(() => { diff --git a/src/components/FloatingNavbar.tsx b/src/components/FloatingNavbar.tsx index 53b65fb8..3997e494 100644 --- a/src/components/FloatingNavbar.tsx +++ b/src/components/FloatingNavbar.tsx @@ -4,9 +4,7 @@ import { usePathname } from "next/navigation"; import Link from "next/link"; import { useState } from "react"; import { - ArrowUpRight, ChevronDown, - Pin, UploadIcon, } from "lucide-react"; import ModeToggle from "./toggle-theme"; diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 464a542f..945b0944 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -1,8 +1,7 @@ "use client"; import Link from "next/link"; -import { useTheme } from "next-themes"; -import { useEffect, useState } from "react"; +import { useState } from "react"; import { Button } from "./ui/button"; import { Input } from "@/components/ui/input"; import { @@ -13,24 +12,12 @@ import { FaXTwitter, FaYoutube, } from "react-icons/fa6"; -import { Bold, Mail } from "lucide-react"; +import { Mail } from "lucide-react"; import toast from "react-hot-toast"; import type { ApiResponse } from '@/interface' -type SubscribeResponse = { - success?: boolean; - message?: string; -}; - export default function Footer() { - const { theme } = useTheme(); - const [isDarkMode, setIsDarkMode] = useState(true); const [email, setEmail] = useState(""); - useEffect(() => { - if (theme) { - setIsDarkMode(theme === "dark"); - } - }, [theme]); const handleSubscribe = async () => { if (!email.trim()) { toast.error("Please enter your email."); diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index d22fdf58..27f56e69 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,22 +1,18 @@ "use client"; import { useState, useEffect } from "react"; -import Image, { StaticImageData } from "next/image"; +import Image, { type StaticImageData } from "next/image"; import Link from "next/link"; import { usePathname } from "next/navigation"; import ccLogo from "../assets/codechef_logo.svg"; import ModeToggle from "@/components/toggle-theme"; import { ArrowDownLeftIcon, - Pin, - ArrowUpRight, ChevronDown, } from "lucide-react"; import FloatingNavbar from "./FloatingNavbar"; import PWAInstallButton from "./ui/PWAInstallButton"; import SearchBarChild from "./Searchbar/searchbar-child"; -import Banner from "@/components/ui/banners/bannerDismiss"; -import type { ICourses } from "@/interface"; import { DropdownMenu, DropdownMenuTrigger, @@ -32,7 +28,7 @@ function Navbar() { const pathname: string = usePathname() ?? "/"; const [dropdownOpen, setDropdownOpen] = useState(false); - const { courses, loading, error, refetch } = useCourses(); + const { courses } = useCourses(); useEffect(() => { if (pathname !== "/catalogue") return; diff --git a/src/components/PapersCarousel.tsx b/src/components/PapersCarousel.tsx index b2368c56..83081d69 100644 --- a/src/components/PapersCarousel.tsx +++ b/src/components/PapersCarousel.tsx @@ -13,7 +13,6 @@ import { } from "@/components/ui/carousel"; import Autoplay from "embla-carousel-autoplay"; import { chunkArray } from "@/lib/utils/array"; -import { Skeleton } from "@/components/ui/skeleton"; import SkeletonPaperCard from "@/components/SkeletonPaperCard"; import { type ApiResponse } from "@/interface" diff --git a/src/components/ReportTagModal.tsx b/src/components/ReportTagModal.tsx index a04e6944..f056f498 100644 --- a/src/components/ReportTagModal.tsx +++ b/src/components/ReportTagModal.tsx @@ -14,7 +14,7 @@ import { Button } from "@/components/ui/button"; import { MultiSelect } from "@/components/multi-select"; import LabeledInput from "@/components/ui/LabeledInput"; import LabeledSelect from "@/components/ui/LabeledSelect"; -import axios, { AxiosError } from "axios"; +import axios from "axios"; import toast from "react-hot-toast"; import { type ApiResponse } from '@/interface' @@ -54,7 +54,6 @@ const ReportTagModal = ({ const [originalCategoryValues, setOriginalCategoryValues] = useState< Record >({}); - const [originalEmail, setOriginalEmail] = useState(""); const [loading, setLoading] = useState(false); const SCROLL_THRESHOLD = 4; @@ -102,7 +101,7 @@ const ReportTagModal = ({ else if (c === "year" && year) setCategoryValues((s) => ({ ...s, [c]: year })); } - }, [selectedCategories, subject, exam, slot, year]); + }, [selectedCategories, subject, exam, slot, year, categoryValues]); useEffect(() => { if (open) { @@ -121,14 +120,12 @@ const ReportTagModal = ({ if (slot) base.slot = slot; if (year) base.year = year; setOriginalCategoryValues(base); - setOriginalEmail(""); } else { setSelectedCategories([]); setCategoryValues({}); setComment(""); setEmail(""); setOriginalCategoryValues({}); - setOriginalEmail(""); } }, [open, subject, exam, slot, year]); diff --git a/src/components/Searchbar/pinned-searchbar.tsx b/src/components/Searchbar/pinned-searchbar.tsx index 76d3b36b..f70f3b4d 100644 --- a/src/components/Searchbar/pinned-searchbar.tsx +++ b/src/components/Searchbar/pinned-searchbar.tsx @@ -2,7 +2,6 @@ import { useState, useRef, useEffect } from "react"; import { Search } from "lucide-react"; -import { useRouter } from "next/navigation"; import { Input } from "@/components/ui/input"; import PinButton from "../PinButton"; import Fuse from "fuse.js"; @@ -11,7 +10,6 @@ import { type StoredSubjects, type ICourseWithCount, type IUpcomingPaper } from function PinnedSearchBar({ initialSubjects, setDisplayPapers, - displayPapers, filtersNotPulled, }: { initialSubjects: ICourseWithCount[]; @@ -19,7 +17,6 @@ function PinnedSearchBar({ displayPapers : IUpcomingPaper[]; filtersNotPulled?: () => void; }) { - const router = useRouter(); const [searchText, setSearchText] = useState(""); const [suggestions, setSuggestions] = useState([]); const suggestionsRef = useRef(null); @@ -154,11 +151,6 @@ function PinnedSearchBar({ }; }, []); - const handleRemoveAll = () => { - localStorage.setItem("userSubjects", JSON.stringify([])); - window.dispatchEvent(new Event("userSubjectsChanged")); - }; - useEffect(() => { const storedSubjects = JSON.parse( localStorage.getItem("userSubjects") ?? "[]", diff --git a/src/components/Searchbar/searchbar-child.tsx b/src/components/Searchbar/searchbar-child.tsx index f7a855ba..f6170d3c 100644 --- a/src/components/Searchbar/searchbar-child.tsx +++ b/src/components/Searchbar/searchbar-child.tsx @@ -5,7 +5,7 @@ import { Search } from "lucide-react"; import { useRouter } from "next/navigation"; import { Input } from "@/components/ui/input"; import Fuse from "fuse.js"; -import { ICourseWithCount } from "@/interface"; +import { type ICourseWithCount } from "@/interface"; function SearchBarChild({ initialSubjects, diff --git a/src/components/Searchbar/searchbar.tsx b/src/components/Searchbar/searchbar.tsx index 35b30f00..4311147d 100644 --- a/src/components/Searchbar/searchbar.tsx +++ b/src/components/Searchbar/searchbar.tsx @@ -15,7 +15,7 @@ export default function SearchBar({ displayPapers?:IUpcomingPaper[] setDisplayPapers?: React.Dispatch> }) { - const { courses, loading, error, refetch } = useCourses(); + const { courses } = useCourses(); return type === "pinned" && setDisplayPapers !== undefined && displayPapers !== undefined ? ( diff --git a/src/components/UpcomingPaper.tsx b/src/components/UpcomingPaper.tsx index 275fb0b4..b5cba19c 100644 --- a/src/components/UpcomingPaper.tsx +++ b/src/components/UpcomingPaper.tsx @@ -5,8 +5,8 @@ import { import { useRouter } from "next/navigation"; import { Pin } from "lucide-react"; -import React, { useContext, useEffect, useState } from "react"; -import { StoredSubjects } from "@/interface"; +import React, { useEffect, useState } from "react"; +import { type StoredSubjects } from "@/interface"; import { useCourses } from "@/context/courseContext"; import { Capsule } from "@/components/ui/capsule"; @@ -18,7 +18,7 @@ interface PaperCardProps { export default function PaperCard({ subject, slots }: PaperCardProps) { const courseName = extractWithoutBracketContent(subject); const courseCode = extractBracketContent(subject); - const { courses, loading, error, refetch } = useCourses(); + const { courses } = useCourses(); const [pinned, setPinned] = useState(false); const [paperCount, setPaperCount] = useState(0); @@ -54,7 +54,7 @@ export default function PaperCard({ subject, slots }: PaperCardProps) { } else { setPaperCount(0); } - }, [subject, courseName]); + }, [subject, courseName, courses]); const router = useRouter(); return ( diff --git a/src/components/multi-select.tsx b/src/components/multi-select.tsx index ae11f1bb..ac493390 100644 --- a/src/components/multi-select.tsx +++ b/src/components/multi-select.tsx @@ -130,7 +130,6 @@ export const MultiSelect = React.forwardRef< animation = 0, maxCount = 3, modalPopover = false, - asChild = false, className, ...props }, diff --git a/src/components/newPdfViewer.tsx b/src/components/newPdfViewer.tsx index 634765e0..43451247 100644 --- a/src/components/newPdfViewer.tsx +++ b/src/components/newPdfViewer.tsx @@ -311,7 +311,7 @@ function WheelZoom({ documentId, viewerRef }: WheelZoomProps) { viewer.removeEventListener("wheel", handleWheel); if (rafId.current !== null) cancelAnimationFrame(rafId.current); }; - }, [handleWheel]); + }, [handleWheel, viewerRef]); return null; } diff --git a/src/components/screens/Info.tsx b/src/components/screens/Info.tsx index c9f729cb..d3748ea3 100644 --- a/src/components/screens/Info.tsx +++ b/src/components/screens/Info.tsx @@ -4,13 +4,10 @@ import { Check, Filter, Book, - ArrowUpRight, } from "lucide-react"; import Image from "next/image"; -import man from "@/assets/man.svg" assert { type: "image/svg" }; -import man1 from "@/assets/man1.svg" assert { type: "image/svg" }; -import Link from "next/link"; -import { Button } from "@/components/ui/button"; +import man from "@/assets/man.svg" with { type: "image/svg" }; +import man1 from "@/assets/man1.svg" with { type: "image/svg" }; import PWAInstallButton from "../ui/PWAInstallButton"; function Info() { diff --git a/src/components/ui/PWAInstallButton.tsx b/src/components/ui/PWAInstallButton.tsx index 85275d6a..1ed3a3fd 100644 --- a/src/components/ui/PWAInstallButton.tsx +++ b/src/components/ui/PWAInstallButton.tsx @@ -16,7 +16,7 @@ const PWAInstallButton = () => { const [deferredPrompt, setDeferredPrompt] = useState(null); const [canInstall, setCanInstall] = useState(false); - const [isMobile, setIsMobile] = useState(false); + const [, setIsMobile] = useState(false); useEffect(() => { const checkMobile = () => { diff --git a/src/components/ui/PinnedModal.tsx b/src/components/ui/PinnedModal.tsx index e395d085..08c09daf 100644 --- a/src/components/ui/PinnedModal.tsx +++ b/src/components/ui/PinnedModal.tsx @@ -95,7 +95,7 @@ const PinnedModal = ({ page?: string; }) => { const [displayPapers, setDisplayPapers] = useState([]); - const [isLoading, setIsLoading] = useState(true); + const [, setIsLoading] = useState(true); const [open, setOpen] = useState(false); const sensors = useSensors(useSensor(PointerSensor)); diff --git a/src/components/ui/RequestModal.tsx b/src/components/ui/RequestModal.tsx index 7db9911f..dca06d1d 100644 --- a/src/components/ui/RequestModal.tsx +++ b/src/components/ui/RequestModal.tsx @@ -27,12 +27,6 @@ import { exams, slots, years } from "@/components/select_options"; import Fuse from 'fuse.js'; import { useCourses } from "@/context/courseContext"; -type Course = { - name?: string | null; - courseName?: string | null; - title?: string | null; -}; - const RequestModal = ({section = "navbar"} : {section? : string}) => { const [open, setOpen] = useState(false); const [subjects, setSubjects] = useState([]); @@ -43,7 +37,7 @@ const RequestModal = ({section = "navbar"} : {section? : string}) => { const [selectedExam, setSelectedExam] = useState(null); const [selectedSlot, setSelectedSlot] = useState(null); const [selectedYear, setSelectedYear] = useState(null); - const { courses, loading, error, refetch } = useCourses(); + const { courses } = useCourses(); useEffect(() => { setSubjects(courses.map((course) => course.name)); diff --git a/src/context/PaperContext.tsx b/src/context/PaperContext.tsx index 1b511e2c..ea6a1bf8 100644 --- a/src/context/PaperContext.tsx +++ b/src/context/PaperContext.tsx @@ -1,6 +1,6 @@ "use client"; -import { createContext, useContext, ReactNode } from "react"; +import { createContext, useContext, type ReactNode } from "react"; interface PaperContextType { paperId: string; diff --git a/src/context/courseContext.tsx b/src/context/courseContext.tsx index 8c873b38..2e294989 100644 --- a/src/context/courseContext.tsx +++ b/src/context/courseContext.tsx @@ -17,10 +17,6 @@ interface CoursesContextType { refetch: () => Promise; } -interface ApiError { - message?: string; -} - const CoursesContext = createContext(undefined); export function CoursesProvider({ children }: { children: React.ReactNode }) { diff --git a/src/context/filterContext.tsx b/src/context/filterContext.tsx index 69c643c9..57a791f3 100644 --- a/src/context/filterContext.tsx +++ b/src/context/filterContext.tsx @@ -8,7 +8,7 @@ import React, { type ReactNode, } from "react"; import { - ReadonlyURLSearchParams, + type ReadonlyURLSearchParams, useRouter, useSearchParams, } from "next/navigation"; @@ -179,7 +179,7 @@ export const FilterProvider: React.FC = ({ a.remove(); URL.revokeObjectURL(url); toast.success("Download Initiated"); - }, [searchParams, selectedPapers, subject]); + }, [searchParams, selectedPapers]); const handleApplyFilters = useCallback( ( diff --git a/src/db/papers.ts b/src/db/papers.ts index 793c7c1e..c3f8781a 100644 --- a/src/db/papers.ts +++ b/src/db/papers.ts @@ -1,5 +1,5 @@ import mongoose, { Schema, type Model } from "mongoose"; -import { type IPaper, type IAdminPaper, type ICourses } from "@/interface"; +import { type IPaper, type IAdminPaper } from "@/interface"; const adminSchema = new Schema({ file_url: { type: String, required: true }, diff --git a/src/interface.ts b/src/interface.ts index 016128fe..46084ceb 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -1,4 +1,4 @@ -import { mongo } from "mongoose"; +import { type mongo } from "mongoose"; export interface IUpcomingSlot { slot: string; diff --git a/src/lib/services/google-sheets.ts b/src/lib/services/google-sheets.ts index 0adb583b..2c31f2dd 100644 --- a/src/lib/services/google-sheets.ts +++ b/src/lib/services/google-sheets.ts @@ -1,5 +1,5 @@ -import { google, sheets_v4 } from "googleapis"; -import { JWT } from "google-auth-library"; +import { google, type sheets_v4 } from "googleapis"; +import { type JWT } from "google-auth-library"; const SCOPES = ["https://www.googleapis.com/auth/spreadsheets"]; const SHEET_ID = process.env.SHEET_ID; diff --git a/src/lib/services/report.ts b/src/lib/services/report.ts index e0daac31..67e70beb 100644 --- a/src/lib/services/report.ts +++ b/src/lib/services/report.ts @@ -23,7 +23,7 @@ export async function reportTag(paperId: string, body: ReportTagBody) { await connectToDatabase(); const count = await TagReport.countDocuments({ paperId }); - if (count >= 5) { + if (count >= MAX_REPORTS_PER_PAPER) { throw new CustomError("Received many reports; we are currently working on it.", 429) } const reportedFields: ReportedFieldInput[] = Array.isArray(body.reportedFields) diff --git a/src/lib/services/subject.ts b/src/lib/services/subject.ts index b257d39a..e59c072e 100644 --- a/src/lib/services/subject.ts +++ b/src/lib/services/subject.ts @@ -1,5 +1,5 @@ import { connectToDatabase } from "@/lib/database/mongoose"; -import { IRelatedSubject } from "@/interface"; +import { type IRelatedSubject } from "@/interface"; import { escapeRegExp } from "@/lib/utils/regex"; import { Course } from "@/db/course"; import RelatedSubject from "@/db/relatedSubjects"; diff --git a/src/lib/utils/download.ts b/src/lib/utils/download.ts index d8fe573e..e72072ab 100644 --- a/src/lib/utils/download.ts +++ b/src/lib/utils/download.ts @@ -1,4 +1,4 @@ -import { IPaper } from "../../interface"; +import { type IPaper } from "../../interface"; import { extractBracketContent } from "./string"; import axios from "axios"; diff --git a/src/lib/utils/response.ts b/src/lib/utils/response.ts index 41105099..83681d50 100644 --- a/src/lib/utils/response.ts +++ b/src/lib/utils/response.ts @@ -1,5 +1,5 @@ import { NextResponse } from "next/server" -import { ApiResponse } from '@/interface' +import { type ApiResponse } from '@/interface' export const success = ( data: T,