1- import React from 'react' ;
1+ import React , { useState , useEffect } from 'react' ;
22import Link from 'next/link' ;
33import { usePathname } from 'next/navigation' ;
44import NewHeader from '@/components/NewHeader' ;
5+ import { useHeaderContext } from '../app/context/CrateContext' ;
6+ import Image from 'next/image' ;
57
68interface CrateNavProps {
79 nsfront : string ;
@@ -13,6 +15,10 @@ interface CrateNavProps {
1315const CrateNav : React . FC < CrateNavProps > = ( { nsfront, nsbehind, name, version } ) => {
1416 const pathname = usePathname ( ) ;
1517 const basePath = `/${ nsfront } /${ nsbehind } /${ name } /${ version } ` ;
18+ const [ isOpen , setIsOpen ] = useState ( false ) ;
19+ const [ currentVersion , setCurrentVersion ] = useState ( version ) ;
20+ const [ searchTerm , setSearchTerm ] = useState ( '' ) ;
21+ const { crateData, setCrateData } = useHeaderContext ( ) ;
1622
1723 const navItems = [
1824 { name : 'Overview' , path : '' } ,
@@ -21,32 +27,114 @@ const CrateNav: React.FC<CrateNavProps> = ({ nsfront, nsbehind, name, version })
2127 { name : 'Versions' , path : '/versions' } ,
2228 ] ;
2329
30+ useEffect ( ( ) => {
31+ const fetchData = async ( ) => {
32+ if ( ! crateData . results ) {
33+ const response = await fetch ( `/api/crates/${ nsfront } /${ nsbehind } /${ name } /${ version } ` ) ;
34+ const data = await response . json ( ) ;
35+ setCrateData ( {
36+ crateName : data . crate_name ,
37+ crateVersion : version ,
38+ results : data ,
39+ } ) ;
40+ }
41+ } ;
42+
43+ fetchData ( ) ;
44+ } , [ nsfront , nsbehind , name , version , setCrateData , crateData . results ] ) ;
45+
2446 const isActive = ( path : string ) => {
2547 if ( path === '' ) {
2648 return pathname === basePath ;
2749 }
2850 return pathname === `${ basePath } ${ path } ` ;
2951 } ;
3052
53+ const toggleDropdown = ( ) => {
54+ setIsOpen ( ( prev ) => ! prev ) ;
55+ } ;
56+
57+ const closeDropdown = ( ) => {
58+ setIsOpen ( false ) ;
59+ } ;
60+
3161 return (
3262 < div >
3363 < NewHeader />
34- < nav className = "border-b border-gray-200 mb-4" >
35- < div className = "flex space-x-8 px-4" >
36- { navItems . map ( ( item ) => (
37- < Link
38- key = { item . name }
39- href = { `${ basePath } ${ item . path } ` }
40- className = { `py-4 px-2 border-b-2 ${ isActive ( item . path )
41- ? 'border-blue-500 text-blue-500'
42- : 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
43- } `}
44- >
45- { item . name }
46- </ Link >
47- ) ) }
64+ < div className = "flex justify-center px-4 py-6" >
65+ < div className = "w-[1500px] h-[120px] bg-white rounded-2xl shadow-[0_0_12px_0_rgba(43,88,221,0.09)] px-8" >
66+ < div className = "flex items-center justify-between h-16" >
67+ < div className = "flex items-center space-x-4" >
68+ < h1 className = "text-2xl font-semibold" style = { { color : 'rgb(28, 63, 115)' } } > { name } </ h1 >
69+ < div className = "relative" >
70+ < button
71+ onClick = { toggleDropdown }
72+ className = "flex items-center justify-between w-[150px] h-[36px] flex-shrink-0 rounded-[18.5px] border border-[#333333] bg-white px-4"
73+ >
74+ < span > { currentVersion || 'Select Version' } </ span >
75+ < Image
76+ src = { isOpen ? "/images/homepage/verison-up.png" : "/images/homepage/version-down.png" }
77+ alt = "version"
78+ width = { 16 }
79+ height = { 16 }
80+ />
81+ </ button >
82+ { isOpen && (
83+ < div className = "absolute mt-1 w-full z-50" >
84+ < div className = "fixed inset-0" onClick = { closeDropdown } > </ div >
85+ < div className = "relative w-[150px] h-[196px] flex-shrink-0 rounded-[16px] bg-white border border-gray-300 shadow-lg" >
86+ < div className = "p-2 border-b border-gray-100" >
87+ < input
88+ type = "text"
89+ value = { searchTerm }
90+ onChange = { ( e ) => setSearchTerm ( e . target . value ) }
91+ className = "w-[125px] h-[30px] flex-shrink-0 rounded-[9.5px] bg-white focus:bg-[#E2E9FF] border border-[#E5E5E5] focus:outline-none px-2"
92+ />
93+ </ div >
94+ < ul className = "max-h-[150px] overflow-y-auto [&::-webkit-scrollbar]:hidden [-ms-overflow-style:none] [scrollbar-width:none] [&:hover::-webkit-scrollbar]:block [&:hover::-webkit-scrollbar]:w-1 [&:hover::-webkit-scrollbar-thumb]:bg-gray-300 [&:hover::-webkit-scrollbar-track]:bg-transparent" >
95+ { crateData . results ?. versions
96+ . filter ( version => version . toLowerCase ( ) . includes ( searchTerm . toLowerCase ( ) ) )
97+ . map ( ( version , index ) => (
98+ < Link
99+ key = { index }
100+ onClick = { ( ) => {
101+ setCurrentVersion ( version ) ;
102+ setSearchTerm ( '' ) ;
103+ closeDropdown ( ) ;
104+ } }
105+ href = { `/${ nsfront } /${ nsbehind } /${ crateData . results ?. crate_name } /${ version } ` }
106+ >
107+ < li className = "px-4 py-2 hover:bg-[#E2E9FF] cursor-pointer" >
108+ { version }
109+ </ li >
110+ </ Link >
111+ ) ) }
112+ </ ul >
113+ </ div >
114+ </ div >
115+ ) }
116+ </ div >
117+ </ div >
118+ </ div >
119+ < nav className = "flex space-x-8" >
120+ { navItems . map ( ( item ) => (
121+ < Link
122+ key = { item . name }
123+ href = { `${ basePath } ${ item . path } ` }
124+ className = { `py-4 px-2 relative font-['HarmonyOS_Sans_SC'] text-center min-w-[108px] ${ isActive ( item . path )
125+ ? 'text-blue-500'
126+ : 'text-gray-500 hover:text-gray-700'
127+ } `}
128+ >
129+ { item . name }
130+ { isActive ( item . path ) && (
131+ < div className = "absolute bottom-0 left-1/2 -translate-x-1/2 w-[108px] h-[4px] flex-shrink-0 rounded-t-[3px] bg-[#4B68FF]" > </ div >
132+ ) }
133+ </ Link >
134+ ) ) }
135+ </ nav >
48136 </ div >
49- </ nav >
137+ </ div >
50138 </ div >
51139 ) ;
52140} ;
0 commit comments