1
- import React from 'react' ;
1
+ import React , { useState , useEffect } from 'react' ;
2
2
import Link from 'next/link' ;
3
3
import { usePathname } from 'next/navigation' ;
4
4
import NewHeader from '@/components/NewHeader' ;
5
+ import { useHeaderContext } from '../app/context/CrateContext' ;
6
+ import Image from 'next/image' ;
5
7
6
8
interface CrateNavProps {
7
9
nsfront : string ;
@@ -13,6 +15,10 @@ interface CrateNavProps {
13
15
const CrateNav : React . FC < CrateNavProps > = ( { nsfront, nsbehind, name, version } ) => {
14
16
const pathname = usePathname ( ) ;
15
17
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 ( ) ;
16
22
17
23
const navItems = [
18
24
{ name : 'Overview' , path : '' } ,
@@ -21,32 +27,114 @@ const CrateNav: React.FC<CrateNavProps> = ({ nsfront, nsbehind, name, version })
21
27
{ name : 'Versions' , path : '/versions' } ,
22
28
] ;
23
29
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
+
24
46
const isActive = ( path : string ) => {
25
47
if ( path === '' ) {
26
48
return pathname === basePath ;
27
49
}
28
50
return pathname === `${ basePath } ${ path } ` ;
29
51
} ;
30
52
53
+ const toggleDropdown = ( ) => {
54
+ setIsOpen ( ( prev ) => ! prev ) ;
55
+ } ;
56
+
57
+ const closeDropdown = ( ) => {
58
+ setIsOpen ( false ) ;
59
+ } ;
60
+
31
61
return (
32
62
< div >
33
63
< 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 >
48
136
</ div >
49
- </ nav >
137
+ </ div >
50
138
</ div >
51
139
) ;
52
140
} ;
0 commit comments