From a9e2e04fe27311eb31a29a278a522adef26933f3 Mon Sep 17 00:00:00 2001 From: Abhinav Pant <67090539+abhitrueprogrammer@users.noreply.github.com> Date: Sun, 10 Aug 2025 12:57:34 +0530 Subject: [PATCH 01/11] Update README.md --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index fc57b13..e6a9026 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,6 @@ - MongoDB & Mongoose : Database and object data modeling (ODM) for Node.js. - Cloudinary : Media storage and optimization service. - Shadcn : Collection of pre-built components using Radix UI and Tailwind CSS. - ## 💡 Features: - Access a vast collection of past CAT and FAT papers From 71338ae8c204db576495fd2e66a016ba811fc41c Mon Sep 17 00:00:00 2001 From: Abhinav Pant <67090539+abhitrueprogrammer@users.noreply.github.com> Date: Mon, 11 Aug 2025 18:56:40 +0530 Subject: [PATCH 02/11] Rename download_paper.tsx to download.tsx --- src/util/{download_paper.tsx => download.tsx} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/util/{download_paper.tsx => download.tsx} (100%) diff --git a/src/util/download_paper.tsx b/src/util/download.tsx similarity index 100% rename from src/util/download_paper.tsx rename to src/util/download.tsx From f2cf1d4c0a5a08e19a44634fd5eaf136b0035210 Mon Sep 17 00:00:00 2001 From: Abhinav Pant <67090539+abhitrueprogrammer@users.noreply.github.com> Date: Mon, 11 Aug 2025 18:57:17 +0530 Subject: [PATCH 03/11] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e6a9026..50b5419 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@

Papers


+ >

Prepare to excel in your CATs and FATs with CodeChef-VIT's dedicated repository of past exam papers. Access key resources to review concepts, tackle challenging questions, and familiarize yourself with exam patterns. Boost your confidence, sharpen your strategy, and get ready to ace your exams!

## 🌐 Deploy From 5724e115e7cff823fd720c1b58df5f7ba3b1ce7b Mon Sep 17 00:00:00 2001 From: abhitrueprogrammer Date: Tue, 12 Aug 2025 01:01:29 +0530 Subject: [PATCH 04/11] light mode --- src/components/CatalogueContent.tsx | 6 +++--- src/components/Navbar.tsx | 6 +++--- src/components/Searchbar/searchbar-child.tsx | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/CatalogueContent.tsx b/src/components/CatalogueContent.tsx index b548b37..a17c8ed 100644 --- a/src/components/CatalogueContent.tsx +++ b/src/components/CatalogueContent.tsx @@ -319,17 +319,17 @@ const CatalogueContent = () => {
-

+

{subject?.split("[")[1]?.replace("]", "")}

-

+

{subject?.split(" [")[0]}

diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 22a54c7..d4ae3b1 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -58,14 +58,14 @@ function Navbar() {
-
+
Pinned Subjects
-
+
Paper Request
@@ -86,7 +86,7 @@ function Navbar() {
-
+
{pathname === "/upload" ? "Search Papers" : "Upload Papers"} diff --git a/src/components/Searchbar/searchbar-child.tsx b/src/components/Searchbar/searchbar-child.tsx index 8d0ed36..b3a83f2 100644 --- a/src/components/Searchbar/searchbar-child.tsx +++ b/src/components/Searchbar/searchbar-child.tsx @@ -145,7 +145,7 @@ function SearchBarChild({
{suggestion} From cebf008c78d6a8a8a4c77f26a9398b6018fa6a9d Mon Sep 17 00:00:00 2001 From: abhitrueprogrammer Date: Tue, 12 Aug 2025 01:41:19 +0530 Subject: [PATCH 05/11] refactor --- ongoing-papers.ts | 43 ---- src/app/api/upload/route.ts | 4 +- src/app/api/user-papers/route.ts | 6 +- src/app/request/page.tsx | 266 ++++++++++++++++++++- src/app/upload/page.tsx | 2 - src/components/Footer.tsx | 12 +- src/components/Navbar.tsx | 4 +- src/components/PapersCarousel.tsx | 19 +- src/components/PinnedPapersCarousel.tsx | 23 +- src/components/SkeletonPaperCard.tsx | 29 +++ src/components/screens/PapersPage.tsx | 296 ------------------------ src/interface.ts | 5 + 12 files changed, 313 insertions(+), 396 deletions(-) delete mode 100644 ongoing-papers.ts create mode 100644 src/components/SkeletonPaperCard.tsx delete mode 100644 src/components/screens/PapersPage.tsx diff --git a/ongoing-papers.ts b/ongoing-papers.ts deleted file mode 100644 index 78fa73f..0000000 --- a/ongoing-papers.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { type IUpcomingPaper } from "@/interface"; - -const papers: IUpcomingPaper[] = [ - { - _id: "6708fd8002a75017a4f08759", - subject: "Discrete Mathematics and Graph Theory [BMAT205L]", - slots: ["A2", "B2"], - }, - { - _id: "670980523ec3fdad83b2d211", - subject: "Compiler Design [BCSE307L]", - slots: ["C1", "D1"], - }, - { - _id: "670a105e6272bcf9da4e2362", - - final_url: - "https://res.cloudinary.com/dtorpaj1c/image/upload/v1728712773/papers/ifkrnjgwdudtev9rxpki.pdf", - thumbnail_url: - "https://res.cloudinary.com/dtorpaj1c/image/upload/w_400,h_400,c_fill/v1728712773/papers/ifkrnjgwdudtev9rxpki.jpg", - subject: "Complex Variables and Linear Algebra [BMAT201L]", - slots: ["A1", "B1"], - year: "2023", - exam: "CAT-2", - semester: "Fall Semester", - campus: "Vellore", - }, - { - _id: "67097e7b3ec3fdad83b2d205", - final_url: - "https://res.cloudinary.com/dtorpaj1c/image/upload/v1728675439/papers/pyyqotz1mzuh2wmq1k9s.pdf", - thumbnail_url: - "https://res.cloudinary.com/dtorpaj1c/image/upload/w_400,h_400,c_fill/v1728675439/papers/pyyqotz1mzuh2wmq1k9s.jpg", - subject: "Computer Networks [BCSE308L]", - slots: ["C2", "D2"], - year: "2023", - exam: "CAT-2", - semester: "Fall Semester", - campus: "Vellore", - }, -]; - -export default papers; diff --git a/src/app/api/upload/route.ts b/src/app/api/upload/route.ts index aee166c..571bbb9 100644 --- a/src/app/api/upload/route.ts +++ b/src/app/api/upload/route.ts @@ -181,5 +181,7 @@ async function CreatePDF(orderedFiles: File[]) { } const mergedPdfBytes = await pdfDoc.save(); - return mergedPdfBytes; + const ab = new ArrayBuffer(mergedPdfBytes.byteLength); + new Uint8Array(ab).set(mergedPdfBytes); + return ab; } diff --git a/src/app/api/user-papers/route.ts b/src/app/api/user-papers/route.ts index cc92e18..9f1ba6b 100644 --- a/src/app/api/user-papers/route.ts +++ b/src/app/api/user-papers/route.ts @@ -1,14 +1,10 @@ import { NextResponse } from "next/server"; import { connectToDatabase } from "@/lib/mongoose"; import Paper from "@/db/papers"; -import { StoredSubjects } from "@/interface"; +import { StoredSubjects, TransformedPaper } from "@/interface"; export const dynamic = "force-dynamic"; -interface TransformedPaper { - subject: string; - slots: string[]; -} export async function POST(req: Request) { try { diff --git a/src/app/request/page.tsx b/src/app/request/page.tsx index 0efe95d..61cb247 100644 --- a/src/app/request/page.tsx +++ b/src/app/request/page.tsx @@ -1,5 +1,265 @@ -import PapersPage from "@/components/screens/PapersPage"; +"use client"; -export default function RequestPage() { - return ; +import { useEffect, useState, useRef, useMemo } from "react"; +import { Button } from "@/components/ui/button"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { exams, slots, years } from "@/components/select_options"; +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"; +import SkeletonPaperCard from "@/components/SkeletonPaperCard"; + +type Course = { + name?: string | null; + courseName?: string | null; + title?: string | null; +}; + +export default function PaperRequest() { + const [subjects, setSubjects] = useState([]); + const [searchText, setSearchText] = useState(""); + const [suggestions, setSuggestions] = useState([]); + const [selectedSubject, setSelectedSubject] = useState(null); + const [selectedExam, setSelectedExam] = useState(null); + const [selectedSlot, setSelectedSlot] = useState(null); + const [selectedYear, setSelectedYear] = useState(null); + const suggestionsRef = useRef(null); + const [displayPapers, setDisplayPapers] = useState([]); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + async function fetchSubjects() { + try { + const response = await axios.get(`/api/course-list`); + const courses: Course[] = response.data; + const names = courses + .map((course) => course.name ?? course.courseName ?? course.title) + .filter(Boolean) as string[]; + + setSubjects(names); + } catch (err) { + console.error("Error fetching subjects:", err); + } + } + void fetchSubjects(); + }, []); + + useEffect(() => { + async function fetchPapers() { + try { + setIsLoading(true); + const response = await axios.get( + "/api/upcoming-papers", + ); + + const randomPapers = [...response.data] + .sort(() => Math.random() - 0.5) + .slice(0, 4); + + setDisplayPapers(randomPapers); + } catch (error) { + console.error("Failed to fetch papers:", error); + } finally { + setIsLoading(false); + } + } + + void fetchPapers(); + }, []); + + const fuse = useMemo( + () => new Fuse(subjects, { includeScore: true, threshold: 0.3 }), + [subjects], + ); + + useEffect(() => { + if (!searchText.trim()) { + setSuggestions([]); + return; + } + + if (selectedSubject && searchText === selectedSubject) { + setSuggestions([]); + return; + } + + const results = fuse.search(searchText); + setSuggestions(results.map((r) => r.item).slice(0, 10)); + }, [searchText, fuse, selectedSubject]); + + const handleSelectSubject = (subject: string) => { + setSelectedSubject(subject); + setSearchText(subject); + setSuggestions([]); + setSelectedExam(null); + setSelectedSlot(null); + setSelectedYear(null); + }; + + useEffect(() => { + function handleClickOutside(event: MouseEvent) { + if ( + suggestionsRef.current && + !suggestionsRef.current.contains(event.target as Node) + ) { + setSuggestions([]); + } + } + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); + + const handleSubmit = async () => { + if (!selectedSubject || !selectedExam || !selectedSlot || !selectedYear) { + toast.error("Please fill all fields before submitting."); + return; + } + + try { + await axios.post("/api/request", { + subject: selectedSubject, + exam: selectedExam, + slot: selectedSlot, + year: selectedYear, + }); + + alert("✅ Your paper request was submitted successfully 🎉"); + + setSearchText(""); + setSelectedSubject(null); + setSelectedExam(null); + setSelectedSlot(null); + setSelectedYear(null); + } catch (error) { + console.error("Error submitting request:", error); + alert("❌ Failed to submit your request. Please try again later."); + } + }; + + return ( +
+
+
+

+ Specific Paper Request +

+ +
+ setSearchText(e.target.value)} + placeholder="Search by subject..." + className={`text-md rounded-lg bg-[#B2B8FF] px-4 py-6 pr-10 font-play tracking-wider text-black shadow-sm ring-0 placeholder:text-black focus:outline-none focus:ring-0 dark:bg-[#7480FF66] dark:text-white placeholder:dark:text-white ${suggestions.length > 0 ? "rounded-b-none" : ""}`} + /> + + {suggestions.length > 0 && ( +
    + {suggestions.map((s, idx) => ( +
  • handleSelectSubject(s)} + className="cursor-pointer truncate p-2 hover:bg-gray-100 dark:hover:bg-gray-800" + > + {s} +
  • + ))} +
+ )} +
+ +
+ + + +
+ + +
+ +
+ {isLoading ? ( + + ) : ( + displayPapers.map((paper, subIndex) => ( +
+ +
+ )) + )} +
+
+
+ ); } diff --git a/src/app/upload/page.tsx b/src/app/upload/page.tsx index 5d88ddb..7ccfae6 100644 --- a/src/app/upload/page.tsx +++ b/src/app/upload/page.tsx @@ -140,9 +140,7 @@ const Page = () => { await toast.promise( async () => { try { - console.log("this is happening now"); await axios.post("/api/upload", formData); - console.log("this is happening after now"); return { message: "Papers uploaded successfully!" }; } catch (error) { if (error instanceof AxiosError && error.response?.data) { diff --git a/src/components/Footer.tsx b/src/components/Footer.tsx index 5bc0c5a..587ad11 100644 --- a/src/components/Footer.tsx +++ b/src/components/Footer.tsx @@ -96,17 +96,17 @@ export default function Footer() { {/* Events */}

Events

- DevSoc - CookOff - Clueminati + DevSoc + CookOff + Clueminati
{/* Projects */}

Our Projects

- Papers - Contactify - FFCS-inator + Papers + Contactify + FFCS-inator
{/* Suggestions */} diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index d4ae3b1..6ce6598 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -40,14 +40,14 @@ function Navbar() {
- + codechef-logo - + ([]); @@ -78,23 +79,7 @@ function PapersCarousel() { chunkSize === 4 ? "grid-cols-2 grid-rows-2" : "grid-cols-4" } gap-4 lg:auto-rows-fr`} > - {Array.from({ length: chunkSize }).map((_, idx) => ( -
-
- -
-
- -
- - -
-
-
- ))} + ) : ( chunkedPapers.map((paperGroup, index) => { diff --git a/src/components/PinnedPapersCarousel.tsx b/src/components/PinnedPapersCarousel.tsx index 449cd41..bd475bd 100644 --- a/src/components/PinnedPapersCarousel.tsx +++ b/src/components/PinnedPapersCarousel.tsx @@ -17,6 +17,7 @@ import AddPapers from "./AddPapers"; import Autoplay from "embla-carousel-autoplay"; import { chunkArray } from "@/util/utils"; import { StoredSubjects } from "@/interface"; +import SkeletonPaperCard from "./SkeletonPaperCard"; function PinnedPapersCarousel({ carouselType = "upcoming", @@ -54,15 +55,11 @@ function PinnedPapersCarousel({ localStorage.getItem("userSubjects") ?? "[]", ) as StoredSubjects; - console.log("Fetching papers for subjects:", storedSubjects); - const response = await axios.post<{ subject: string; slots: string[] }[]>( "/api/user-papers", storedSubjects, ); - console.log("Fetched papers:", response.data); - const fetchedPapers = response.data; const fetchedSubjectsSet = new Set( @@ -131,23 +128,7 @@ function PinnedPapersCarousel({ chunkSize === 4 ? "grid-cols-2 grid-rows-2" : "grid-cols-4" } gap-4 lg:auto-rows-fr`} > - {Array.from({ length: chunkSize }).map((_, idx) => ( -
-
- -
-
- -
- - -
-
-
- ))} + ) : ( chunkedPapers.map((paperGroup, index) => { diff --git a/src/components/SkeletonPaperCard.tsx b/src/components/SkeletonPaperCard.tsx new file mode 100644 index 0000000..bcc50fc --- /dev/null +++ b/src/components/SkeletonPaperCard.tsx @@ -0,0 +1,29 @@ +import { Skeleton } from "@/components/ui/skeleton"; + +interface SkeletonPaperCardProps { + length?: number; +} + +export default function SkeletonPaperCard({ length = 4 }: SkeletonPaperCardProps) { + return ( + <> + {Array.from({ length }).map((_, idx) => ( +
+
+ +
+
+ +
+ + +
+
+
+ ))} + + ); +} diff --git a/src/components/screens/PapersPage.tsx b/src/components/screens/PapersPage.tsx deleted file mode 100644 index 60702e4..0000000 --- a/src/components/screens/PapersPage.tsx +++ /dev/null @@ -1,296 +0,0 @@ -"use client"; - -import { useEffect, useState, useRef, useMemo } from "react"; -import { Button } from "@/components/ui/button"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; -import { exams, slots, years } from "@/components/select_options"; -import { Input } from "@/components/ui/input"; -import axios from "axios"; -import Fuse from "fuse.js"; -import { ArrowRight } from "lucide-react"; -import Image from "next/image"; -import { IUpcomingPaper } from "@/interface"; -import { Skeleton } from "../ui/skeleton"; -import { CarouselItem } from "@/components/ui/carousel"; -import UpcomingPaper from "../UpcomingPaper"; - -type Course = { - name?: string | null; - courseName?: string | null; - title?: string | null; -}; - -export default function PapersPage() { - const [subjects, setSubjects] = useState([]); - const [searchText, setSearchText] = useState(""); - const [suggestions, setSuggestions] = useState([]); - const [selectedSubject, setSelectedSubject] = useState(null); - const [selectedExam, setSelectedExam] = useState(null); - const [selectedSlot, setSelectedSlot] = useState(null); - const [selectedYear, setSelectedYear] = useState(null); - const suggestionsRef = useRef(null); - const [displayPapers, setDisplayPapers] = useState([]); - const [isLoading, setIsLoading] = useState(true); - - useEffect(() => { - async function fetchSubjects() { - try { - const response = await axios.get(`/api/course-list`); - const courses: Course[] = response.data; - const names = courses - .map((course) => course.name ?? course.courseName ?? course.title) - .filter(Boolean) as string[]; - - setSubjects(names); - } catch (err) { - console.error("Error fetching subjects:", err); - } - } - void fetchSubjects(); - }, []); - - useEffect(() => { - async function fetchPapers() { - try { - setIsLoading(true); - const response = await axios.get( - "/api/upcoming-papers", - ); - - const randomPapers = [...response.data] - .sort(() => Math.random() - 0.5) - .slice(0, 4); - - setDisplayPapers(randomPapers); - } catch (error) { - console.error("Failed to fetch papers:", error); - } finally { - setIsLoading(false); - } - } - - void fetchPapers(); - }, []); - - const fuse = useMemo( - () => new Fuse(subjects, { includeScore: true, threshold: 0.3 }), - [subjects], - ); - - useEffect(() => { - if (!searchText.trim()) { - setSuggestions([]); - return; - } - - if (selectedSubject && searchText === selectedSubject) { - setSuggestions([]); - return; - } - - const results = fuse.search(searchText); - setSuggestions(results.map((r) => r.item).slice(0, 10)); - }, [searchText, fuse, selectedSubject]); - - const handleSelectSubject = (subject: string) => { - setSelectedSubject(subject); - setSearchText(subject); - setSuggestions([]); - setSelectedExam(null); - setSelectedSlot(null); - setSelectedYear(null); - }; - - useEffect(() => { - function handleClickOutside(event: MouseEvent) { - if ( - suggestionsRef.current && - !suggestionsRef.current.contains(event.target as Node) - ) { - setSuggestions([]); - } - } - document.addEventListener("mousedown", handleClickOutside); - return () => document.removeEventListener("mousedown", handleClickOutside); - }, []); - - const handleSubmit = async () => { - if (!selectedSubject || !selectedExam || !selectedSlot || !selectedYear) { - alert("⚠️ Please fill all fields before submitting."); - return; - } - - try { - await axios.post("/api/request", { - subject: selectedSubject, - exam: selectedExam, - slot: selectedSlot, - year: selectedYear, - }); - - alert("✅ Your paper request was submitted successfully 🎉"); - - setSearchText(""); - setSelectedSubject(null); - setSelectedExam(null); - setSelectedSlot(null); - setSelectedYear(null); - } catch (error) { - console.error("Error submitting request:", error); - alert("❌ Failed to submit your request. Please try again later."); - } - }; - - return ( -
-
-
-

- Specific Paper Request -

- -
- setSearchText(e.target.value)} - placeholder="Search by subject..." - className={`text-md rounded-lg bg-[#B2B8FF] px-4 py-6 pr-10 font-play tracking-wider text-black shadow-sm ring-0 placeholder:text-black focus:outline-none focus:ring-0 dark:bg-[#7480FF66] dark:text-white placeholder:dark:text-white ${suggestions.length > 0 ? "rounded-b-none" : ""}`} - /> - - {suggestions.length > 0 && ( -
    - {suggestions.map((s, idx) => ( -
  • handleSelectSubject(s)} - className="cursor-pointer truncate p-2 hover:bg-gray-100 dark:hover:bg-gray-800" - > - {s} -
  • - ))} -
- )} -
- -
- - - -
- - -
- -
- {isLoading - ? Array.from({ length: 4 }).map((_, idx) => ( -
- {/* Top section */} -
- - -
- - {/* Middle section */} -
- -
- - -
-
-
- )) - : displayPapers.map((paper, subIndex) => ( -
- -
- ))} -
-
-
- ); -} diff --git a/src/interface.ts b/src/interface.ts index 74bcfca..2ee6030 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -204,3 +204,8 @@ export interface Filters { export interface StoredSubjects { subjects: string[]; } + +export interface TransformedPaper { + subject: string; + slots: string[]; +} From 10ca176a7c040393c222ace416e683c7c75184b7 Mon Sep 17 00:00:00 2001 From: abhitrueprogrammer Date: Tue, 12 Aug 2025 13:20:31 +0530 Subject: [PATCH 06/11] alert -> toast --- src/app/request/page.tsx | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/app/request/page.tsx b/src/app/request/page.tsx index 61cb247..f215103 100644 --- a/src/app/request/page.tsx +++ b/src/app/request/page.tsx @@ -127,14 +127,19 @@ export default function PaperRequest() { } try { - await axios.post("/api/request", { - subject: selectedSubject, - exam: selectedExam, - slot: selectedSlot, - year: selectedYear, - }); - - alert("✅ Your paper request was submitted successfully 🎉"); + await toast.promise( + axios.post("/api/request", { + subject: selectedSubject, + exam: selectedExam, + slot: selectedSlot, + year: selectedYear, + }), + { + loading: "Submitting your request...", + success: "Your paper request was submitted successfully", + error: "Failed to submit your request. Please try again later.", + } + ); setSearchText(""); setSelectedSubject(null); @@ -143,7 +148,6 @@ export default function PaperRequest() { setSelectedYear(null); } catch (error) { console.error("Error submitting request:", error); - alert("❌ Failed to submit your request. Please try again later."); } }; From d77d08bdad57b4e0d180c3069c859bd3683cb1c1 Mon Sep 17 00:00:00 2001 From: abhitrueprogrammer Date: Tue, 12 Aug 2025 15:28:43 +0530 Subject: [PATCH 07/11] mongo db multiple connections fix --- src/lib/mongoose.ts | 48 +++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/src/lib/mongoose.ts b/src/lib/mongoose.ts index 7f129fe..7be32c3 100644 --- a/src/lib/mongoose.ts +++ b/src/lib/mongoose.ts @@ -1,27 +1,41 @@ import mongoose from "mongoose"; - -if (!process.env.MONGODB_URI) { - throw new Error("Please add your Mongo URI to .env.local"); +declare global { + // eslint-disable-next-line no-var + var mongoose: { conn: mongoose.Mongoose | null; promise: Promise | null } | undefined; // This must be a `var` and not a `let / const` } -const uri = process.env.MONGODB_URI; +let cached = global.mongoose; -let isConnected = false; +cached ??= global.mongoose = { conn: null, promise: null }; -export const connectToDatabase = async () => { - if (isConnected) { - return; - } +export async function connectToDatabase() { + const MONGODB_URI = process.env.MONGODB_URI!; - if (mongoose.connection.readyState === mongoose.ConnectionStates.connected) { - isConnected = true; - return; + if (!MONGODB_URI) { + throw new Error( + "Please define the MONGODB_URI environment variable inside .env.local", + ); } + if (cached?.conn) { + return cached.conn; + } + if (cached && !cached.promise) { + const opts = { + bufferCommands: false, + }; + cached.promise = mongoose.connect(MONGODB_URI, opts).then((mongoose) => { + return mongoose; + }); + } try { - await mongoose.connect(uri); - isConnected = true; - } catch (error) { - throw new Error("Failed to connect to MongoDB"); + cached!.conn = await cached!.promise; + } catch (e) { + if (cached) { + cached.promise = null; + } + throw e; } -}; + + return cached?.conn; +} From 023a0ddc28f834085d91991edf1f5b00a045fe21 Mon Sep 17 00:00:00 2001 From: abhitrueprogrammer Date: Wed, 13 Aug 2025 03:28:39 +0530 Subject: [PATCH 08/11] feat: related subs --- src/app/api/related-subject/route.ts | 41 ++++++++++++++++ src/components/CatalogueContent.tsx | 73 +++++++++++++++++++++------- src/db/relatedSubjects.ts | 14 ++++++ src/interface.ts | 6 +++ 4 files changed, 117 insertions(+), 17 deletions(-) create mode 100644 src/app/api/related-subject/route.ts create mode 100644 src/db/relatedSubjects.ts diff --git a/src/app/api/related-subject/route.ts b/src/app/api/related-subject/route.ts new file mode 100644 index 0000000..1640f9e --- /dev/null +++ b/src/app/api/related-subject/route.ts @@ -0,0 +1,41 @@ +import { NextResponse, type NextRequest } from "next/server"; +import { connectToDatabase } from "@/lib/mongoose"; +import { IRelatedSubject } from "@/interface"; +import RelatedSubject from "@/db/relatedSubjects"; + +export const dynamic = "force-dynamic"; + +export async function GET(req: NextRequest) { + try { + await connectToDatabase(); + const url = req.nextUrl.searchParams; + const subject = url.get("subject"); + const escapeRegExp = (text: string) => { + return text.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); + }; + const escapedSubject = escapeRegExp(subject ?? ""); + + if (!subject) { + return NextResponse.json( + { message: "Subject query parameter is required" }, + { status: 400 }, + ); + } + const subjects: IRelatedSubject[] = await RelatedSubject.find({ + subject: { $regex: new RegExp(`${escapedSubject}`, "i") }, + }); + console.log("realted", subjects); + + return NextResponse.json( + { + related_subjects: subjects[0]?.related_subjects + }, + { status: 200 }, + ); + } catch (error) { + return NextResponse.json( + { message: "Failed to fetch related subject", error }, + { status: 500 }, + ); + } +} diff --git a/src/components/CatalogueContent.tsx b/src/components/CatalogueContent.tsx index a17c8ed..8891ca7 100644 --- a/src/components/CatalogueContent.tsx +++ b/src/components/CatalogueContent.tsx @@ -4,7 +4,7 @@ import { useSearchParams } from "next/navigation"; import { useCallback, useEffect, useState } from "react"; import axios, { type AxiosError } from "axios"; import { Button } from "@/components/ui/button"; -import { type IPaper, type Filters } from "@/interface"; +import { type IPaper, type Filters, IRelatedSubject, StoredSubjects } from "@/interface"; import Card from "./Card"; import { useRouter } from "next/navigation"; import Loader from "./ui/loader"; @@ -13,8 +13,8 @@ import Error from "./Error"; import { Filter } from "lucide-react"; import { Sheet, SheetContent, SheetTrigger } from "./ui/sheet"; import { Pin } from "lucide-react"; -import { StoredSubjects } from "@/interface"; import { getSecureUrl, generateFileName, downloadFile } from "@/util/download"; +import Link from "next/link"; const CatalogueContent = () => { const router = useRouter(); @@ -39,6 +39,29 @@ const CatalogueContent = () => { const [filtersPulled, setFiltersPulled] = useState(false); const [appliedFilters, setAppliedFilters] = useState(false); const [pinned, setPinned] = useState(false); + const [relatedSubjects, setRelatedSubjects] = useState([]); + // Fetch related subjects when subject changes + useEffect(() => { + if (!subject) return; + const fetchRelatedSubjects = async () => { + try { + const res = await axios.get<{related_subjects: string []}>("/api/related-subject", { + params: { subject }, + }); + console.log(res.data) + const data = res.data.related_subjects; + console.log("data" , data[0], data[1]); + if (data && data.length > 0) { + setRelatedSubjects(data); + } else { + setRelatedSubjects([]); + } + } catch (e) { + setRelatedSubjects([]); + } + }; + void fetchRelatedSubjects(); + }, [subject]); // Set initial state from searchParams on client-side mount useEffect(() => { @@ -317,22 +340,38 @@ const CatalogueContent = () => { -
-
-

- {subject?.split("[")[1]?.replace("]", "")} -

-

- {subject?.split(" [")[0]} -

-
-
- +
+
+
+

+ {subject?.split("[")[1]?.replace("]", "")} +

+

+ {subject?.split(" [")[0]} +

+
+
+ +
+ {relatedSubjects.length > 0 && ( +
+ Related subjects: + {relatedSubjects.map((sub) => ( + + {sub} + + ))} +
+ )}
{loading ? ( diff --git a/src/db/relatedSubjects.ts b/src/db/relatedSubjects.ts new file mode 100644 index 0000000..c9a4c27 --- /dev/null +++ b/src/db/relatedSubjects.ts @@ -0,0 +1,14 @@ +import mongoose, { Schema, type Model } from "mongoose"; +import { type IRelatedSubject } from "@/interface"; + + +const relatedSubjectSchema = new Schema({ + subject: { type: String, required: true }, + related_subjects: { type: [String], required: true }, +}); + +const RelatedSubject: Model = + mongoose.models.RelatedSubject ?? + mongoose.model("RelatedSubject", relatedSubjectSchema); + +export default RelatedSubject; diff --git a/src/interface.ts b/src/interface.ts index 2ee6030..c8362da 100644 --- a/src/interface.ts +++ b/src/interface.ts @@ -209,3 +209,9 @@ export interface TransformedPaper { subject: string; slots: string[]; } + + +export interface IRelatedSubject { + subject: string; + related_subjects: string[]; +} \ No newline at end of file From 971dab05cfa6898cdf5e8f170933cd714c97d817 Mon Sep 17 00:00:00 2001 From: Noscope999 Date: Wed, 13 Aug 2025 22:38:57 +0530 Subject: [PATCH 09/11] fix: added back searchbar into navbar and added dropdown for buttons --- src/components/Navbar.tsx | 107 +++++++++++++++++++++++++++++--------- 1 file changed, 81 insertions(+), 26 deletions(-) diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 6ce6598..5af7733 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -6,17 +6,27 @@ import Link from "next/link"; import { usePathname } from "next/navigation"; import ccLogo from "../assets/codechef_logo.svg"; import ModeToggle from "@/components/toggle-theme"; -import { Button } from "@/components/ui/button"; import { ArrowDownLeftIcon, Pin, ArrowUpRight } from "lucide-react"; import NavDropdownButton from "./NavDropdownButton"; import FloatingNavbar from "./FloatingNavbar"; import PWAInstallButton from "./ui/PWAInstallButton"; +import SearchBarChild from "./Searchbar/searchbar-child"; function Navbar() { const pathname = usePathname(); const [open, setOpen] = useState(false); + const [subjects, setSubjects] = useState([]); const dropdownContainerRef = useRef(null); + useEffect(() => { + async function getSubjects() { + const res = await fetch("/api/course-list"); + const data = await res.json(); + setSubjects(data.map((course: { name: string }) => course.name)); + } + if (pathname === "/catalogue") getSubjects(); + }, [pathname]); + useEffect(() => { function handleClickOutside(event: MouseEvent) { if ( @@ -36,11 +46,29 @@ function Navbar() { }; }, [open]); + + const renderHomePageButtons = () => ( + <> + +
+ + Pinned Subjects +
+ + +
+ + Paper Request +
+ + + ); + return (
-
- +
+ codechef-logo -
- -
- - Pinned Subjects -
- -
- -
- - Paper Request + {pathname === "/catalogue" ? ( +
+ setOpen((prev) => !prev)} + variant="default" + /> + {open && ( +
+
+ + + + + + +
- + )}
-
- - {/* Desktop: Create Paper Request button */} + ) : ( +
+ {renderHomePageButtons()} +
+ )}
+ {pathname === "/catalogue" && ( +
+
+ +
+
+ )} +
-
- -
+
{pathname === "/upload" ? "Search Papers" : "Upload Papers"} @@ -95,16 +151,15 @@ function Navbar() {
- {/* Mobile: Create Paper Request button inside dropdown */}
setOpen((prev) => !prev)} + variant="default" />
setOpen(false)} />
From 859190a57970e5628798612e50c2b7189fcb72d3 Mon Sep 17 00:00:00 2001 From: Noscope999 Date: Thu, 14 Aug 2025 22:14:25 +0530 Subject: [PATCH 10/11] Used shadCN component for dropdown menu --- package.json | 1 + pnpm-lock.yaml | 381 +++++++++++++++++++++++++++- src/components/Navbar.tsx | 110 +++----- src/components/ui/dropdown-menu.tsx | 200 +++++++++++++++ 4 files changed, 616 insertions(+), 76 deletions(-) create mode 100644 src/components/ui/dropdown-menu.tsx diff --git a/package.json b/package.json index d913dcd..ce335f4 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "dependencies": { "@radix-ui/react-accordion": "^1.2.4", "@radix-ui/react-dialog": "^1.1.7", + "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-popover": "^1.1.7", "@radix-ui/react-select": "^2.1.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 96894a1..2fae401 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,6 +14,9 @@ importers: '@radix-ui/react-dialog': specifier: ^1.1.7 version: 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-dropdown-menu': + specifier: ^2.1.16 + version: 2.1.16(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-icons': specifier: ^1.3.2 version: 1.3.2(react@18.3.1) @@ -369,6 +372,9 @@ packages: '@radix-ui/primitive@1.1.2': resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==} + '@radix-ui/primitive@1.1.3': + resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} + '@radix-ui/react-accordion@1.2.4': resolution: {integrity: sha512-SGCxlSBaMvEzDROzyZjsVNzu9XY5E28B3k8jOENyrz6csOv/pG1eHyYfLJai1n9tRjwG61coXDhfpgtxKxUv5g==} peerDependencies: @@ -395,6 +401,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-arrow@1.1.7': + resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-collapsible@1.1.4': resolution: {integrity: sha512-u7LCw1EYInQtBNLGjm9nZ89S/4GcvX1UR5XbekEgnQae2Hkpq39ycJ1OhdeN1/JDfVNG91kWaWoest127TaEKQ==} peerDependencies: @@ -421,6 +440,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-collection@1.1.7': + resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-compose-refs@1.0.1': resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -505,6 +537,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-dismissable-layer@1.1.11': + resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-dismissable-layer@1.1.6': resolution: {integrity: sha512-7gpgMT2gyKym9Jz2ZhlRXSg2y6cNQIK8d/cqBZ0RBCaps8pFryCWXiUKI+uHGFrhMrbGUP7U6PWgiXzIxoyF3Q==} peerDependencies: @@ -518,6 +563,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-dropdown-menu@2.1.16': + resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-focus-guards@1.0.1': resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} peerDependencies: @@ -536,6 +594,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-focus-guards@1.1.3': + resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-focus-scope@1.0.4': resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==} peerDependencies: @@ -562,6 +629,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-focus-scope@1.1.7': + resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-icons@1.3.2': resolution: {integrity: sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==} peerDependencies: @@ -585,6 +665,19 @@ packages: '@types/react': optional: true + '@radix-ui/react-menu@2.1.16': + resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-popover@1.1.7': resolution: {integrity: sha512-I38OYWDmJF2kbO74LX8UsFydSHWOJuQ7LxPnTefjxxvdvPLempvAnmsyX9UsBlywcbSGpRH7oMLfkUf+ij4nrw==} peerDependencies: @@ -611,6 +704,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-popper@1.2.8': + resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-portal@1.0.4': resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} peerDependencies: @@ -637,6 +743,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-portal@1.1.9': + resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-presence@1.0.1': resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} peerDependencies: @@ -663,6 +782,19 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-presence@1.1.5': + resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-primitive@1.0.3': resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} peerDependencies: @@ -689,6 +821,32 @@ packages: '@types/react-dom': optional: true + '@radix-ui/react-primitive@2.1.3': + resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-roving-focus@1.1.11': + resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-select@2.1.7': resolution: {integrity: sha512-exzGIRtc7S8EIM2KjFg+7lJZsH7O7tpaBaJbBNVDnOZNhtoQ2iV+iSNfi2Wth0m6h3trJkMVvzAehB3c6xj/3Q==} peerDependencies: @@ -733,6 +891,15 @@ packages: '@types/react': optional: true + '@radix-ui/react-slot@1.2.3': + resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-switch@1.1.4': resolution: {integrity: sha512-zGP6W8plLeogoeGMiTHJ/uvf+TE1C2chVsEwfP8YlvpQKJHktG+iCkUtCLGPAuDV8/qDSmIRPm4NggaTxFMVBQ==} peerDependencies: @@ -782,6 +949,24 @@ packages: '@types/react': optional: true + '@radix-ui/react-use-controllable-state@1.2.2': + resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-effect-event@0.0.2': + resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@radix-ui/react-use-escape-keydown@1.0.3': resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} peerDependencies: @@ -3517,6 +3702,8 @@ snapshots: '@radix-ui/primitive@1.1.2': {} + '@radix-ui/primitive@1.1.3': {} + '@radix-ui/react-accordion@1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -3543,6 +3730,15 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-collapsible@1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -3571,6 +3767,18 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-collection@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.20)(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -3662,6 +3870,19 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-dismissable-layer@1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -3675,6 +3896,21 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-menu': 2.1.16(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.20)(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -3688,6 +3924,12 @@ snapshots: optionalDependencies: '@types/react': 18.3.20 + '@radix-ui/react-focus-guards@1.1.3(@types/react@18.3.20)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.20 + '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -3711,6 +3953,17 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-icons@1.3.2(react@18.3.1)': dependencies: react: 18.3.1 @@ -3730,6 +3983,32 @@ snapshots: optionalDependencies: '@types/react': 18.3.20 + '@radix-ui/react-menu@2.1.16(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) + aria-hidden: 1.2.4 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.6.3(@types/react@18.3.20)(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-popover@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -3771,6 +4050,24 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-popper@1.2.8(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-arrow': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/rect': 1.1.1 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -3791,6 +4088,16 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-portal@1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -3812,6 +4119,16 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-presence@1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -3831,6 +4148,32 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-primitive@2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + + '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.20 + '@types/react-dom': 18.3.6(@types/react@18.3.20) + '@radix-ui/react-select@2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.1 @@ -3884,6 +4227,13 @@ snapshots: optionalDependencies: '@types/react': 18.3.20 + '@radix-ui/react-slot@1.2.3(@types/react@18.3.20)(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.20 + '@radix-ui/react-switch@1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -3927,6 +4277,21 @@ snapshots: optionalDependencies: '@types/react': 18.3.20 + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.20)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.20)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.20 + + '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.20)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.20 + '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.20)(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -4840,8 +5205,8 @@ snapshots: '@typescript-eslint/parser': 8.30.1(eslint@8.57.1)(typescript@5.8.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.5(eslint@8.57.1) eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.57.1) @@ -4860,7 +5225,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1): + eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0 @@ -4871,22 +5236,22 @@ snapshots: tinyglobby: 0.2.12 unrs-resolver: 1.5.0 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.30.1(eslint@8.57.1)(typescript@5.8.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -4897,7 +5262,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index 5af7733..f640cc7 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,22 +1,26 @@ "use client"; -import { useState, useRef, useEffect } from "react"; +import { useState, useEffect } from "react"; import Image 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 } from "lucide-react"; -import NavDropdownButton from "./NavDropdownButton"; +import { ArrowDownLeftIcon, Pin, ArrowUpRight, ChevronDown } from "lucide-react"; import FloatingNavbar from "./FloatingNavbar"; import PWAInstallButton from "./ui/PWAInstallButton"; import SearchBarChild from "./Searchbar/searchbar-child"; +import { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, +} from "@/components/ui/dropdown-menu"; function Navbar() { const pathname = usePathname(); - const [open, setOpen] = useState(false); const [subjects, setSubjects] = useState([]); - const dropdownContainerRef = useRef(null); + const [dropdownOpen, setDropdownOpen] = useState(false); useEffect(() => { async function getSubjects() { @@ -27,26 +31,6 @@ function Navbar() { if (pathname === "/catalogue") getSubjects(); }, [pathname]); - useEffect(() => { - function handleClickOutside(event: MouseEvent) { - if ( - dropdownContainerRef.current && - !dropdownContainerRef.current.contains(event.target as Node) - ) { - setOpen(false); - } - } - - if (open) { - document.addEventListener("mousedown", handleClickOutside); - } - - return () => { - document.removeEventListener("mousedown", handleClickOutside); - }; - }, [open]); - - const renderHomePageButtons = () => ( <> @@ -85,39 +69,39 @@ function Navbar() { {pathname === "/catalogue" ? ( -
- setOpen((prev) => !prev)} - variant="default" - /> - {open && ( -
-
- - +
+ + + + + + + + + + Pinned Subjects - - + + + + + Paper Request -
-
- )} + + +
) : (
@@ -151,18 +135,8 @@ function Navbar() {
-
- setOpen((prev) => !prev)} - variant="default" - /> -
- setOpen(false)} /> -
+
+ { }} />
diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000..4fc75b2 --- /dev/null +++ b/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,200 @@ +"use client" + +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { cn } from "@/lib/utils" +import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "@radix-ui/react-icons" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + svg]:size-4 [&>svg]:shrink-0", + inset && "pl-8", + className + )} + {...props} + /> +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} From 501d7ae4c82ff5c4ed0ba5e871b1df0e33a9db99 Mon Sep 17 00:00:00 2001 From: Abhinav Pant <67090539+abhitrueprogrammer@users.noreply.github.com> Date: Fri, 15 Aug 2025 01:24:48 +0530 Subject: [PATCH 11/11] Revert "fix: added back searchbar into navbar and added dropdown for buttons" --- package.json | 1 - pnpm-lock.yaml | 381 +--------------------------- src/components/Navbar.tsx | 141 ++++------ src/components/ui/dropdown-menu.tsx | 200 --------------- 4 files changed, 64 insertions(+), 659 deletions(-) delete mode 100644 src/components/ui/dropdown-menu.tsx diff --git a/package.json b/package.json index ce335f4..d913dcd 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,6 @@ "dependencies": { "@radix-ui/react-accordion": "^1.2.4", "@radix-ui/react-dialog": "^1.1.7", - "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-icons": "^1.3.2", "@radix-ui/react-popover": "^1.1.7", "@radix-ui/react-select": "^2.1.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2fae401..96894a1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -14,9 +14,6 @@ importers: '@radix-ui/react-dialog': specifier: ^1.1.7 version: 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-dropdown-menu': - specifier: ^2.1.16 - version: 2.1.16(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-icons': specifier: ^1.3.2 version: 1.3.2(react@18.3.1) @@ -372,9 +369,6 @@ packages: '@radix-ui/primitive@1.1.2': resolution: {integrity: sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==} - '@radix-ui/primitive@1.1.3': - resolution: {integrity: sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==} - '@radix-ui/react-accordion@1.2.4': resolution: {integrity: sha512-SGCxlSBaMvEzDROzyZjsVNzu9XY5E28B3k8jOENyrz6csOv/pG1eHyYfLJai1n9tRjwG61coXDhfpgtxKxUv5g==} peerDependencies: @@ -401,19 +395,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-arrow@1.1.7': - resolution: {integrity: sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-collapsible@1.1.4': resolution: {integrity: sha512-u7LCw1EYInQtBNLGjm9nZ89S/4GcvX1UR5XbekEgnQae2Hkpq39ycJ1OhdeN1/JDfVNG91kWaWoest127TaEKQ==} peerDependencies: @@ -440,19 +421,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-collection@1.1.7': - resolution: {integrity: sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-compose-refs@1.0.1': resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -537,19 +505,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dismissable-layer@1.1.11': - resolution: {integrity: sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-dismissable-layer@1.1.6': resolution: {integrity: sha512-7gpgMT2gyKym9Jz2ZhlRXSg2y6cNQIK8d/cqBZ0RBCaps8pFryCWXiUKI+uHGFrhMrbGUP7U6PWgiXzIxoyF3Q==} peerDependencies: @@ -563,19 +518,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-dropdown-menu@2.1.16': - resolution: {integrity: sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-focus-guards@1.0.1': resolution: {integrity: sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA==} peerDependencies: @@ -594,15 +536,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-focus-guards@1.1.3': - resolution: {integrity: sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-focus-scope@1.0.4': resolution: {integrity: sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA==} peerDependencies: @@ -629,19 +562,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-focus-scope@1.1.7': - resolution: {integrity: sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-icons@1.3.2': resolution: {integrity: sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==} peerDependencies: @@ -665,19 +585,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-menu@2.1.16': - resolution: {integrity: sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-popover@1.1.7': resolution: {integrity: sha512-I38OYWDmJF2kbO74LX8UsFydSHWOJuQ7LxPnTefjxxvdvPLempvAnmsyX9UsBlywcbSGpRH7oMLfkUf+ij4nrw==} peerDependencies: @@ -704,19 +611,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-popper@1.2.8': - resolution: {integrity: sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-portal@1.0.4': resolution: {integrity: sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q==} peerDependencies: @@ -743,19 +637,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-portal@1.1.9': - resolution: {integrity: sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-presence@1.0.1': resolution: {integrity: sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg==} peerDependencies: @@ -782,19 +663,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-presence@1.1.5': - resolution: {integrity: sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-primitive@1.0.3': resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} peerDependencies: @@ -821,32 +689,6 @@ packages: '@types/react-dom': optional: true - '@radix-ui/react-primitive@2.1.3': - resolution: {integrity: sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - - '@radix-ui/react-roving-focus@1.1.11': - resolution: {integrity: sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==} - peerDependencies: - '@types/react': '*' - '@types/react-dom': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@types/react-dom': - optional: true - '@radix-ui/react-select@2.1.7': resolution: {integrity: sha512-exzGIRtc7S8EIM2KjFg+7lJZsH7O7tpaBaJbBNVDnOZNhtoQ2iV+iSNfi2Wth0m6h3trJkMVvzAehB3c6xj/3Q==} peerDependencies: @@ -891,15 +733,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-slot@1.2.3': - resolution: {integrity: sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-switch@1.1.4': resolution: {integrity: sha512-zGP6W8plLeogoeGMiTHJ/uvf+TE1C2chVsEwfP8YlvpQKJHktG+iCkUtCLGPAuDV8/qDSmIRPm4NggaTxFMVBQ==} peerDependencies: @@ -949,24 +782,6 @@ packages: '@types/react': optional: true - '@radix-ui/react-use-controllable-state@1.2.2': - resolution: {integrity: sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - - '@radix-ui/react-use-effect-event@0.0.2': - resolution: {integrity: sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==} - peerDependencies: - '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc - peerDependenciesMeta: - '@types/react': - optional: true - '@radix-ui/react-use-escape-keydown@1.0.3': resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} peerDependencies: @@ -3702,8 +3517,6 @@ snapshots: '@radix-ui/primitive@1.1.2': {} - '@radix-ui/primitive@1.1.3': {} - '@radix-ui/react-accordion@1.2.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -3730,15 +3543,6 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-collapsible@1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -3767,18 +3571,6 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-collection@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-compose-refs@1.0.1(@types/react@18.3.20)(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -3870,19 +3662,6 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-dismissable-layer@1.1.6(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -3896,21 +3675,6 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-focus-guards@1.0.1(@types/react@18.3.20)(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -3924,12 +3688,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.20 - '@radix-ui/react-focus-guards@1.1.3(@types/react@18.3.20)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.20 - '@radix-ui/react-focus-scope@1.0.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -3953,17 +3711,6 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-icons@1.3.2(react@18.3.1)': dependencies: react: 18.3.1 @@ -3983,32 +3730,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.20 - '@radix-ui/react-menu@2.1.16(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - aria-hidden: 1.2.4 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.6.3(@types/react@18.3.20)(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-popover@1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -4050,24 +3771,6 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-popper@1.2.8(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@floating-ui/react-dom': 2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/rect': 1.1.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-portal@1.0.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -4088,16 +3791,6 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-portal@1.1.9(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-presence@1.0.1(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -4119,16 +3812,6 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-presence@1.1.5(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-primitive@1.0.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -4148,32 +3831,6 @@ snapshots: '@types/react': 18.3.20 '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-primitive@2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - - '@radix-ui/react-roving-focus@1.1.11(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.20 - '@types/react-dom': 18.3.6(@types/react@18.3.20) - '@radix-ui/react-select@2.1.7(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/number': 1.1.1 @@ -4227,13 +3884,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.20 - '@radix-ui/react-slot@1.2.3(@types/react@18.3.20)(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.20 - '@radix-ui/react-switch@1.1.4(@types/react-dom@18.3.6(@types/react@18.3.20))(@types/react@18.3.20)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@radix-ui/primitive': 1.1.2 @@ -4277,21 +3927,6 @@ snapshots: optionalDependencies: '@types/react': 18.3.20 - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.20)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.20)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.20 - - '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.20)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.20)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.20 - '@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.3.20)(react@18.3.1)': dependencies: '@babel/runtime': 7.27.0 @@ -5205,8 +4840,8 @@ snapshots: '@typescript-eslint/parser': 8.30.1(eslint@8.57.1)(typescript@5.8.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1) - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@8.57.1) eslint-plugin-jsx-a11y: 6.10.2(eslint@8.57.1) eslint-plugin-react: 7.37.5(eslint@8.57.1) eslint-plugin-react-hooks: 5.0.0-canary-7118f5dd7-20230705(eslint@8.57.1) @@ -5225,7 +4860,7 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1): + eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1): dependencies: '@nolyfill/is-core-module': 1.0.39 debug: 4.4.0 @@ -5236,22 +4871,22 @@ snapshots: tinyglobby: 0.2.12 unrs-resolver: 1.5.0 optionalDependencies: - eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: '@typescript-eslint/parser': 8.30.1(eslint@8.57.1)(typescript@5.8.3) eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1) + eslint-import-resolver-typescript: 3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1) transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-typescript@3.10.0)(eslint@8.57.1): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.8 @@ -5262,7 +4897,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint@8.57.1))(eslint@8.57.1))(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@8.30.1(eslint@8.57.1)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.10.0(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 diff --git a/src/components/Navbar.tsx b/src/components/Navbar.tsx index f640cc7..6ce6598 100644 --- a/src/components/Navbar.tsx +++ b/src/components/Navbar.tsx @@ -1,58 +1,46 @@ "use client"; -import { useState, useEffect } from "react"; +import { useState, useRef, useEffect } from "react"; import Image 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 { Button } from "@/components/ui/button"; +import { ArrowDownLeftIcon, Pin, ArrowUpRight } from "lucide-react"; +import NavDropdownButton from "./NavDropdownButton"; import FloatingNavbar from "./FloatingNavbar"; import PWAInstallButton from "./ui/PWAInstallButton"; -import SearchBarChild from "./Searchbar/searchbar-child"; -import { - DropdownMenu, - DropdownMenuTrigger, - DropdownMenuContent, - DropdownMenuItem, -} from "@/components/ui/dropdown-menu"; function Navbar() { const pathname = usePathname(); - const [subjects, setSubjects] = useState([]); - const [dropdownOpen, setDropdownOpen] = useState(false); + const [open, setOpen] = useState(false); + const dropdownContainerRef = useRef(null); useEffect(() => { - async function getSubjects() { - const res = await fetch("/api/course-list"); - const data = await res.json(); - setSubjects(data.map((course: { name: string }) => course.name)); + function handleClickOutside(event: MouseEvent) { + if ( + dropdownContainerRef.current && + !dropdownContainerRef.current.contains(event.target as Node) + ) { + setOpen(false); + } } - if (pathname === "/catalogue") getSubjects(); - }, [pathname]); - const renderHomePageButtons = () => ( - <> - -
- - Pinned Subjects -
- - -
- - Paper Request -
- - - ); + if (open) { + document.addEventListener("mousedown", handleClickOutside); + } + + return () => { + document.removeEventListener("mousedown", handleClickOutside); + }; + }, [open]); return (
-
- +
+ codechef-logo - {pathname === "/catalogue" ? ( -
- - - - - - - - - - Pinned Subjects - - - - - - Paper Request - - - - -
- ) : ( -
- {renderHomePageButtons()} -
- )} -
- - {pathname === "/catalogue" && ( -
-
- +
+ +
+ + Pinned Subjects +
+ +
+ +
+ + Paper Request +
+
- )} + + {/* Desktop: Create Paper Request button */} +
+
+ -
+
{pathname === "/upload" ? "Search Papers" : "Upload Papers"} @@ -135,8 +95,19 @@ function Navbar() {
-
- { }} /> + {/* Mobile: Create Paper Request button inside dropdown */} +
+ setOpen((prev) => !prev)} + /> +
+ setOpen(false)} /> +
diff --git a/src/components/ui/dropdown-menu.tsx b/src/components/ui/dropdown-menu.tsx deleted file mode 100644 index 4fc75b2..0000000 --- a/src/components/ui/dropdown-menu.tsx +++ /dev/null @@ -1,200 +0,0 @@ -"use client" - -import * as React from "react" -import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" -import { cn } from "@/lib/utils" -import { CheckIcon, ChevronRightIcon, DotFilledIcon } from "@radix-ui/react-icons" - -const DropdownMenu = DropdownMenuPrimitive.Root - -const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger - -const DropdownMenuGroup = DropdownMenuPrimitive.Group - -const DropdownMenuPortal = DropdownMenuPrimitive.Portal - -const DropdownMenuSub = DropdownMenuPrimitive.Sub - -const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup - -const DropdownMenuSubTrigger = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, children, ...props }, ref) => ( - - {children} - - -)) -DropdownMenuSubTrigger.displayName = - DropdownMenuPrimitive.SubTrigger.displayName - -const DropdownMenuSubContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DropdownMenuSubContent.displayName = - DropdownMenuPrimitive.SubContent.displayName - -const DropdownMenuContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - - - -)) -DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName - -const DropdownMenuItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - svg]:size-4 [&>svg]:shrink-0", - inset && "pl-8", - className - )} - {...props} - /> -)) -DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName - -const DropdownMenuCheckboxItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, checked, ...props }, ref) => ( - - - - - - - {children} - -)) -DropdownMenuCheckboxItem.displayName = - DropdownMenuPrimitive.CheckboxItem.displayName - -const DropdownMenuRadioItem = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, children, ...props }, ref) => ( - - - - - - - {children} - -)) -DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName - -const DropdownMenuLabel = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef & { - inset?: boolean - } ->(({ className, inset, ...props }, ref) => ( - -)) -DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName - -const DropdownMenuSeparator = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, ...props }, ref) => ( - -)) -DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName - -const DropdownMenuShortcut = ({ - className, - ...props -}: React.HTMLAttributes) => { - return ( - - ) -} -DropdownMenuShortcut.displayName = "DropdownMenuShortcut" - -export { - DropdownMenu, - DropdownMenuTrigger, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuCheckboxItem, - DropdownMenuRadioItem, - DropdownMenuLabel, - DropdownMenuSeparator, - DropdownMenuShortcut, - DropdownMenuGroup, - DropdownMenuPortal, - DropdownMenuSub, - DropdownMenuSubContent, - DropdownMenuSubTrigger, - DropdownMenuRadioGroup, -}