11"use client" ;
22
3- import { useState , useRef , useEffect } from "react" ;
4- import Image from "next/image" ;
3+ import { useState , useEffect } from "react" ;
4+ import Image , { StaticImageData } from "next/image" ;
55import Link from "next/link" ;
66import { usePathname } from "next/navigation" ;
77import ccLogo from "../assets/codechef_logo.svg" ;
88import ModeToggle from "@/components/toggle-theme" ;
9- import { Button } from "@/components/ui/button" ;
10- import { ArrowDownLeftIcon , Pin , ArrowUpRight } from "lucide-react" ;
11- import NavDropdownButton from "./NavDropdownButton" ;
9+ import { ArrowDownLeftIcon , Pin , ArrowUpRight , ChevronDown } from "lucide-react" ;
1210import FloatingNavbar from "./FloatingNavbar" ;
1311import PWAInstallButton from "./ui/PWAInstallButton" ;
12+ import SearchBarChild from "./Searchbar/searchbar-child" ;
13+ import type { ICourses } from "@/interface" ;
14+ import {
15+ DropdownMenu ,
16+ DropdownMenuTrigger ,
17+ DropdownMenuContent ,
18+ DropdownMenuItem ,
19+ } from "@/components/ui/dropdown-menu" ;
1420
1521function Navbar ( ) {
16- const pathname = usePathname ( ) ;
17- const [ open , setOpen ] = useState ( false ) ;
18- const dropdownContainerRef = useRef < HTMLDivElement > ( null ) ;
22+ const pathname : string = usePathname ( ) ?? "/" ;
23+ const [ subjects , setSubjects ] = useState < string [ ] > ( [ ] ) ;
24+ const [ dropdownOpen , setDropdownOpen ] = useState < boolean > ( false ) ;
1925
2026 useEffect ( ( ) => {
21- function handleClickOutside ( event : MouseEvent ) {
22- if (
23- dropdownContainerRef . current &&
24- ! dropdownContainerRef . current . contains ( event . target as Node )
25- ) {
26- setOpen ( false ) ;
27- }
28- }
27+ if ( pathname !== "/catalogue" ) return ;
28+
29+ const getSubjects = async ( ) => {
30+ try {
31+ const res = await fetch ( "/api/course-list" ) ;
32+ if ( ! res . ok ) return ;
2933
30- if ( open ) {
31- document . addEventListener ( "mousedown" , handleClickOutside ) ;
32- }
34+ const json : unknown = await res . json ( ) ;
3335
34- return ( ) => {
35- document . removeEventListener ( "mousedown" , handleClickOutside ) ;
36+ if ( Array . isArray ( json ) ) {
37+ const filtered = json
38+ . filter ( ( item ) : item is ICourses => typeof item === "object" && item !== null && "name" in item )
39+ . map ( item => item . name ) ;
40+ setSubjects ( filtered ) ;
41+ } else {
42+ console . error ( "Invalid data returned from API:" , json ) ;
43+ }
44+ } catch ( err ) {
45+ console . error ( "Failed to fetch courses" , err ) ;
46+ }
3647 } ;
37- } , [ open ] ) ;
48+
49+ void getSubjects ( ) ;
50+ } , [ pathname ] ) ;
51+
52+ const renderHomePageButtons = ( ) => (
53+ < >
54+ < Link href = "/pinned" className = "ml-2" >
55+ < div className = "flex items-center gap-2 rounded-full border bg-[#e8e9ff] dark:bg-black border-[#3A3745] px-4 py-2 text-sm font-semibold dark:text-white transition hover:bg-slate-50 text-gray-700 dark:hover:bg-[#1A1823] h-10" >
56+ < Pin className = "h-4 w-4" />
57+ Pinned Subjects
58+ </ div >
59+ </ Link >
60+ < Link href = "/request" className = "ml-2" >
61+ < div className = "flex items-center gap-2 rounded-full border bg-[#e8e9ff] dark:bg-black border-[#3A3745] px-4 py-2 text-sm font-semibold dark:text-white transition hover:bg-slate-50 text-gray-700 dark:hover:bg-[#1A1823] h-10" >
62+ < ArrowUpRight className = "h-4 w-4" />
63+ Paper Request
64+ </ div >
65+ </ Link >
66+ </ >
67+ ) ;
3868
3969 return (
4070 < div className = "sticky top-0 z-10 w-full bg-[#B2B8FF] px-4 py-4 dark:bg-[#130E1F] md:px-8 md:py-5" >
4171 < div className = "flex items-center justify-between" >
42- < div className = "flex items-center gap-4" >
43- < Link href = "https://www.codechefvit.com/" target = "_blank" >
44- < Image
45- src = { ccLogo as HTMLImageElement }
46- alt = "codechef-logo"
47- height = { 60 }
48- width = { 60 }
49- />
72+ { }
73+ < div className = "flex items-center gap-4 relative" >
74+ < Link href = "https://www.codechefvit.com/" target = "_blank" >
75+ < Image src = { ccLogo as StaticImageData } alt = "codechef-logo" height = { 60 } width = { 60 } />
5076 </ Link >
5177
5278 < Link
@@ -56,62 +82,76 @@ function Navbar() {
5682 Papers
5783 </ Link >
5884
59- < div className = "mt-3 hidden md:flex" >
60- < Link href = "/pinned" >
61- < div className = "ml-2 flex items-center gap-2 rounded-full border bg-[#e8e9ff] dark:bg-black border-[#3A3745] px-4 py-2 text-sm font-semibold dark:text-white transition hover:bg-slate-50 text-gray-700 dark:hover:bg-[#1A1823]" >
62- < Pin className = "h-4 w-4" />
63- Pinned Subjects
64- </ div >
65- </ Link >
66- < div className = "ml-2 hidden md:flex" >
67- < Link href = "/request" >
68- < div className = "ml-2 flex items-center gap-2 rounded-full border bg-[#e8e9ff] dark:bg-black border-[#3A3745] px-4 py-2 text-sm font-semibold dark:text-white transition hover:bg-slate-50 text-gray-700 dark:hover:bg-[#1A1823]" >
69- < ArrowUpRight className = "h-4 w-4" />
70- Paper Request
71- </ div >
72- </ Link >
73- </ div >
74- </ div >
85+ { pathname === "/catalogue" ? (
86+ < div className = "ml-4 hidden md:block relative" >
87+ < DropdownMenu open = { dropdownOpen } onOpenChange = { setDropdownOpen } >
88+ < DropdownMenuTrigger asChild >
89+ < button
90+ className = "flex h-10 w-10 items-center justify-center rounded-full bg-[#4B22D1] text-white shadow-lg transition-transform duration-200 hover:scale-105 active:scale-95"
91+ aria-label = "Toggle dropdown"
92+ >
93+ < ChevronDown
94+ className = { `h-5 w-5 transition-transform duration-200 ${ dropdownOpen ? "rotate-180" : "" } ` }
95+ />
96+ </ button >
97+ </ DropdownMenuTrigger >
7598
76- { /* Desktop: Create Paper Request button */ }
99+ < DropdownMenuContent
100+ className = "w-56 rounded-2xl bg-[#4B22D1] text-white border border-[rgba(255,255,255,0.1)] shadow-2xl backdrop-blur-sm"
101+ align = "start"
102+ >
103+ < DropdownMenuItem asChild >
104+ < Link href = "/pinned" className = "flex items-center gap-3" >
105+ < Pin className = "h-4 w-4" />
106+ < span className = "font-medium" > Pinned Subjects</ span >
107+ </ Link >
108+ </ DropdownMenuItem >
109+ < DropdownMenuItem asChild >
110+ < Link href = "/request" className = "flex items-center gap-3" >
111+ < ArrowUpRight className = "h-4 w-4" />
112+ < span className = "font-medium" > Paper Request</ span >
113+ </ Link >
114+ </ DropdownMenuItem >
115+ </ DropdownMenuContent >
116+ </ DropdownMenu >
117+ </ div >
118+ ) : (
119+ < div className = "hidden md:flex items-center h-10" > { renderHomePageButtons ( ) } </ div >
120+ ) }
77121 </ div >
78122
123+ { }
124+ { pathname === "/catalogue" && (
125+ < div className = "hidden md:flex flex-1 justify-center mx-4" >
126+ < div className = "w-full max-w-[700px]" >
127+ < SearchBarChild initialSubjects = { subjects } />
128+ </ div >
129+ </ div >
130+ ) }
131+
132+ { }
79133 < div className = "hidden items-center gap-4 md:flex" >
80134 < div className = "rounded-full border border-[#3A3745] p-1" >
81135 < ModeToggle />
82136 </ div >
83-
84137 < div className = "hidden max-w-[200px] md:block" >
85138 < PWAInstallButton />
86139 </ div >
87-
88140 < Link href = { pathname === "/upload" ? "/" : "/upload" } >
89- < div className = "flex items-center gap-2 rounded-full border bg-[#e8e9ff] dark:bg-black border-[#3A3745] px-4 py-2 text-sm font-semibold dark:text-white transition hover:bg-slate-50 text-gray-700 dark:hover:bg-[#1A1823]" >
141+ < div className = "flex items-center gap-2 rounded-full border bg-[#e8e9ff] dark:bg-black border-[#3A3745] px-4 py-2 text-sm font-semibold dark:text-white transition hover:bg-slate-50 text-gray-700 dark:hover:bg-[#1A1823] h-10 " >
90142 < ArrowDownLeftIcon className = "h-4 w-4 rotate-90" />
91- < span >
92- { pathname === "/upload" ? "Search Papers" : "Upload Papers" }
93- </ span >
143+ < span > { pathname === "/upload" ? "Search Papers" : "Upload Papers" } </ span >
94144 </ div >
95145 </ Link >
96146 </ div >
97147
98- { /* Mobile: Create Paper Request button inside dropdown */ }
99- < div className = "md:hidden" ref = { dropdownContainerRef } >
100- < NavDropdownButton
101- isOpen = { open }
102- onClick = { ( ) => setOpen ( ( prev ) => ! prev ) }
103- />
104- < div
105- className = { `transition-all duration-300 ease-in-out ${
106- open ? "block" : "hidden"
107- } `}
108- >
109- < FloatingNavbar onNavigate = { ( ) => setOpen ( false ) } />
110- </ div >
148+ { }
149+ < div className = "md:hidden" >
150+ < FloatingNavbar onNavigate = { ( ) => void 0 } />
111151 </ div >
112152 </ div >
113153 </ div >
114154 ) ;
115155}
116156
117- export default Navbar ;
157+ export default Navbar ;
0 commit comments